KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > binding > model > DefinitionContext


1 /*
2 Copyright (c) 2004-2005, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.binding.model;
30
31 import java.util.ArrayList JavaDoc;
32 import java.util.HashMap JavaDoc;
33
34 /**
35  * Definition context information. This is used to track definitions of items
36  * that can be referenced by other items. The contexts are nested, so that names
37  * not found in a context may be defined by a containing context. The access
38  * methods take this into account, automatically delegating to the containing
39  * context (if defined) when a lookup fails.
40  *
41  * @author Dennis M. Sosnoski
42  * @version 1.0
43  */

44
45 public class DefinitionContext
46 {
47     /** Link to containing definition context. */
48     private final DefinitionContext m_outerContext;
49
50     /** Namespace used by default at this level for attributes. */
51     private NamespaceElement m_attributeDefault;
52
53     /** Namespace used by default at this level for elements. */
54     private NamespaceElement m_elementDefault;
55
56     /** Namespaces defined at level (lazy create). */
57     private ArrayList JavaDoc m_namespaces;
58
59     /** Mapping from prefix to namespace definition (lazy create). */
60     private HashMap JavaDoc m_prefixMap;
61
62     /** Mapping from URI to namespace definition (lazy create). */
63     private HashMap JavaDoc m_uriMap;
64     
65     /** Class hierarchy context for format definitions (lazy create). */
66     private ClassHierarchyContext m_formatContext;
67     
68     /** Class hierarchy context for template definitions (lazy create). */
69     private ClassHierarchyContext m_templateContext;
70     
71     /** Named binding components (lazy create). */
72     private HashMap JavaDoc m_namedStructureMap;
73     
74     /**
75      * Constructor.
76      *
77      * @param outer containing definition context (<code>null</code> if
78      * at root of tree)
79      */

80     protected DefinitionContext(DefinitionContext outer) {
81         m_outerContext = outer;
82     }
83     
84     /**
85      * Get containing context.
86      *
87      * @return containing context information (<code>null</code> if at root of
88      * tree)
89      */

90     public DefinitionContext getContaining() {
91         return m_outerContext;
92     }
93
94     /**
95      * Get containing format context.
96      *
97      * @return innermost containing context for format definitions
98      * (<code>null</code> none defined)
99      */

100     private ClassHierarchyContext getContainingFormatContext() {
101         if (m_outerContext == null) {
102             return null;
103         } else {
104             return m_outerContext.getFormatContext();
105         }
106     }
107     
108     /**
109      * Get current format context.
110      *
111      * @return innermost context for format definitions (<code>null</code> none
112      * defined)
113      */

114     private ClassHierarchyContext getFormatContext() {
115         if (m_formatContext == null) {
116             return getContainingFormatContext();
117         } else {
118             return m_formatContext;
119         }
120     }
121
122     /**
123      * Get containing template context.
124      *
125      * @return innermost containing context for template definitions
126      * (<code>null</code> none defined)
127      */

128     private ClassHierarchyContext getContainingTemplateContext() {
129         if (m_outerContext == null) {
130             return null;
131         } else {
132             return m_outerContext.getTemplateContext();
133         }
134     }
135     
136     /**
137      * Get current template context.
138      *
139      * @return innermost context for template definitions (<code>null</code> none
140      * defined)
141      */

142     private ClassHierarchyContext getTemplateContext() {
143         if (m_templateContext == null) {
144             return getContainingTemplateContext();
145         } else {
146             return m_templateContext;
147         }
148     }
149
150     /**
151      * Add namespace to set defined at this level.
152      *
153      * @param def namespace definition element to be added
154      * @return problem information, or <code>null</code> if no problem
155      */

156     public ValidationProblem addNamespace(NamespaceElement def) {
157         
158         // initialize structures if first namespace definition
159
if (m_namespaces == null) {
160             m_namespaces = new ArrayList JavaDoc();
161             m_prefixMap = new HashMap JavaDoc();
162             m_uriMap = new HashMap JavaDoc();
163         }
164
165         // check for conflict as default for attributes
166
if (def.isAttributeDefault()) {
167             if (m_attributeDefault == null) {
168                 m_attributeDefault = def;
169             } else {
170                 return new ValidationProblem
171                     ("Conflicting attribute namespaces", def);
172             }
173         }
174
175         // check for conflict as default for elements
176
if (def.isElementDefault()) {
177             if (m_elementDefault == null) {
178                 m_elementDefault = def;
179             } else {
180                 return new ValidationProblem
181                     ("Conflicting element namespaces", def);
182             }
183         }
184
185         // check for conflict on prefix
186
String JavaDoc prefix = def.getPrefix();
187         if (m_prefixMap.get(prefix) != null) {
188             return new ValidationProblem("Namespace prefix conflict", def);
189         }
190         
191         // check for duplicate definition of same URI
192
String JavaDoc uri = def.getUri();
193         Object JavaDoc prior = m_uriMap.get(uri);
194         if (prior != null && ((NamespaceElement)prior).getPrefix() != null) {
195             // TODO: is this needed? multiple prefixes should be allowed
196
return null;
197         }
198
199         // add only if successful in all tests
200
m_namespaces.add(def);
201         m_prefixMap.put(prefix, def);
202         m_uriMap.put(uri, def);
203         return null;
204     }
205
206     /**
207      * Get namespace definition for element name.
208      * TODO: handle multiple prefixes for namespace, proper screening
209      *
210      * @param name attribute group defining name
211      * @return namespace definition, or <code>null</code> if none that matches
212      */

213     public NamespaceElement getElementNamespace(NameAttributes name) {
214         String JavaDoc uri = name.getUri();
215         String JavaDoc prefix = name.getPrefix();
216         NamespaceElement ns = null;
217         if (uri != null) {
218             if (m_uriMap != null) {
219                 ns = (NamespaceElement)m_uriMap.get(uri);
220                 if (ns != null && prefix != null) {
221                     if (!prefix.equals(ns.getPrefix())) {
222                         ns = null;
223                     }
224                 }
225             }
226         } else if (prefix != null) {
227             if (m_prefixMap != null) {
228                 ns = (NamespaceElement)m_prefixMap.get(prefix);
229             }
230         } else {
231             ns = m_elementDefault;
232         }
233         if (ns == null && m_outerContext != null) {
234             ns = m_outerContext.getElementNamespace(name);
235         }
236         return ns;
237     }
238
239     /**
240      * Get namespace definition for attribute name.
241      * TODO: handle multiple prefixes for namespace, proper screening
242      *
243      * @param name attribute group defining name
244      * @return namespace definition, or <code>null</code> if none that matches
245      */

246     public NamespaceElement getAttributeNamespace(NameAttributes name) {
247         String JavaDoc uri = name.getUri();
248         String JavaDoc prefix = name.getPrefix();
249         NamespaceElement ns = null;
250         if (uri != null) {
251             if (m_uriMap != null) {
252                 ns = (NamespaceElement)m_uriMap.get(uri);
253                 if (ns != null && prefix != null) {
254                     if (!prefix.equals(ns.getPrefix())) {
255                         ns = null;
256                     }
257                 }
258             }
259         } else if (prefix != null) {
260             if (m_prefixMap != null) {
261                 ns = (NamespaceElement)m_prefixMap.get(prefix);
262             }
263         } else {
264             ns = m_attributeDefault;
265         }
266         if (ns == null && m_outerContext != null) {
267             ns = m_outerContext.getAttributeNamespace(name);
268         }
269         return ns;
270     }
271     
272     /**
273      * Add format to set defined at this level.
274      *
275      * @param def format definition element to be added
276      * @param vctx validation context in use
277      */

278     public void addFormat(FormatElement def, ValidationContext vctx) {
279         if (m_formatContext == null) {
280             m_formatContext =
281                 new ClassHierarchyContext(getContainingFormatContext());
282         }
283         if (def.isDefaultFormat()) {
284             IClass clas = def.getType();
285             m_formatContext.addTypedComponent(clas, def, vctx);
286         }
287         if (def.getLabel() != null) {
288             m_formatContext.addNamedComponent(def.getLabel(), def, vctx);
289         }
290     }
291
292     /**
293      * Get specific format definition for type. Finds with an exact match
294      * on the class name, checking the containing definitions if a format
295      * is not found at this level.
296      *
297      * @param type fully qualified class name to be converted
298      * @return conversion definition for class, or <code>null</code> if not
299      * found
300      */

301     public FormatElement getSpecificFormat(String JavaDoc type) {
302         ClassHierarchyContext ctx = getFormatContext();
303         if (ctx == null) {
304             return null;
305         } else {
306             return (FormatElement)ctx.getSpecificComponent(type);
307         }
308     }
309     
310     /**
311      * Get named format definition. Finds the format with the supplied
312      * name, checking the containing definitions if the format is not found
313      * at this level.
314      *
315      * @param name conversion name to be found
316      * @return conversion definition for class
317      */

318     public FormatElement getNamedFormat(String JavaDoc name) {
319         ClassHierarchyContext ctx = getFormatContext();
320         if (ctx == null) {
321             return null;
322         } else {
323             return (FormatElement)ctx.getNamedComponent(name);
324         }
325     }
326
327     /**
328      * Get best format definition for class. Finds the format based on the
329      * inheritance hierarchy for the supplied class. If a specific format for
330      * the actual class is not found (either in this or a containing level) this
331      * returns the most specific superclass format.
332      *
333      * @param clas information for target conversion class
334      * @return conversion definition for class
335      */

336     public FormatElement getBestFormat(IClass clas) {
337         ClassHierarchyContext ctx = getFormatContext();
338         if (ctx == null) {
339             return null;
340         } else {
341             return (FormatElement)ctx.getBestComponent(clas);
342         }
343     }
344
345     /**
346      * Add template or mapping to set defined at this level.
347      *
348      * @param def template definition element to be added
349      * @param vctx validation context in use
350      */

351     public void addTemplate(TemplateElementBase def, ValidationContext vctx) {
352         if (m_templateContext == null) {
353             m_templateContext =
354                 new ClassHierarchyContext(getContainingTemplateContext());
355         }
356         if (def.isDefaultTemplate()) {
357             IClass clas = def.getHandledClass();
358             m_templateContext.addTypedComponent(clas, def, vctx);
359         }
360         if (def instanceof TemplateElement) {
361             TemplateElement tdef = (TemplateElement)def;
362             if (tdef.getLabel() != null) {
363                 m_templateContext.addNamedComponent(tdef.getLabel(), def, vctx);
364             }
365         }
366     }
367
368     /**
369      * Get specific template definition for type. Finds with an exact match
370      * on the class name, checking the containing definitions if a template
371      * is not found at this level.
372      *
373      * @param type fully qualified class name to be converted
374      * @return conversion definition for class, or <code>null</code> if not
375      * found
376      */

377     public TemplateElementBase getSpecificTemplate(String JavaDoc type) {
378         ClassHierarchyContext ctx = getTemplateContext();
379         if (ctx == null) {
380             return null;
381         } else {
382             return (TemplateElementBase)ctx.getSpecificComponent(type);
383         }
384     }
385     
386     /**
387      * Get named template definition. Finds the template with the supplied
388      * name, checking the containing definitions if the template is not found
389      * at this level.
390      *
391      * @param name conversion name to be found
392      * @return conversion definition for class
393      */

394     public TemplateElement getNamedTemplate(String JavaDoc name) {
395         ClassHierarchyContext ctx = getTemplateContext();
396         if (ctx == null) {
397             return null;
398         } else {
399             return (TemplateElement)ctx.getNamedComponent(name);
400         }
401     }
402
403     /**
404      * Get best template definition for class. Finds the template based on the
405      * inheritance hierarchy for the supplied class. If a specific template for
406      * the actual class is not found (either in this or a containing level) this
407      * returns the most specific superclass template.
408      *
409      * @param clas information for target conversion class
410      * @return conversion definition for class, or <code>null</code> if no
411      * compatible mapping defined
412      */

413     public TemplateElementBase getBestTemplate(IClass clas) {
414         ClassHierarchyContext ctx = getTemplateContext();
415         if (ctx == null) {
416             return null;
417         } else {
418             return (TemplateElementBase)ctx.getBestComponent(clas);
419         }
420     }
421
422     /**
423      * Checks if a class is compatible with one or more templates. This checks
424      * based on the inheritance hierarchy for the supplied class, looks for the
425      * class or interface itself as well as any subclasses or implementations.
426      *
427      * @param clas information for target class
428      * @return <code>true</code> if compatible type, <code>false</code> if not
429      */

430     public boolean isCompatibleTemplateType(IClass clas) {
431         ClassHierarchyContext chctx = getTemplateContext();
432         if (chctx == null) {
433             return false;
434         } else {
435             return chctx.isCompatibleType(clas);
436         }
437     }
438     
439     /**
440      * Add named structure to set defined in this context.
441      *
442      * @param def structure definition
443      * @return problem information, or <code>null</code> if no problem
444      */

445
446     public ValidationProblem addNamedStructure(StructureElementBase def) {
447
448         // create structure if not already done
449
if (m_namedStructureMap == null) {
450             m_namedStructureMap = new HashMap JavaDoc();
451         }
452
453         // check for conflict on label before adding to definitions
454
String JavaDoc label = def.getLabel();
455         if (m_namedStructureMap.get(label) == null) {
456             m_namedStructureMap.put(label, def);
457             return null;
458         } else {
459             return new ValidationProblem("Duplicate label " + label, def);
460         }
461     }
462
463     /**
464      * Get labeled structure definition within this context.
465      *
466      * @param label structure definition label
467      * @return structure definition, or <code>null</code> if not defined
468      */

469
470     public StructureElementBase getNamedStructure(String JavaDoc label) {
471         if (m_namedStructureMap == null) {
472             return null;
473         } else {
474             return (StructureElementBase)m_namedStructureMap.get(label);
475         }
476     }
477 }
Popular Tags