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    }