KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > hivemind > impl > SchemaProcessorImpl


1 // Copyright 2004, 2005 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.hivemind.impl;
16
17 import java.util.ArrayList JavaDoc;
18 import java.util.HashMap JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import org.apache.hivemind.ApplicationRuntimeException;
24 import org.apache.hivemind.Element;
25 import org.apache.hivemind.ErrorLog;
26 import org.apache.hivemind.SymbolExpander;
27 import org.apache.hivemind.TranslatorManager;
28 import org.apache.hivemind.internal.Module;
29 import org.apache.hivemind.schema.AttributeModel;
30 import org.apache.hivemind.schema.ElementModel;
31 import org.apache.hivemind.schema.Schema;
32 import org.apache.hivemind.schema.SchemaProcessor;
33 import org.apache.hivemind.schema.Translator;
34 import org.apache.hivemind.util.Defense;
35
36 /**
37  * Used to assemble all the data contributed to an
38  * {@link org.apache.hivemind.internal.ConfigurationPoint} while converting the XML (represented as
39  * {@link org.apache.hivemind.Element}s into Java objects.
40  *
41  * @author Howard Lewis Ship
42  */

43 public final class SchemaProcessorImpl implements SchemaProcessor
44 {
45     private ErrorLog _errorLog;
46
47     private Schema _schema;
48
49     private List JavaDoc _stack = new ArrayList JavaDoc();
50
51     private Module _contributingModule;
52     
53     private TranslatorManager _translatorManager;
54     
55     private SymbolExpander _symbolExpander;
56     
57     /**
58      * Map on element name to {@link SchemaElement}.
59      */

60     private Map JavaDoc _elementMap = new HashMap JavaDoc();
61
62     private boolean _canElementsBeMapped;
63
64     /**
65      * Used to track the nesting of elements.
66      */

67     private List JavaDoc _elementStack = new ArrayList JavaDoc();
68
69     public SchemaProcessorImpl(ErrorLog errorLog, Schema schema)
70     {
71         _errorLog = errorLog;
72         _schema = schema;
73
74         if (_schema != null)
75         {
76             List JavaDoc l = _schema.getElementModel();
77
78             int count = l.size();
79             for (int i = 0; i < count; i++)
80             {
81                 ElementModel model = (ElementModel) l.get(i);
82                 _elementMap.put(model.getElementName(), new SchemaElement(this, model));
83             }
84
85             // That is for backward compatibility only, key-attribute is deprecated
86
_canElementsBeMapped = schema.canInstancesBeKeyed();
87         }
88     }
89
90     private Element peekElement()
91     {
92         return (Element) _elementStack.get(_elementStack.size() - 1);
93     }
94     
95     /**
96      * Invoked over reflection by the {@link org.apache.hivemind.schema.rules.InvokeParentRule}.
97      * Only if {@link #isInBackwardCompatibilityModeForMaps()} returns true.
98      * Places the element in the map which is expected to be the first object in the stack.
99      */

100     public void addKeyedElement(Object JavaDoc element)
101     {
102         if (_canElementsBeMapped)
103         {
104             Element currentElement = peekElement();
105             String JavaDoc keyAttribute = _activeElement.getModel().getKeyAttribute();
106
107             if (keyAttribute == null) {
108                 // check for unique attribute
109
for (Iterator JavaDoc j = _activeElement.getModel().getAttributeModels().iterator(); j.hasNext();)
110                 {
111                     AttributeModel attributeModel = (AttributeModel) j.next();
112     
113                     if (attributeModel.isUnique())
114                         keyAttribute = attributeModel.getName();
115                 }
116             }
117
118             String JavaDoc expandedKey = getSymbolExpander().expandSymbols(
119                     currentElement.getAttributeValue(keyAttribute),
120                     currentElement.getLocation());
121
122             Translator t = getAttributeTranslator(keyAttribute);
123
124             Object JavaDoc finalValue = t.translate(
125                     getContributingModule(),
126                     Object JavaDoc.class,
127                     expandedKey,
128                     currentElement.getLocation());
129             
130             Map JavaDoc container = (Map JavaDoc) _stack.get(0);
131             container.put(finalValue, element);
132
133         }
134     }
135     
136     /**
137      * @see org.apache.hivemind.schema.SchemaProcessor#isInBackwardCompatibilityModeForMaps()
138      */

139     public boolean isInBackwardCompatibilityModeForMaps()
140     {
141         return _canElementsBeMapped;
142     }
143     
144     public void push(Object JavaDoc object)
145     {
146         _stack.add(object);
147     }
148
149     public Object JavaDoc pop()
150     {
151         if (_stack.isEmpty())
152             throw new ArrayIndexOutOfBoundsException JavaDoc(XmlImplMessages.schemaStackViolation(this));
153
154         return _stack.remove(_stack.size() - 1);
155     }
156
157     public Object JavaDoc peek()
158     {
159         return peek(0);
160     }
161
162     public Object JavaDoc peek(int depth)
163     {
164         int count = _stack.size();
165
166         int position = count - 1 - depth;
167
168         if (position < 0)
169             throw new ArrayIndexOutOfBoundsException JavaDoc(XmlImplMessages.schemaStackViolation(this));
170
171         return _stack.get(count - 1 - depth);
172     }
173
174     public Module getContributingModule()
175     {
176         return _contributingModule;
177     }
178
179     /** @since 1.1 */
180
181     public String JavaDoc getDefiningModuleId()
182     {
183         return _schema.getDefiningModuleId();
184     }
185     
186     public Module getDefiningModule()
187     {
188         Module definingModule = getContributingModule().getRegistry().getModule(_schema.getDefiningModuleId());
189         Defense.notNull(definingModule, "Defining module");
190         return definingModule;
191     }
192
193     public String JavaDoc getElementPath()
194     {
195         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
196         int count = _elementStack.size();
197
198         for (int i = 0; i < count; i++)
199         {
200             if (i > 0)
201                 buffer.append('/');
202
203             buffer.append(((Element) _elementStack.get(i)).getElementName());
204         }
205
206         return buffer.toString();
207     }
208
209     private void pushElement(Element element)
210     {
211         _elementStack.add(element);
212     }
213
214     private void popElement()
215     {
216         _elementStack.remove(_elementStack.size() - 1);
217     }
218
219     /**
220      * Processes a single extension.
221      * @param container the container object in that the parsed elements are placed
222      */

223     public void process(Object JavaDoc container, List JavaDoc elements, Module contributingModule)
224     {
225         if (elements == null)
226             return;
227
228         if (_schema == null)
229         {
230             return;
231         }
232         Defense.notNull(contributingModule, "Contributing module");
233         
234         if (_canElementsBeMapped && !(container instanceof Map JavaDoc)) {
235             throw new ApplicationRuntimeException("Schema root class is expected to be assignable to " +
236                     "'java.util.Map' because key-attribute or unique attribute is used in the schema. ");
237         }
238
239         // Move the container to the stack as top level element
240
push(container);
241
242         _contributingModule = contributingModule;
243
244         int count = elements.size();
245
246         for (int i = 0; i < count; i++)
247         {
248             Element e = (Element) elements.get(i);
249
250             processRootElement(e);
251         }
252         
253         _contributingModule = null;
254     }
255
256     private void processRootElement(Element element)
257     {
258         String JavaDoc name = element.getElementName();
259
260         SchemaElement schemaElement = (SchemaElement) _elementMap.get(name);
261
262         processElement(element, schemaElement);
263     }
264
265     private SchemaElement _activeElement;
266
267     private void processElement(Element element, SchemaElement schemaElement)
268     {
269         pushElement(element);
270
271         if (schemaElement == null)
272             _errorLog
273                     .error(XmlImplMessages.unknownElement(this, element), element.getLocation(), null);
274         else
275         {
276             SchemaElement prior = _activeElement;
277
278             schemaElement.validateAttributes(element);
279
280             _activeElement = schemaElement;
281
282             schemaElement.fireBegin(element);
283
284             processNestedElements(element, schemaElement);
285
286             schemaElement.fireEnd(element);
287
288             _activeElement = prior;
289         }
290
291         popElement();
292     }
293
294     private void processNestedElements(Element element, SchemaElement schemaElement)
295     {
296         List JavaDoc l = element.getElements();
297         int count = l.size();
298
299         for (int i = 0; i < count; i++)
300         {
301             Element nested = (Element) l.get(i);
302             String JavaDoc name = nested.getElementName();
303
304             processElement(nested, schemaElement.getNestedElement(name));
305         }
306     }
307
308     public Translator getContentTranslator()
309     {
310         return _activeElement.getContentTranslator();
311     }
312
313     public String JavaDoc getAttributeDefault(String JavaDoc attributeName)
314     {
315         return _activeElement.getAttributeDefault(attributeName);
316     }
317
318     public Translator getAttributeTranslator(String JavaDoc attributeName)
319     {
320         return _activeElement.getAttributeTranslator(attributeName);
321     }
322
323     public Translator getTranslator(String JavaDoc translator)
324     {
325         if (_translatorManager == null) {
326             _translatorManager = (TranslatorManager) _contributingModule.getService(TranslatorManager.class);
327         }
328         
329         return _translatorManager.getTranslator(translator);
330     }
331
332     public SymbolExpander getSymbolExpander()
333     {
334         if (_symbolExpander == null) {
335             _symbolExpander = (SymbolExpander) _contributingModule.getService(SymbolExpander.class);
336         }
337        return _symbolExpander;
338     }
339 }
Popular Tags