KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > tools > xjc > runtime > GrammarInfoFacade


1 package com.sun.tools.xjc.runtime;
2
3 import java.util.ArrayList JavaDoc;
4 import java.util.StringTokenizer JavaDoc;
5
6 import javax.xml.bind.JAXBContext;
7 import javax.xml.bind.JAXBException;
8
9 import com.sun.xml.bind.GrammarImpl;
10 import com.sun.xml.bind.Messages;
11 import com.sun.xml.bind.ProxyGroup;
12
13 /**
14  * This class is a facade to a collection of GrammarInfo objects. It
15  * dispatches rootElement requests to the underlying GrammarInfo objects.
16  *
17  * @version $Revision: 1.1 $
18  */

19 class GrammarInfoFacade implements GrammarInfo {
20
21     private GrammarInfo[] grammarInfos = null;
22     
23     
24     
25     public GrammarInfoFacade( GrammarInfo[] items ) throws JAXBException {
26         grammarInfos = items;
27
28 // META-IF(U)
29
detectRootElementCollisions( getProbePoints() );
30 // META-ENDIF
31
}
32
33 // META-IF(U)
34
/*
35      * Gets a generated implementation class for the specified root element.
36      * This method is used to determine the first object to be unmarshalled.
37      */

38     public UnmarshallingEventHandler createUnmarshaller(String JavaDoc namespaceUri, String JavaDoc localName, UnmarshallingContext context) {
39         // find the root element among the GrammarInfos
40
for( int i = 0; i < grammarInfos.length; i++ ) {
41             UnmarshallingEventHandler ueh = grammarInfos[i].createUnmarshaller( namespaceUri, localName, context );
42             if( ueh != null ) {
43                 return ueh;
44             }
45         }
46         
47         // the element was not located in any of the grammar infos...
48
return null;
49     }
50
51     public Class JavaDoc getRootElement(String JavaDoc namespaceUri, String JavaDoc localName) {
52         // find the root element among the GrammarInfos
53
for( int i = 0; i < grammarInfos.length; i++ ) {
54             Class JavaDoc c = grammarInfos[i].getRootElement( namespaceUri, localName );
55             if( c != null ) {
56                 return c;
57             }
58         }
59         
60         // the element was not located in any of the grammar infos...
61
return null;
62     }
63
64     public boolean recognize( String JavaDoc nsUri, String JavaDoc localName ) {
65         for( int i = 0; i < grammarInfos.length; i++ )
66             if( grammarInfos[i].recognize(nsUri, localName) )
67                 return true;
68         return false;
69     }
70     
71     /*
72      * Return the probe points for this GrammarInfo, which are used to detect
73      * {namespaceURI,localName} collisions across the GrammarInfo's on the
74      * schemaPath. This is a slightly more complex implementation than a simple
75      * hashmap, but it is more flexible in supporting additional schema langs.
76      */

77     public String JavaDoc[] getProbePoints() {
78         ArrayList JavaDoc probePointList = new ArrayList JavaDoc();
79         
80         for( int i = 0; i < grammarInfos.length; i++ ) {
81             String JavaDoc[] points = grammarInfos[i].getProbePoints();
82             for( int j = 0; j < points.length; j++ ) {
83                 probePointList.add( points[j] );
84             }
85         }
86
87         // once per JAXBContext creation, so it may not be worth it.
88
return (String JavaDoc[])probePointList.toArray( new String JavaDoc[ probePointList.size() ] );
89     }
90     
91     
92     /**
93      * Iterate through the probe points looking for root element collisions.
94      * If a duplicate is detected, then multiple root element componenets
95      * exist with the same uri:localname
96      */

97     private void detectRootElementCollisions( String JavaDoc[] points )
98     throws JAXBException {
99         
100         // the array of probe points contain uri:localname pairs
101
for( int i = 0; i < points.length; i += 2 ) {
102             // iterate over GrammarInfos - if more than one GI returns
103
// a class from getRootElement, then there is a collision
104
boolean elementFound = false;
105             for( int j = grammarInfos.length-1; j >= 0; j -- ) {
106                 if( grammarInfos[j].recognize( points[i], points[i+1] ) ) {
107                     if( elementFound == false ) {
108                         elementFound = true;
109                     } else {
110                         throw new JAXBException(
111                                 Messages.format( Messages.COLLISION_DETECTED,
112                                         points[i], points[i+1] ) );
113                     }
114                 }
115             }
116         }
117     }
118 // META-ENDIF
119

120     /*
121      * This static method is used to setup the GrammarInfoFacade. It
122      * is invoked by the DefaultJAXBContextImpl constructor
123      */

124     static GrammarInfo createGrammarInfoFacade( String JavaDoc contextPath,
125                                                 ClassLoader JavaDoc classLoader )
126         throws JAXBException {
127             
128         String JavaDoc version=null;
129         
130         // array of GrammarInfo objs
131
ArrayList JavaDoc gis = new ArrayList JavaDoc();
132
133         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc( contextPath, ":;" );
134
135         // instantiate all of the specified JAXBContextImpls
136
while( st.hasMoreTokens() ) {
137             String JavaDoc targetPackage = st.nextToken();
138             String JavaDoc objectFactoryName = targetPackage + ".ObjectFactory";
139             
140             try {
141                 JAXBContext c = (JAXBContext)Class.forName(
142                         objectFactoryName, true, classLoader ).newInstance();
143                 
144                 // check version
145
if( version==null ) version = getVersion(c);
146                 else
147                 if( !version.equals(getVersion(c)) )
148                     throw new JAXBException( Messages.format(
149                         Messages.INCOMPATIBLE_VERSION, new Object JavaDoc[]{
150                             version,
151                             c.getClass().getName(),
152                             getVersion(c) } ) );
153                
154                 // use reflection to get GrammarInfo
155
Object JavaDoc grammarInfo = c.getClass().getField("grammarInfo").get(null);
156                
157                 // wrap the grammarInfo into a proxy if necessary
158
grammarInfo = ProxyGroup.blindWrap(
159                     grammarInfo, GrammarInfo.class,
160                     new Class JavaDoc[]{
161                         GrammarInfo.class,
162                     // META-IF(U)
163
UnmarshallingContext.class,
164                         UnmarshallingEventHandler.class,
165                     // META-ENDIF
166
// META-IF(V|M)
167
XMLSerializer.class,
168                         XMLSerializable.class,
169                         NamespaceContext2.class,
170                     // META-ENDIF
171
// META-IF(V)
172
ValidatableObject.class
173                     // META-ENDIF
174
} );
175                 
176                 gis.add( grammarInfo );
177             } catch( ClassNotFoundException JavaDoc e ) {
178                 throw new NoClassDefFoundError JavaDoc(e.getMessage());
179             } catch( Exception JavaDoc e ) {
180                 throw new JAXBException(e);
181             }
182         }
183
184         if( gis.size()==1 )
185             // if there's only one path, no need to use a facade.
186
return (GrammarInfo)gis.get(0);
187         
188         return new GrammarInfoFacade(
189             (GrammarInfo[])(gis.toArray( new GrammarInfo[ gis.size() ] ) ) );
190     }
191     
192     /**
193      * Obtains a version number of the JAXB RI that has generated
194      * the specified context, or null if it fails (for example
195      * because it's not generated by JAXB RI.)
196      *
197      * @param c
198      * an instance of a generated ObjectFactory class.
199      * This will return the version number written into
200      * the corresponding JAXBVersion class.
201      */

202     private static String JavaDoc getVersion(JAXBContext c) throws JAXBException {
203         try {
204             Class JavaDoc jaxbBersionClass = (Class JavaDoc)c.getClass().getField("version").get(null);
205             return (String JavaDoc)jaxbBersionClass.getField("version").get(null);
206         } catch( Throwable JavaDoc t ) {
207             return null;
208         }
209     }
210
211     public Class JavaDoc getDefaultImplementation( Class JavaDoc javaContentInterface ) {
212         for( int i=0; i<grammarInfos.length; i++ ) {
213             Class JavaDoc c = grammarInfos[i].getDefaultImplementation( javaContentInterface );
214             if(c!=null) return c;
215         }
216         return null;
217     }
218
219 // META-IF(W)
220
private com.sun.msv.grammar.Grammar bgm = null;
221     
222     public com.sun.msv.grammar.Grammar getGrammar() throws JAXBException {
223         if(bgm==null) {
224             com.sun.msv.grammar.Grammar[] grammars = new com.sun.msv.grammar.Grammar[grammarInfos.length];
225             
226             // load al the grammars individually
227
for( int i=0; i<grammarInfos.length; i++ )
228                 grammars[i] = grammarInfos[i].getGrammar();
229             
230             // connect them to each other
231
for( int i=0; i<grammarInfos.length; i++ )
232                 if( grammars[i] instanceof GrammarImpl )
233                     ((GrammarImpl)grammars[i]).connect(grammars);
234             
235             // take union of them
236
for( int i=0; i<grammarInfos.length; i++ ) {
237                 com.sun.msv.grammar.Grammar n = grammars[i];
238                 if( bgm == null ) bgm = n;
239                 else bgm = union( bgm, n );
240             }
241         }
242         return bgm;
243     }
244
245
246     /**
247      * Computes the union of two grammars.
248      */

249     private com.sun.msv.grammar.Grammar union( com.sun.msv.grammar.Grammar g1, com.sun.msv.grammar.Grammar g2 ) {
250         // either g1.getPool() or g2.getPool() is OK.
251
// this is just a metter of performance problem.
252
final com.sun.msv.grammar.ExpressionPool pool = g1.getPool();
253         final com.sun.msv.grammar.Expression top = pool.createChoice(g1.getTopLevel(),g2.getTopLevel());
254         
255         return new com.sun.msv.grammar.Grammar() {
256             public com.sun.msv.grammar.ExpressionPool getPool() {
257                 return pool;
258             }
259             public com.sun.msv.grammar.Expression getTopLevel() {
260                 return top;
261             }
262         };
263     }
264 // META-ENDIF
265

266     
267 // META-IF(V|M)
268
/**
269      * @see com.sun.tools.xjc.runtime.GrammarInfo#castToXMLSerializable(java.lang.Object)
270      */

271     public XMLSerializable castToXMLSerializable(Object JavaDoc o) {
272         XMLSerializable result = null;
273         for( int i = 0; i < grammarInfos.length; i++ ) {
274             result = grammarInfos[i].castToXMLSerializable( o );
275             if( result != null ) {
276                 return result;
277             }
278         }
279         return null;
280     }
281 // META-ENDIF
282

283 // META-IF(V)
284
/**
285      * @see com.sun.tools.xjc.runtime.GrammarInfo#castToValidatableObject(java.lang.Object)
286      */

287     public ValidatableObject castToValidatableObject(Object JavaDoc o) {
288         ValidatableObject result = null;
289         for( int i = 0; i < grammarInfos.length; i++ ) {
290             result = grammarInfos[i].castToValidatableObject( o );
291             if( result != null ) {
292                 return result;
293             }
294         }
295         return null;
296     }
297 // META-ENDIF
298
}
299
Popular Tags