if (NSLog.debugLoggingAllowedForGroups(NSLog.DebugGroupRules)) System.out.println(keys);
if (log.isDebugEnabled()) log.debug("Rhs key "+key+" <-- " + keys);
    public void prepareDataStructures() {        log.debug("prepareDataStructures");        boolean localizationEnabled = ERXLocalizer.isLocalizationEnabled();        // is a dictionary which will contain for each rhs key, which other keys it depends        // on, for single rule hops        Hashtable dependendKeysPerKey=new Hashtable();        // here we put per key the keys which this key depends on, when computed by a delayed        // assignment. When this is the case, we only need to add those keys to the main dictionary        // when the rhs key itself shows up on the lhs        Hashtable delayedDependendKeysPerKey=new Hashtable();        _LhsKeysCallback c=new _LhsKeysCallback();        // we first put all those implicit depedencies introduced by the computedKey business        Vector v=new Vector();        v.addElement("propertyKey");        dependendKeysPerKey.put(D2WModel.PropertyIsKeyPathKey,v.clone());        v.addElement("entity");        dependendKeysPerKey.put(D2WModel.RelationshipKey,v.clone());        dependendKeysPerKey.put(D2WModel.AttributeKey,v.clone());        dependendKeysPerKey.put(D2WModel.PropertyTypeKey,v.clone());        dependendKeysPerKey.put(D2WModel.PropertyKeyPortionInModelKey,v.clone());        // then enumerate through all the rules; h         for (Enumeration e=publicRules().objectEnumerator(); e.hasMoreElements();) {            Rule r=(Rule)e.nextElement();            String rhsKey=r.rhs().keyPath();            Vector dependendantKeys=(Vector)dependendKeysPerKey.get(rhsKey);            if (dependendantKeys==null) {                dependendantKeys=new Vector();                dependendKeysPerKey.put(rhsKey,dependendantKeys);            }            ERDQualifierTraversal.traverseQualifier(r.lhs(),c);            for (Enumeration e2=c.keys.objectEnumerator(); e2.hasMoreElements(); ) {                String k=(String)e2.nextElement();                addKeyToVector(k,dependendantKeys);            }            // also add those from the assignment            // if the assignment is delayed, do not add them here;            // they only need to be added if the key that the assignment computes is itself used            // on the left hand side            if (r.rhs() instanceof ERDComputingAssignmentInterface) {                Vector recipientForNewKeys=dependendantKeys;                if (r.rhs() instanceof ERDDelayedAssignment) {                    // put those keys away, needed when reducing the graph and                    recipientForNewKeys=(Vector)delayedDependendKeysPerKey.get(rhsKey);                    if (recipientForNewKeys ==null) {                        recipientForNewKeys =new Vector();                        delayedDependendKeysPerKey.put(rhsKey, recipientForNewKeys);                    }                                    }                NSArray extraKeys=((ERDComputingAssignmentInterface)r.rhs()).dependentKeys(rhsKey);                if (extraKeys!=null) {                    for (Enumeration e6=extraKeys.objectEnumerator(); e6.hasMoreElements(); ) {                        String k=(String)e6.nextElement();                        addKeyToVector(k, recipientForNewKeys);                    }                }            } else if (r.rhs() instanceof DefaultAssignment) {                // special treatment for the only custom assignment coming for the D2W default rule set                // since it does not implement ERDComputingAssignmentInterface, we add the required keys explicitely here                // another way to do this would be to introduce a rule with the required keys in their LHS, but that is                // quite a few rules and this is a bit more self contained                addKeyToVector("task", dependendantKeys);                addKeyToVector("entity", dependendantKeys);                addKeyToVector("propertyKey", dependendantKeys);            }            if(localizationEnabled && r.rhs() instanceof ERDLocalizableAssignmentInterface) {                addKeyToVector("session.localizer", dependendantKeys);            }            c.keys=new NSMutableArray();        }        // we then reduce the graph        log.debug("reducing graph");        boolean touched=true;        while (touched) {            touched=false;            for (Enumeration e3=dependendKeysPerKey.keys(); e3.hasMoreElements();) {                String rk=(String)e3.nextElement();                Vector keys=(Vector)dependendKeysPerKey.get(rk);                for (Enumeration e4=keys.elements(); e4.hasMoreElements();) {                    String k=(String)e4.nextElement();                    if (!BACKSTOP_KEYS.containsObject(k)) {                        Vector newKeys=(Vector)dependendKeysPerKey.get(k);                        Vector keyFromDelayedAssignment=(Vector)delayedDependendKeysPerKey.get(k);                                                if (newKeys!=null || keyFromDelayedAssignment!=null) {                            keys.removeElement(k);                            touched=true;                            if (newKeys!=null) {                                for (Enumeration e5=newKeys.elements(); e5.hasMoreElements();) {                                    String s=(String)e5.nextElement();                                    addKeyToVector(s, keys);                                }                            }                            if (keyFromDelayedAssignment!=null) {                                for (Enumeration e5=keyFromDelayedAssignment.elements(); e5.hasMoreElements();) {                                    String s=(String)e5.nextElement();                                    addKeyToVector(s, keys);                                }                            }                                                    }                    }                }            }        }        // transfer all this into        for (Enumeration e7=dependendKeysPerKey.keys(); e7.hasMoreElements(); ) {            String key=(String)e7.nextElement();            if (NSLog.debugLoggingAllowedForGroups(NSLog.DebugGroupRules)) System.out.print("Rhs key "+key+" <-- ");            Vector keys=(Vector)dependendKeysPerKey.get(key);            if (NSLog.debugLoggingAllowedForGroups(NSLog.DebugGroupRules)) System.out.println(keys);            String[] a=new String[keys.size()];            for (int i=0; i<keys.size();i++) a[i]=(String)keys.elementAt(i);            _significantKeysPerKey.put(key,a);        }    }