001: // Copyright (c) 2004 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.mapping;
005:
006: public class InheritingEnvironment extends SimpleEnvironment {
007: int numInherited;
008: Environment[] inherited;
009: Namespace[] namespaceMap;
010: Object[] propertyMap;
011: int baseTimestamp;
012:
013: public InheritingEnvironment(String name, Environment parent) {
014: super (name);
015: addParent(parent);
016: if (parent instanceof SimpleEnvironment) {
017: int timestamp = ++((SimpleEnvironment) parent).currentTimestamp;
018: baseTimestamp = timestamp;
019: currentTimestamp = timestamp;
020: }
021: }
022:
023: public final int getNumParents() {
024: return numInherited;
025: }
026:
027: public final Environment getParent(int index) {
028: return inherited[index];
029: }
030:
031: public void addParent(Environment env) {
032: if (numInherited == 0)
033: inherited = new Environment[4];
034: else if (numInherited <= inherited.length) {
035: Environment[] newInherited = new Environment[2 * numInherited];
036: System.arraycopy(inherited, 0, newInherited, 0,
037: numInherited);
038: inherited = newInherited;
039: }
040: inherited[numInherited] = env;
041: numInherited++;
042: }
043:
044: public NamedLocation lookupInherited(Symbol name, Object property,
045: int hash) {
046: for (int i = 0; i < numInherited; i++) {
047: Symbol sym = name;
048: Object prop = property;
049: if (namespaceMap != null && namespaceMap.length > 2 * i) {
050: Object srcNamespace = namespaceMap[2 * i];
051: Object dstNamespace = namespaceMap[2 * i + 1];
052: if (srcNamespace != null || dstNamespace != null) {
053: if (name.getNamespace() != dstNamespace)
054: continue;
055: sym = Symbol.make(srcNamespace, name.getName());
056: }
057: }
058: if (propertyMap != null && propertyMap.length > 2 * i) {
059: Object srcProperty = propertyMap[2 * i];
060: Object dstProperty = propertyMap[2 * i + 1];
061: if (srcProperty != null || dstProperty != null) {
062: if (property != dstProperty)
063: continue;
064: prop = srcProperty;
065: }
066: }
067: NamedLocation loc = inherited[i].lookup(sym, prop, hash);
068: if (loc != null && loc.isBound()) {
069: if (!(loc instanceof SharedLocation)
070: || ((SharedLocation) loc).timestamp < baseTimestamp)
071: return loc;
072: }
073: }
074: return null;
075: }
076:
077: public NamedLocation lookup(Symbol name, Object property, int hash) {
078: NamedLocation loc = super .lookup(name, property, hash);
079: if (loc != null && loc.isBound())
080: return loc;
081: return lookupInherited(name, property, hash);
082: }
083:
084: public synchronized NamedLocation getLocation(Symbol name,
085: Object property, int hash, boolean create) {
086: NamedLocation loc = lookupDirect(name, property, hash);
087: if (loc != null && (create || loc.isBound()))
088: return loc;
089: if ((flags & INDIRECT_DEFINES) != 0 && create)
090: loc = inherited[0].getLocation(name, property, hash, true);
091: else
092: loc = lookupInherited(name, property, hash);
093:
094: if (loc != null) {
095: if (create /* && loc.getEnvironment() != this*/) {
096: NamedLocation xloc = addUnboundLocation(name, property,
097: hash);
098: if ((flags & CAN_DEFINE) == 0 && loc.isBound())
099: redefineError(name, property, xloc);
100: xloc.base = loc;
101: if (loc.value == IndirectableLocation.INDIRECT_FLUIDS)
102: xloc.value = loc.value;
103: else if ((flags & DIRECT_INHERITED_ON_SET) != 0)
104: xloc.value = IndirectableLocation.DIRECT_ON_SET;
105: else
106: xloc.value = null;
107: if (xloc instanceof SharedLocation)
108: ((SharedLocation) xloc).timestamp = baseTimestamp;
109: return xloc;
110: } else
111: return loc;
112: }
113: return create ? addUnboundLocation(name, property, hash) : null;
114: }
115:
116: public LocationEnumeration enumerateAllLocations() {
117: LocationEnumeration it = new LocationEnumeration(table,
118: 1 << log2Size);
119: it.env = this ;
120: if (inherited != null && inherited.length > 0) {
121: it.inherited = inherited[0].enumerateAllLocations();
122: it.index = 0;
123: }
124: return it;
125: }
126:
127: protected boolean hasMoreElements(LocationEnumeration it) {
128: if (it.inherited != null) {
129: for (;;) {
130: NamedLocation loc = it.curLoc;
131: for (;;) {
132: it.inherited.curLoc = loc;
133: if (!it.inherited.hasMoreElements()) {
134: it.curLoc = it.inherited.curLoc;
135: break;
136: }
137: loc = it.inherited.curLoc;
138: if (lookup(loc.name, loc.property) == loc) {
139: it.curLoc = loc;
140: return true;
141: }
142: loc = loc.next;
143: }
144: if (++it.index == numInherited)
145: break;
146: it.inherited = inherited[it.index]
147: .enumerateAllLocations();
148: }
149: it.inherited = null;
150: it.bindings = table;
151: it.index = 1 << log2Size;
152: }
153: return super .hasMoreElements(it);
154: }
155:
156: protected void toStringBase(StringBuffer sbuf) {
157: sbuf.append(" baseTs:");
158: sbuf.append(baseTimestamp);
159: for (int i = 0; i < numInherited; i++) {
160: sbuf.append(" base:");
161: sbuf.append(inherited[i].toStringVerbose());
162: }
163: }
164: }
|