001    package com.thaiopensource.validate.nrl;
002    
003    import org.xml.sax.Locator;
004    import org.xml.sax.helpers.LocatorImpl;
005    
006    import java.util.Hashtable;
007    import java.util.Enumeration;
008    
009    import com.thaiopensource.validate.nrl.ActionSet;
010    import com.thaiopensource.validate.nrl.AttributeActionSet;
011    
012    class Mode {
013      static final String ANY_NAMESPACE = "##any";
014      static final int ATTRIBUTE_PROCESSING_NONE = 0;
015      static final int ATTRIBUTE_PROCESSING_QUALIFIED = 1;
016      static final int ATTRIBUTE_PROCESSING_FULL = 2;
017      static final Mode CURRENT = new Mode("#current", null);
018    
019      private final String name;
020      private Mode baseMode;
021      private boolean defined;
022      private Locator whereDefined;
023      private Locator whereUsed;
024      private final Hashtable elementMap = new Hashtable();
025      private final Hashtable attributeMap = new Hashtable();
026      private int attributeProcessing = -1;
027    
028      Mode(String name, Mode baseMode) {
029        this.name = name;
030        this.baseMode = baseMode;
031      }
032    
033      String getName() {
034        return name;
035      }
036    
037      Mode getBaseMode() {
038        return baseMode;
039      }
040    
041      void setBaseMode(Mode baseMode) {
042        this.baseMode = baseMode;
043      }
044    
045      ActionSet getElementActions(String ns) {
046        ActionSet actions = getElementActionsExplicit(ns);
047        if (actions == null) {
048          actions = getElementActionsExplicit(ANY_NAMESPACE);
049          // this is not correct: it breaks a derived mode that use anyNamespace
050          // elementMap.put(ns, actions);
051        }
052        return actions;
053      }
054    
055      private ActionSet getElementActionsExplicit(String ns) {
056        ActionSet actions = (ActionSet)elementMap.get(ns);
057        if (actions == null && baseMode != null) {
058          actions = baseMode.getElementActionsExplicit(ns);
059          if (actions != null) {
060            actions = actions.changeCurrentMode(this);
061            elementMap.put(ns, actions);
062          }
063        }
064        return actions;
065      }
066    
067      AttributeActionSet getAttributeActions(String ns) {
068        AttributeActionSet actions = getAttributeActionsExplicit(ns);
069        if (actions == null) {
070          actions = getAttributeActionsExplicit(ANY_NAMESPACE);
071          // this is not correct: it breaks a derived mode that use anyNamespace
072          // attributeMap.put(ns, actions);
073        }
074        return actions;
075      }
076    
077      private AttributeActionSet getAttributeActionsExplicit(String ns) {
078        AttributeActionSet actions = (AttributeActionSet)attributeMap.get(ns);
079        if (actions == null && baseMode != null) {
080          actions = baseMode.getAttributeActionsExplicit(ns);
081          if (actions != null)
082            attributeMap.put(ns, actions);
083        }
084        return actions;
085      }
086    
087      int getAttributeProcessing() {
088        if (attributeProcessing == -1) {
089          if (baseMode != null)
090            attributeProcessing = baseMode.getAttributeProcessing();
091          else
092            attributeProcessing = ATTRIBUTE_PROCESSING_NONE;
093          for (Enumeration en = attributeMap.keys(); en.hasMoreElements() && attributeProcessing != ATTRIBUTE_PROCESSING_FULL;) {
094            String ns = (String)en.nextElement();
095            AttributeActionSet actions = (AttributeActionSet)attributeMap.get(ns);
096            if (!actions.getAttach()
097                || actions.getReject()
098                || actions.getSchemas().length > 0)
099              attributeProcessing = ((ns.equals("") || ns.equals(ANY_NAMESPACE))
100                                    ? ATTRIBUTE_PROCESSING_FULL
101                                    : ATTRIBUTE_PROCESSING_QUALIFIED);
102          }
103        }
104        return attributeProcessing;
105      }
106    
107      Locator getWhereDefined() {
108        return whereDefined;
109      }
110    
111      boolean isDefined() {
112        return defined;
113      }
114    
115      Locator getWhereUsed() {
116        return whereUsed;
117      }
118    
119      void noteUsed(Locator locator) {
120        if (whereUsed == null && locator != null)
121          whereUsed = new LocatorImpl(locator);
122      }
123    
124      void noteDefined(Locator locator) {
125        defined = true;
126        if (whereDefined == null && locator != null)
127          whereDefined = new LocatorImpl(locator);
128      }
129    
130      boolean bindElement(String ns, ActionSet actions) {
131        if (elementMap.get(ns) != null)
132          return false;
133        elementMap.put(ns, actions);
134        return true;
135      }
136    
137      boolean bindAttribute(String ns, AttributeActionSet actions) {
138        if (attributeMap.get(ns) != null)
139          return false;
140        attributeMap.put(ns, actions);
141        return true;
142      }
143    
144    }