KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > xb > binding > AbstractMarshaller


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.xb.binding;
23
24 import java.io.IOException JavaDoc;
25 import java.io.Writer JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Properties JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import javax.xml.namespace.QName JavaDoc;
34 import org.jboss.logging.Logger;
35 import org.jboss.xb.binding.introspection.FieldInfo;
36 import org.xml.sax.SAXException JavaDoc;
37 import org.xml.sax.ContentHandler JavaDoc;
38 import org.xml.sax.Locator JavaDoc;
39 import org.xml.sax.Attributes JavaDoc;
40
41 /**
42  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
43  * @version <tt>$Revision: 1958 $</tt>
44  */

45 public abstract class AbstractMarshaller
46    implements Marshaller
47 {
48    protected final Logger log = Logger.getLogger(getClass());
49
50    protected String JavaDoc version = VERSION;
51    protected String JavaDoc encoding = ENCODING;
52    protected List JavaDoc rootQNames = new ArrayList JavaDoc();
53
54    protected NamespaceRegistry nsRegistry = new NamespaceRegistry();
55
56    private Map JavaDoc classMappings = Collections.EMPTY_MAP;
57    protected Map JavaDoc field2WildcardMap = Collections.EMPTY_MAP;
58    protected Map JavaDoc cls2TypeMap = Collections.EMPTY_MAP;
59
60    /**
61     * Content the result is written to
62     */

63    protected Content content = new Content();
64
65    private Properties JavaDoc props;
66
67    // Marshaller implementation
68

69    public void mapClassToGlobalElement(Class JavaDoc cls,
70                                        String JavaDoc localName,
71                                        String JavaDoc namespaceUri,
72                                        String JavaDoc schemaUrl,
73                                        ObjectModelProvider provider)
74    {
75       GenericObjectModelProvider delProv = null;
76       if(provider != null)
77       {
78          delProv = provider instanceof GenericObjectModelProvider ?
79          (GenericObjectModelProvider)provider :
80          new DelegatingObjectModelProvider(provider);
81       }
82
83       ClassMapping mapping = new ClassMapping(cls,
84          localName,
85          null,
86          namespaceUri,
87          schemaUrl,
88          delProv
89       );
90
91       addClassMapping(mapping);
92    }
93
94    public void mapClassToGlobalType(Class JavaDoc cls,
95                                     String JavaDoc localName,
96                                     String JavaDoc nsUri,
97                                     String JavaDoc schemaUrl,
98                                     ObjectModelProvider provider)
99    {
100       ClassMapping mapping = new ClassMapping(cls,
101          null,
102          localName,
103          nsUri,
104          schemaUrl,
105          provider instanceof GenericObjectModelProvider ?
106          (GenericObjectModelProvider)provider :
107          new DelegatingObjectModelProvider(provider)
108       );
109
110       addClassMapping(mapping);
111    }
112
113    public void mapFieldToWildcard(Class JavaDoc cls, String JavaDoc field, ObjectLocalMarshaller marshaller)
114    {
115       FieldToWildcardMapping mapping = new FieldToWildcardMapping(cls, field, marshaller);
116       switch(field2WildcardMap.size())
117       {
118          case 0:
119             field2WildcardMap = Collections.singletonMap(cls, mapping);
120             break;
121          case 1:
122             field2WildcardMap = new HashMap JavaDoc(field2WildcardMap);
123          default:
124             field2WildcardMap.put(cls, mapping);
125       }
126    }
127
128    public void mapClassToXsiType(Class JavaDoc cls, String JavaDoc typeNs, String JavaDoc typeLocalPart)
129    {
130       QName JavaDoc typeQName = new QName JavaDoc(typeNs, typeLocalPart);
131       switch(cls2TypeMap.size())
132       {
133          case 0:
134             cls2TypeMap = Collections.singletonMap(cls, typeQName);
135             break;
136          case 1:
137             cls2TypeMap = new HashMap JavaDoc(cls2TypeMap);
138          default:
139             cls2TypeMap.put(cls, typeQName);
140       }
141
142       if(log.isTraceEnabled())
143       {
144          log.trace("mapped " + cls + " to xsi:type " + typeQName);
145       }
146    }
147
148    public void setVersion(String JavaDoc version)
149    {
150       this.version = version;
151    }
152
153    public void setEncoding(String JavaDoc encoding)
154    {
155       this.encoding = encoding;
156    }
157
158    public void mapPublicIdToSystemId(String JavaDoc publicId, String JavaDoc systemId)
159    {
160       throw new UnsupportedOperationException JavaDoc();
161    }
162
163    public void addRootElement(String JavaDoc namespaceUri, String JavaDoc prefix, String JavaDoc name)
164    {
165       addRootElement(new QName JavaDoc(namespaceUri, name, prefix));
166    }
167
168    public void addRootElement(QName JavaDoc qName)
169    {
170       rootQNames.add(qName);
171    }
172
173    public void setProperty(String JavaDoc name, String JavaDoc value)
174    {
175       if(props == null)
176       {
177          props = new Properties JavaDoc();
178       }
179       props.setProperty(name, value);
180    }
181
182    public String JavaDoc getProperty(String JavaDoc name)
183    {
184       return props == null ? null : props.getProperty(name);
185    }
186
187    /**
188     * Defines a namespace. The namespace declaration will appear in the root element.
189     * <p>If <code>prefix</code> argument is <code>null</code> or is an empty string then
190     * the passed in URI will be used for the default namespace, i.e. <code>xmlns</code>.
191     * Otherwise, the declaration will follow the format <code>xmlns:prefix=uri</code>.
192     * <p>If the namespace with the given prefix was already declared, its value is overwritten.
193     *
194     * @param prefix the prefix for the namespace to declare (can be null or empty string)
195     * @param uri the URI of the namespace.
196     */

197    public void declareNamespace(String JavaDoc prefix, String JavaDoc uri)
198    {
199       if(prefix == null)
200       {
201          return;
202       }
203
204       nsRegistry.addPrefixMapping(prefix, uri);
205    }
206
207    public void removePrefixMapping(String JavaDoc prefix)
208    {
209       nsRegistry.removePrefixMapping(prefix);
210    }
211
212    public String JavaDoc getPrefix(String JavaDoc ns)
213    {
214       String JavaDoc prefix = nsRegistry.getPrefix(ns);
215       if(prefix == null && Constants.NS_XML_NAMESPACE.equals(ns))
216       {
217          prefix = "xml";
218       }
219       return prefix;
220    }
221
222    protected void declareNs(AttributesImpl attrs)
223    {
224       for(Iterator JavaDoc i = nsRegistry.getRegisteredURIs(); i.hasNext();)
225       {
226          String JavaDoc uri = (String JavaDoc)i.next();
227          String JavaDoc prefix = nsRegistry.getPrefix(uri);
228          declareNs(attrs, prefix, uri);
229       }
230    }
231
232    protected static void declareNs(AttributesImpl attrs, String JavaDoc prefix, String JavaDoc ns)
233    {
234       attrs.add(null, prefix, prefix.length() == 0 ? "xmlns" : "xmlns:" + prefix, "CDATA", ns);
235    }
236
237    /**
238     * Adds xsi:type attribute and optionally declares namespaces for xsi and type's namespace.
239     *
240     * @param typeQName the type to declare xsi:type attribute for
241     * @param attrs the attributes to add xsi:type attribute to
242     * @return prefix for the type's ns if it was generated
243     */

244    protected String JavaDoc declareXsiType(QName JavaDoc typeQName, AttributesImpl attrs)
245    {
246       String JavaDoc result = null;
247       String JavaDoc xsiPrefix = nsRegistry.getPrefix(Constants.NS_XML_SCHEMA_INSTANCE);
248       if(xsiPrefix == null)
249       {
250          declareNs(attrs, "xsi", Constants.NS_XML_SCHEMA_INSTANCE);
251          xsiPrefix = "xsi";
252       }
253
254       String JavaDoc pref = getPrefix(typeQName.getNamespaceURI());
255       if(pref == null)
256       {
257          // the ns is not declared
258
result = pref = typeQName.getLocalPart() + "_ns";
259       }
260
261       String JavaDoc qName = prefixLocalName(pref, typeQName.getLocalPart());
262       attrs.add(Constants.NS_XML_SCHEMA_INSTANCE, "type", xsiPrefix + ":type", "CDATA", qName);
263       return result;
264    }
265
266    protected static String JavaDoc prefixLocalName(String JavaDoc prefix, String JavaDoc local)
267    {
268       return prefix == null || prefix.length() == 0 ? local : prefix + ':' + local;
269    }
270
271    public abstract void addAttribute(String JavaDoc prefix, String JavaDoc localName, String JavaDoc type, String JavaDoc value);
272
273    // Protected
274

275    protected boolean propertyIsTrueOrNotSet(String JavaDoc name)
276    {
277       String JavaDoc value = getProperty(name);
278       return value == null || "true".equalsIgnoreCase(value);
279    }
280
281    protected void writeXmlVersion(Writer JavaDoc writer) throws IOException JavaDoc
282    {
283       String JavaDoc xmlVersion = getProperty(Marshaller.PROP_OUTPUT_XML_VERSION);
284       if(xmlVersion == null || "true".equalsIgnoreCase(xmlVersion))
285       {
286          writer.write("<?xml version=\"");
287          writer.write(version);
288          writer.write("\" encoding=\"");
289          writer.write(encoding);
290          writer.write("\"?>\n");
291       }
292    }
293
294    protected ClassMapping getClassMapping(Class JavaDoc cls)
295    {
296       return (ClassMapping)classMappings.get(cls);
297    }
298
299    private void addClassMapping(ClassMapping mapping)
300    {
301       if(classMappings == Collections.EMPTY_MAP)
302       {
303          classMappings = new HashMap JavaDoc();
304       }
305       classMappings.put(mapping.cls, mapping);
306    }
307
308    // Inner
309

310    protected class ClassMapping
311    {
312       public final Class JavaDoc cls;
313       public final QName JavaDoc elementName;
314       public final QName JavaDoc typeName;
315       public final String JavaDoc schemaUrl;
316       public final GenericObjectModelProvider provider;
317
318       public ClassMapping(Class JavaDoc cls,
319                           String JavaDoc elementName,
320                           String JavaDoc typeName,
321                           String JavaDoc nsUri,
322                           String JavaDoc schemaUrl,
323                           GenericObjectModelProvider provider)
324       {
325          this.cls = cls;
326          if(elementName != null)
327          {
328             this.elementName = nsUri == null ? new QName JavaDoc(elementName) : new QName JavaDoc(nsUri, elementName);
329             this.typeName = null;
330          }
331          else if(typeName != null)
332          {
333             this.elementName = null;
334             this.typeName = nsUri == null ? new QName JavaDoc(typeName) : new QName JavaDoc(nsUri, typeName);
335          }
336          else
337          {
338             throw new JBossXBRuntimeException("Element or type name must not null for " + cls);
339          }
340
341          this.schemaUrl = schemaUrl;
342          this.provider = provider;
343       }
344
345       public boolean equals(Object JavaDoc o)
346       {
347          if(this == o)
348          {
349             return true;
350          }
351          if(o == null || getClass() != o.getClass())
352          {
353             return false;
354          }
355
356          final ClassMapping that = (ClassMapping)o;
357
358          if(cls != null ? !cls.equals(that.cls) : that.cls != null)
359          {
360             return false;
361          }
362          if(elementName != null ? !elementName.equals(that.elementName) : that.elementName != null)
363          {
364             return false;
365          }
366          if(provider != null ? !provider.equals(that.provider) : that.provider != null)
367          {
368             return false;
369          }
370          if(schemaUrl != null ? !schemaUrl.equals(that.schemaUrl) : that.schemaUrl != null)
371          {
372             return false;
373          }
374          if(typeName != null ? !typeName.equals(that.typeName) : that.typeName != null)
375          {
376             return false;
377          }
378
379          return true;
380       }
381
382       public int hashCode()
383       {
384          int result;
385          result = (cls != null ? cls.hashCode() : 0);
386          result = 29 * result + (elementName != null ? elementName.hashCode() : 0);
387          result = 29 * result + (typeName != null ? typeName.hashCode() : 0);
388          result = 29 * result + (schemaUrl != null ? schemaUrl.hashCode() : 0);
389          result = 29 * result + (provider != null ? provider.hashCode() : 0);
390          return result;
391       }
392    }
393
394    protected class FieldToWildcardMapping
395    {
396       public final Class JavaDoc cls;
397       public final ObjectLocalMarshaller marshaller;
398       public final FieldInfo fieldInfo;
399
400       public FieldToWildcardMapping(Class JavaDoc cls, String JavaDoc field, ObjectLocalMarshaller marshaller)
401       {
402          if(log.isTraceEnabled())
403          {
404             log.trace("new FieldToWildcardMapping: [cls=" +
405                cls.getName() +
406                ",field=" +
407                field +
408                "]"
409             );
410          }
411
412          this.cls = cls;
413          this.marshaller = marshaller;
414          this.fieldInfo = FieldInfo.getFieldInfo(cls, field, true);
415       }
416
417       public boolean equals(Object JavaDoc o)
418       {
419          if(this == o)
420          {
421             return true;
422          }
423          if(!(o instanceof FieldToWildcardMapping))
424          {
425             return false;
426          }
427
428          final FieldToWildcardMapping fieldToWildcardMapping = (FieldToWildcardMapping)o;
429
430          if(!cls.equals(fieldToWildcardMapping.cls))
431          {
432             return false;
433          }
434          if(!fieldInfo.getName().equals(fieldToWildcardMapping.fieldInfo.getName()))
435          {
436             return false;
437          }
438
439          return true;
440       }
441
442       public int hashCode()
443       {
444          int result;
445          result = cls.hashCode();
446          result = 29 * result + fieldInfo.getName().hashCode();
447          return result;
448       }
449    }
450
451    protected static interface Stack
452    {
453       void clear();
454
455       void push(Object JavaDoc o);
456
457       Object JavaDoc pop();
458
459       Object JavaDoc peek();
460
461       boolean isEmpty();
462    }
463
464    public static class StackImpl
465       implements Stack
466    {
467       private List JavaDoc list = new ArrayList JavaDoc();
468
469       public void clear()
470       {
471          list.clear();
472       }
473
474       public void push(Object JavaDoc o)
475       {
476          list.add(o);
477       }
478
479       public Object JavaDoc pop()
480       {
481          return list.remove(list.size() - 1);
482       }
483
484       public Object JavaDoc peek()
485       {
486          return list.get(list.size() - 1);
487       }
488
489       public boolean isEmpty()
490       {
491          return list.isEmpty();
492       }
493    }
494
495    public class ContentHandlerAdaptor
496       implements ContentHandler JavaDoc
497    {
498       public void setDocumentLocator(Locator JavaDoc locator)
499       {
500       }
501
502       public void startDocument() throws SAXException JavaDoc
503       {
504          // this is used to marshal a fragment of a document so we don't delegate startDocument
505
}
506
507       public void endDocument() throws SAXException JavaDoc
508       {
509          // this is used to marshal a fragment of a document so we don't delegate endDocument
510
}
511
512       public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) throws SAXException JavaDoc
513       {
514          content.startPrefixMapping(prefix, uri);
515       }
516
517       public void endPrefixMapping(String JavaDoc prefix) throws SAXException JavaDoc
518       {
519          content.endPrefixMapping(prefix);
520       }
521
522       public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc atts) throws SAXException JavaDoc
523       {
524          content.startElement(uri, localName, qName, atts);
525       }
526
527       public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc
528       {
529          content.endElement(uri, localName, qName);
530       }
531
532       public void characters(char ch[], int start, int length) throws SAXException JavaDoc
533       {
534          content.characters(ch, start, length);
535       }
536
537       public void ignorableWhitespace(char ch[], int start, int length) throws SAXException JavaDoc
538       {
539       }
540
541       public void processingInstruction(String JavaDoc target, String JavaDoc data) throws SAXException JavaDoc
542       {
543       }
544
545       public void skippedEntity(String JavaDoc name) throws SAXException JavaDoc
546       {
547       }
548    }
549 }
550
Popular Tags