001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200.bytecode;
018:
019: import java.util.ArrayList;
020: import java.util.Comparator;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.TreeSet;
024:
025: /**
026: * This class implements the special set (which is aware of
027: * domains) used when generating ClassConstantPools.
028: * It's called a Set, but isn't quite a Collection - it
029: * doesn't implement all the API required.
030: */
031: public class ClassPoolSet {
032:
033: class GeneralComparator implements Comparator {
034: /* (non-Javadoc)
035: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
036: */
037: public int compare(Object o1, Object o2) {
038: if (o1.equals(o2)) {
039: return 0;
040: }
041: return o1.getClass().getName().compareTo(
042: o2.getClass().getName());
043: }
044: }
045:
046: class PoolComparator extends GeneralComparator {
047: /* (non-Javadoc)
048: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
049: */
050: public int compare(Object o1, Object o2) {
051: int classCompare = super .compare(o1, o2);
052: if (classCompare != 0) {
053: return classCompare;
054: }
055: // If we compare anything other than ConstantPoolEntries
056: // with this comparator, it is an error.
057: ConstantPoolEntry cpe1 = (ConstantPoolEntry) o1;
058: ConstantPoolEntry cpe2 = (ConstantPoolEntry) o2;
059:
060: // Domains must be the same, need to compare
061: // based on comparisonString.
062: String compare1 = cpe1.comparisonString();
063: String compare2 = cpe2.comparisonString();
064: return compare1.compareTo(compare2);
065: }
066: }
067:
068: class SignatureAsciizComparator extends GeneralComparator {
069: /* (non-Javadoc)
070: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
071: */
072: public int compare(Object o1, Object o2) {
073: int classCompare = super .compare(o1, o2);
074: if (classCompare != 0) {
075: return classCompare;
076: }
077:
078: // Now that we've reached this point, we're
079: // comparing objects of the same class. Since
080: // they have the same class, we can make the
081: // statement that they're UTF8s, since only
082: // UTF8s will be added to a TreeSet with
083: // the SignatureAsciizComparator.
084: CPUTF8 cpe1 = (CPUTF8) o1;
085: CPUTF8 cpe2 = (CPUTF8) o2;
086:
087: String compare1 = cpe1.signatureComparisonString();
088: String compare2 = cpe2.signatureComparisonString();
089: return compare1.compareTo(compare2);
090: }
091: }
092:
093: class NormalAsciizComparator extends GeneralComparator {
094: /* (non-Javadoc)
095: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
096: */
097: public int compare(Object o1, Object o2) {
098: int classCompare = super .compare(o1, o2);
099: if (classCompare != 0) {
100: return classCompare;
101: }
102:
103: // Now that we've reached this point, we're
104: // comparing objects of the same class. Since
105: // they have the same class, we can make the
106: // statement that they're UTF8s, since only
107: // UTF8s will be added to a TreeSet with
108: // the NormalAsciizComparator.
109: CPUTF8 cpe1 = (CPUTF8) o1;
110: CPUTF8 cpe2 = (CPUTF8) o2;
111:
112: String compare1 = cpe1.normalComparisonString();
113: String compare2 = cpe2.normalComparisonString();
114: return compare1.compareTo(compare2);
115: }
116: }
117:
118: protected Comparator[] comparators = new Comparator[ClassConstantPool.NUM_DOMAINS];
119: protected TreeSet[] sets = new TreeSet[ClassConstantPool.NUM_DOMAINS];
120:
121: public ClassPoolSet() {
122: // These are the comparators in numeric order.
123: comparators[ClassConstantPool.DOMAIN_UNDEFINED] = new PoolComparator();
124: comparators[ClassConstantPool.DOMAIN_INTEGER] = new PoolComparator();
125: comparators[ClassConstantPool.DOMAIN_FLOAT] = new PoolComparator();
126: comparators[ClassConstantPool.DOMAIN_STRING] = new PoolComparator();
127: comparators[ClassConstantPool.DOMAIN_NORMALASCIIZ] = new NormalAsciizComparator();
128: comparators[ClassConstantPool.DOMAIN_LONG] = new PoolComparator();
129: comparators[ClassConstantPool.DOMAIN_DOUBLE] = new PoolComparator();
130: comparators[ClassConstantPool.DOMAIN_CLASSREF] = new PoolComparator();
131: comparators[ClassConstantPool.DOMAIN_SIGNATUREASCIIZ] = new SignatureAsciizComparator();
132: comparators[ClassConstantPool.DOMAIN_NAMEANDTYPE] = new PoolComparator();
133: comparators[ClassConstantPool.DOMAIN_FIELD] = new PoolComparator();
134: comparators[ClassConstantPool.DOMAIN_METHOD] = new PoolComparator();
135: comparators[ClassConstantPool.DOMAIN_ATTRIBUTEASCIIZ] = new NormalAsciizComparator();
136:
137: for (int index = 0; index < ClassConstantPool.NUM_DOMAINS; index++) {
138: sets[index] = new TreeSet(comparators[index]);
139: }
140: }
141:
142: /**
143: * Answer the index of the first set which contains the entry
144: * passed in as the parameter.
145: * @param entry ConstantPoolEntry to test for (with .contains())
146: * @return int index of the first set containing the entry
147: */
148: protected int findFirstSetContaining(ConstantPoolEntry entry) {
149: for (int index = 0; index < ClassConstantPool.NUM_DOMAINS; index++) {
150: if (sets[index].contains(entry)) {
151: return index;
152: }
153: }
154: return -1;
155: }
156:
157: /**
158: * @param set
159: * @param testEntry
160: * @return
161: */
162: protected ConstantPoolEntry getStoredEntry(int set,
163: ConstantPoolEntry testEntry) {
164: TreeSet searchSet = sets[set];
165: Iterator iterator = searchSet.iterator();
166: while (iterator.hasNext()) {
167: ConstantPoolEntry storedEntry = (ConstantPoolEntry) iterator
168: .next();
169: if (0 == (comparators[set].compare(storedEntry, testEntry))) {
170: return storedEntry;
171: }
172: }
173: // Not found. Should not happen.
174: throw new Error(
175: "Tried to find a stored entry which wasn't in the set");
176: }
177:
178: /**
179: * Add the parameter to the receiver. If the parameter
180: * already exists in a higher precedence domain, answer
181: * that. If the parameter exists in a lower precedence
182: * domain, remove it from the lower domain and add it to
183: * the higher one.
184: *
185: * @param entry ConstantPoolEntry to add
186: * @return ConstantPoolEntry from the domain where it's stored
187: */
188: public ConstantPoolEntry add(Object entry) {
189: ConstantPoolEntry cpEntry = (ConstantPoolEntry) entry;
190: int entryDomain = cpEntry.getDomain();
191: int currentStoredDomain = findFirstSetContaining(cpEntry);
192:
193: if (currentStoredDomain < 0) {
194: // Entry is not currently stored; just store it.
195: sets[entryDomain].add(cpEntry);
196: return cpEntry;
197: }
198:
199: if (currentStoredDomain <= entryDomain) {
200: // Entry is either already in this place
201: // or in a higher-precedence (numerically lower)
202: // domain; answer the value in the stored
203: // domain.
204: return getStoredEntry(currentStoredDomain, cpEntry);
205: }
206:
207: // Entry is in a lower-precedence (numerically higher)
208: // domain. Need to remove it from the lower-precedence
209: // domain and add it to the higher precedence domain.
210: sets[currentStoredDomain].remove(cpEntry);
211: sets[entryDomain].add(cpEntry);
212: return cpEntry;
213: }
214:
215: public Iterator iterator() {
216: return partialIterator(ClassConstantPool.DOMAIN_INTEGER,
217: ClassConstantPool.DOMAIN_ATTRIBUTEASCIIZ);
218: }
219:
220: /**
221: * Answer an iterator which iterates over the sets
222: * from sets[start] to sets[stop] only.
223: * @param start int the first set over which iteration will occur.
224: * @param stop int the last set over which iteration will occur
225: * @return Iterator
226: */
227: public Iterator partialIterator(int start, int stop) {
228: // Make sure there's nothing in the undefined domain
229: if (sets[ClassConstantPool.DOMAIN_UNDEFINED].size() > 0) {
230: throw new Error(
231: "Trying to get iterator but have undefined elements");
232: }
233: List someElements = new ArrayList();
234: for (int index = start; index <= stop; index++) {
235: someElements.addAll(sets[index]);
236: }
237: return someElements.iterator();
238: }
239: }
|