KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 Copyright (c) 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.HashMap JavaDoc;
32 import java.util.HashSet JavaDoc;
33
34 /**
35  * Context for components using a hierarchy of definitions based on class type.
36  * This is used to track conversion definitions in the form of <b>format</b> and
37  * <b>template</b> elements. The access methods take the different levels of
38  * nesting into account, automatically delegating to the containing context (if
39  * defined) when a lookup fails.
40  *
41  * @author Dennis M. Sosnoski
42  * @version 1.0
43  */

44
45 public class ClassHierarchyContext
46 {
47     /** Link to containing context. */
48     private final ClassHierarchyContext m_outerContext;
49     
50     /** Map from type name to binding component. */
51     private HashMap JavaDoc m_typeToComponentMap;
52     
53     /** Set of compatible type names. */
54     private HashSet JavaDoc m_compatibleTypeSet;
55     
56     /** Map from format names to <code>String</code> conversions (lazy create). */
57     private HashMap JavaDoc m_nameToComponentMap;
58     
59     /**
60      * Constructor.
61      *
62      * @param outer containing context (<code>null</code> if at root of tree)
63      */

64     protected ClassHierarchyContext(ClassHierarchyContext outer) {
65         m_outerContext = outer;
66         m_typeToComponentMap = new HashMap JavaDoc();
67         m_compatibleTypeSet = new HashSet JavaDoc();
68         m_nameToComponentMap = new HashMap JavaDoc();
69     }
70     
71     /**
72      * Get containing context.
73      *
74      * @return containing context information (<code>null</code> if at root of
75      * tree)
76      */

77     public ClassHierarchyContext getContaining() {
78         return m_outerContext;
79     }
80     
81     /**
82      * Add typed component to set defined at this level. This associated the
83      * component with the type for class hierarchy-based lookups.
84      *
85      * @param type type name to be associated with component
86      * @param comp definition component to be added
87      * @param vctx validation context in use
88      */

89     public void addTypedComponent(IClass clas, ElementBase comp,
90         ValidationContext vctx) {
91         String JavaDoc type = clas.getName();
92         if (m_typeToComponentMap.put(type, comp) == null) {
93             
94             // new type, add all interfaces and supertypes to compatible set
95
String JavaDoc[] interfaces = clas.getInterfaces();
96             for (int i = 0; i < interfaces.length; i++) {
97                 m_compatibleTypeSet.add(interfaces[i]);
98             }
99             IClass sclas = clas;
100             do {
101                 m_compatibleTypeSet.add(sclas.getName());
102             } while ((sclas = sclas.getSuperClass()) != null);
103             
104         } else {
105             vctx.addError("Duplicate conversion defined for type " + type,
106                 comp);
107         }
108     }
109     
110     /**
111      * Add named component to set defined at this level. This associated the
112      * component with the type for class hierarchy-based lookups.
113      *
114      * @param label name to be associated with component
115      * @param comp definition component to be added
116      * @param vctx validation context in use
117      */

118     public void addNamedComponent(String JavaDoc label, ElementBase comp,
119         ValidationContext vctx) {
120         if (m_nameToComponentMap.put(label, comp) != null) {
121             vctx.addError("Duplicate label " + label, comp);
122         }
123     }
124
125     /**
126      * Get specific binding component for type. Finds with an exact match
127      * on the type name, checking the containing definitions if a matching
128      * component is not found at this level.
129      *
130      * @param name fully qualified class name to be converted
131      * @return binding component for class, or <code>null</code> if not
132      * found
133      */

134     public ElementBase getSpecificComponent(String JavaDoc name) {
135         ElementBase comp = null;
136         if (m_typeToComponentMap != null) {
137             comp = (ElementBase)m_typeToComponentMap.get(name);
138         }
139         if (comp == null && m_outerContext != null) {
140             comp = m_outerContext.getSpecificComponent(name);
141         }
142         return comp;
143     }
144     
145     /**
146      * Get named binding component definition. Finds the component with the
147      * supplied name, checking the containing definitions if the component is
148      * not found at this level.
149      *
150      * @param name component name to be found
151      * @return binding component with name, or <code>null</code> if not
152      * found
153      */

154     public ElementBase getNamedComponent(String JavaDoc name) {
155         ElementBase comp = null;
156         if (m_nameToComponentMap != null) {
157             comp = (FormatElement)m_nameToComponentMap.get(name);
158         }
159         if (comp == null && m_outerContext != null) {
160             comp = m_outerContext.getNamedComponent(name);
161         }
162         return comp;
163     }
164
165     /**
166      * Get best binding component for class. Finds the component based on a
167      * fully qualified class name. If a specific component for the actual
168      * class is not found (either in this or a containing level) this returns
169      * the most specific superclass component.
170      *
171      * @param clas information for target class
172      * @return binding component definition for class, or <code>null</code> if
173      * none found
174      */

175     public ElementBase getBestComponent(IClass clas) {
176         ElementBase comp = getSpecificComponent(clas.getName());
177         while (comp == null) {
178             IClass sclas = clas.getSuperClass();
179             if (sclas == null) {
180                 break;
181             }
182             clas = sclas;
183             comp = getSpecificComponent(clas.getName());
184         }
185         return comp;
186     }
187
188     /**
189      * Checks if a class is compatible with one or more components. If a
190      * specific component for the actual class is not found (either in this or a
191      * containing level) this checks for components that handle subclasses or
192      * implementations of the class.
193      *
194      * @param clas information for target class
195      * @return <code>true</code> if compatible type, <code>false</code> if not
196      */

197     public boolean isCompatibleType(IClass clas) {
198         if (m_compatibleTypeSet.contains(clas.getName())) {
199             return true;
200         } else if (m_outerContext != null) {
201             return m_outerContext.isCompatibleType(clas);
202         } else {
203             return false;
204         }
205     }
206 }
Popular Tags