001: /*
002: * Copyright (c) 1998-2007 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Emil Ong
028: */
029:
030: package com.caucho.jaxb.mapping;
031:
032: import com.caucho.jaxb.JAXBContextImpl;
033: import com.caucho.util.L10N;
034: import com.caucho.xml.stream.StaxUtil;
035:
036: import org.w3c.dom.Node;
037:
038: import static javax.xml.XMLConstants.*;
039:
040: import javax.xml.bind.JAXBElement;
041: import javax.xml.bind.JAXBException;
042: import javax.xml.bind.Marshaller;
043: import javax.xml.bind.Unmarshaller;
044:
045: import javax.xml.bind.annotation.XmlElement;
046: import javax.xml.bind.annotation.XmlElementWrapper;
047: import javax.xml.bind.annotation.XmlID;
048: import javax.xml.bind.annotation.XmlList;
049: import javax.xml.bind.annotation.XmlMimeType;
050: import javax.xml.bind.annotation.XmlNsForm;
051: import javax.xml.bind.annotation.XmlSchema;
052: import javax.xml.bind.annotation.XmlSchemaType;
053: import javax.xml.bind.annotation.XmlSchemaTypes;
054:
055: import javax.xml.namespace.QName;
056:
057: import javax.xml.stream.XMLStreamException;
058: import javax.xml.stream.XMLStreamReader;
059: import javax.xml.stream.XMLStreamWriter;
060:
061: import java.io.IOException;
062: import java.lang.annotation.Annotation;
063: import java.util.Collection;
064:
065: import com.caucho.jaxb.accessor.Accessor;
066: import com.caucho.jaxb.property.WrapperProperty;
067: import com.caucho.jaxb.skeleton.ClassSkeleton;
068:
069: public class ElementMapping extends SingleQNameXmlMapping {
070: private static final L10N L = new L10N(ElementMapping.class);
071:
072: public ElementMapping(JAXBContextImpl context, Accessor accessor)
073: throws JAXBException {
074: super (context, accessor);
075:
076: // XXX respect the type from the XmlElement annotation
077:
078: XmlElement element = accessor.getAnnotation(XmlElement.class);
079: boolean xmlList = (accessor.getAnnotation(XmlList.class) != null);
080:
081: XmlMimeType xmlMimeType = accessor
082: .getAnnotation(XmlMimeType.class);
083: String mimeType = null;
084:
085: if (xmlMimeType != null)
086: mimeType = xmlMimeType.value();
087:
088: _property = _context.createProperty(accessor.getGenericType(),
089: false, mimeType, xmlList);
090:
091: if (element != null) {
092: _qname = qnameFromXmlElement(element);
093: _nillable = element.nillable();
094: } else {
095: XmlSchema xmlSchema = accessor
096: .getPackageAnnotation(XmlSchema.class);
097:
098: if (xmlSchema != null
099: && xmlSchema.elementFormDefault() == XmlNsForm.QUALIFIED)
100: _qname = new QName(xmlSchema.namespace(), accessor
101: .getName());
102: else
103: _qname = new QName(accessor.getName());
104:
105: if (!_property.isXmlPrimitiveType())
106: _context.createSkeleton(accessor.getType());
107: }
108:
109: XmlElementWrapper wrapper = accessor
110: .getAnnotation(XmlElementWrapper.class);
111:
112: if (wrapper != null) {
113: WrapperProperty wrapperProperty = new WrapperProperty(
114: _property, wrapper, _qname.getNamespaceURI(),
115: _qname.getLocalPart());
116:
117: _property = wrapperProperty;
118: _qname = wrapperProperty.getWrapperQName();
119: }
120: }
121:
122: public void generateSchema(XMLStreamWriter out)
123: throws JAXBException, XMLStreamException {
124: XmlElement element = _accessor.getAnnotation(XmlElement.class);
125: XmlList xmlList = _accessor.getAnnotation(XmlList.class);
126:
127: if (xmlList != null) {
128: out.writeStartElement(XML_SCHEMA_PREFIX, "element",
129: W3C_XML_SCHEMA_NS_URI);
130: out.writeAttribute("name", _accessor.getName());
131:
132: out.writeStartElement(XML_SCHEMA_PREFIX, "simpleType",
133: W3C_XML_SCHEMA_NS_URI);
134:
135: out.writeEmptyElement(XML_SCHEMA_PREFIX, "list",
136: W3C_XML_SCHEMA_NS_URI);
137:
138: String itemType = StaxUtil.qnameToString(out, _property
139: .getSchemaType());
140:
141: out.writeAttribute("itemType", itemType);
142:
143: out.writeEndElement(); // simpleType
144:
145: out.writeEndElement(); // element
146: } else {
147: out.writeEmptyElement(XML_SCHEMA_PREFIX, "element",
148: W3C_XML_SCHEMA_NS_URI);
149:
150: if (!_generateRICompatibleSchema
151: || !_accessor.getType().isPrimitive()) {
152:
153: if (element != null) {
154: if (element.required())
155: out.writeAttribute("minOccurs", "1");
156: else
157: out.writeAttribute("minOccurs", "0");
158:
159: if (element.nillable())
160: out.writeAttribute("nillable", "true");
161: } else
162: out.writeAttribute("minOccurs", "0");
163: }
164:
165: if (_property.getMaxOccurs() != null)
166: out.writeAttribute("maxOccurs", _property
167: .getMaxOccurs());
168:
169: if ((element != null && element.nillable())
170: || Collection.class.isAssignableFrom(_accessor
171: .getType())
172: || (_accessor.getType().isArray() && !byte.class
173: .equals(_accessor.getType()
174: .getComponentType())))
175: out.writeAttribute("nillable", "true");
176:
177: String typeName = StaxUtil.qnameToString(out, _property
178: .getSchemaType());
179:
180: // jaxb/22d0
181: if (_accessor.getAnnotation(XmlID.class) != null)
182: typeName = "xsd:ID";
183:
184: // look for the XmlSchemaType
185: XmlSchemaType xmlSchemaType = _accessor
186: .getAnnotation(XmlSchemaType.class);
187:
188: if (xmlSchemaType == null) {
189: xmlSchemaType = _accessor
190: .getPackageAnnotation(XmlSchemaType.class);
191:
192: if (xmlSchemaType != null) {
193: if (XmlSchemaType.DEFAULT.class
194: .equals(xmlSchemaType.type()))
195: throw new JAXBException(
196: L
197: .l(
198: "@XmlSchemaType with name {0} on package {1} does not specify type",
199: xmlSchemaType.name(),
200: _accessor.getPackage()
201: .getName()));
202:
203: if (!_accessor.getType().equals(
204: xmlSchemaType.type()))
205: xmlSchemaType = null;
206: }
207: }
208:
209: if (xmlSchemaType == null) {
210: XmlSchemaTypes xmlSchemaTypes = _accessor
211: .getPackageAnnotation(XmlSchemaTypes.class);
212:
213: if (xmlSchemaTypes != null) {
214: XmlSchemaType[] array = xmlSchemaTypes.value();
215:
216: for (int i = 0; i < array.length; i++) {
217: xmlSchemaType = array[i];
218:
219: if (XmlSchemaType.DEFAULT.class
220: .equals(xmlSchemaType.type()))
221: throw new JAXBException(
222: L
223: .l(
224: "@XmlSchemaType with name {0} on package {1} does not specify type",
225: xmlSchemaType
226: .name(),
227: _accessor
228: .getPackage()
229: .getName()));
230:
231: if (_accessor.getType().equals(
232: xmlSchemaType.type()))
233: break;
234:
235: xmlSchemaType = null;
236: }
237: }
238: }
239:
240: if (xmlSchemaType != null) {
241: QName typeQName = new QName(xmlSchemaType.namespace(),
242: xmlSchemaType.name());
243: typeName = StaxUtil.qnameToString(out, typeQName);
244: }
245:
246: out.writeAttribute("type", typeName);
247: out.writeAttribute("name", _qname.getLocalPart());
248:
249: XmlMimeType xmlMimeType = _accessor
250: .getAnnotation(XmlMimeType.class);
251:
252: if (xmlMimeType != null) {
253: out.writeAttribute(XML_MIME_NS, "expectedContentTypes",
254: xmlMimeType.value());
255: }
256: }
257: }
258: }
|