001 package com.oxygenxml.validate.nvdl; 002 003 import org.xml.sax.Attributes; 004 005 /** 006 * Implementation of the Attributes interface that filters out some of the 007 * attributes of an actual Attributes implementation. We will keep only the 008 * attributes whose indexes are specified in a given set of indexes. 009 */ 010 class FilteredAttributes implements Attributes { 011 /** 012 * The actual attributes, we will filter out some of them. 013 */ 014 private final Attributes attributes; 015 016 /** 017 * The set of indexes of the attributes to used. 018 */ 019 private final IntSet indexSet; 020 021 /** 022 * Maps indexes in the real attributes list to 1 based indexes in the 023 * filtered attributes list. For instance if we keep only the 024 * 1st and the 3rd attributes from 4 attributes then the 025 * reverse index map will have as values 026 * [0] --> 1 027 * [1] --> 0 028 * [2] --> 2 029 * [3] --> 0 030 * 031 */ 032 private int[] reverseIndexMap; 033 034 /** 035 * Creates a filtered attributes instance. 036 * @param indexSet The set with indexes that we will keep. 037 * @param attributes The actual attributes. 038 */ 039 public FilteredAttributes(IntSet indexSet, Attributes attributes) { 040 this.indexSet = indexSet; 041 this.attributes = attributes; 042 } 043 044 /** 045 * Gets the index in the filtered set for a given real index. 046 * If the reverseIndexMap is not computed it computes it, 047 * otherwise it just uses the previously computed map. 048 * @param k The index in the real attributes. 049 * @return The index in the filtered attributes. 050 */ 051 private int reverseIndex(int k) { 052 if (reverseIndexMap == null) { 053 reverseIndexMap = new int[attributes.getLength()]; 054 for (int i = 0, len = indexSet.size(); i < len; i++) 055 reverseIndexMap[indexSet.get(i)] = i + 1; 056 } 057 return reverseIndexMap[k] - 1; 058 } 059 060 /** 061 * The number of attributes, the same as the length of the list of indexes. 062 */ 063 public int getLength() { 064 return indexSet.size(); 065 } 066 067 /** 068 * Get the URI for the index-th attribute. 069 */ 070 public String getURI(int index) { 071 if (index < 0 || index >= indexSet.size()) 072 return null; 073 return attributes.getURI(indexSet.get(index)); 074 } 075 076 /** 077 * Get the local name for the index-th attribute. 078 */ 079 public String getLocalName(int index) { 080 if (index < 0 || index >= indexSet.size()) 081 return null; 082 return attributes.getLocalName(indexSet.get(index)); 083 } 084 085 /** 086 * Get the QName for the index-th attribute. 087 */ 088 public String getQName(int index) { 089 if (index < 0 || index >= indexSet.size()) 090 return null; 091 return attributes.getQName(indexSet.get(index)); 092 } 093 094 /** 095 * Get the type for the index-th attribute. 096 */ 097 public String getType(int index) { 098 if (index < 0 || index >= indexSet.size()) 099 return null; 100 return attributes.getType(indexSet.get(index)); 101 } 102 103 /** 104 * Get the value for the index-th attribute. 105 */ 106 public String getValue(int index) { 107 if (index < 0 || index >= indexSet.size()) 108 return null; 109 return attributes.getValue(indexSet.get(index)); 110 } 111 112 public int getIndex(String uri, String localName) { 113 int n = attributes.getIndex(uri, localName); 114 if (n < 0) 115 return n; 116 return reverseIndex(n); 117 } 118 119 public int getIndex(String qName) { 120 int n = attributes.getIndex(qName); 121 if (n < 0) 122 return n; 123 return reverseIndex(n); 124 } 125 126 /** 127 * Get the real index, in the initial attributes list of a given attribute. 128 * If the attribute is filtered out then return -1. 129 * @param uri The attribute uri. 130 * @param localName The attribute local name. 131 * @return The real index if the attribute is present and not filtered out, otherwise -1. 132 */ 133 private int getRealIndex(String uri, String localName) { 134 int index = attributes.getIndex(uri, localName); 135 if (index < 0 || reverseIndex(index) < 0) 136 return -1; 137 return index; 138 } 139 140 /** 141 * Get the real index, in the initial attributes list of a given attribute. 142 * If the attribute is filtered out then return -1. 143 * @param qName The attribute qualified name. 144 * @return The real index if the attribute is present and not filtered out, otherwise -1. 145 */ 146 private int getRealIndex(String qName) { 147 int index = attributes.getIndex(qName); 148 if (index < 0 || reverseIndex(index) < 0) 149 return -1; 150 return index; 151 } 152 153 /** 154 * Get the type of the attribute. 155 * @param uri The attribute uri. 156 * @param localName The attribute local name. 157 */ 158 public String getType(String uri, String localName) { 159 return attributes.getType(getRealIndex(uri, localName)); 160 } 161 162 /** 163 * Get the value of the attribute. 164 * @param uri The attribute uri. 165 * @param localName The attribute local name. 166 */ 167 public String getValue(String uri, String localName) { 168 return attributes.getValue(getRealIndex(uri, localName)); 169 } 170 171 /** 172 * Get the type of the attribute. 173 * @param qName The attribute qualified name. 174 */ 175 public String getType(String qName) { 176 return attributes.getType(getRealIndex(qName)); 177 } 178 179 /** 180 * Get the value of the attribute. 181 * @param qName The attribute qualified name. 182 */ 183 public String getValue(String qName) { 184 return attributes.getValue(getRealIndex(qName)); 185 } 186 }