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:
035: import org.w3c.dom.Node;
036:
037: import static javax.xml.XMLConstants.*;
038:
039: import javax.xml.bind.JAXBElement;
040: import javax.xml.bind.JAXBException;
041: import javax.xml.bind.Marshaller;
042: import javax.xml.bind.Unmarshaller;
043: import javax.xml.bind.UnmarshalException;
044:
045: import javax.xml.bind.annotation.XmlElementRef;
046:
047: import javax.xml.namespace.QName;
048:
049: import javax.xml.stream.XMLStreamException;
050: import javax.xml.stream.XMLStreamReader;
051: import javax.xml.stream.XMLStreamWriter;
052:
053: import java.lang.annotation.Annotation;
054:
055: import java.lang.reflect.ParameterizedType;
056: import java.lang.reflect.Type;
057:
058: import java.io.IOException;
059:
060: import java.util.Collection;
061: import java.util.HashMap;
062: import java.util.List;
063: import java.util.Map;
064:
065: import com.caucho.jaxb.accessor.Accessor;
066:
067: import com.caucho.jaxb.property.ArrayProperty;
068: import com.caucho.jaxb.property.ListProperty;
069: import com.caucho.jaxb.property.MultiProperty;
070: import com.caucho.jaxb.property.Property;
071:
072: import com.caucho.jaxb.skeleton.ClassSkeleton;
073:
074: public class ElementRefMapping extends XmlMapping {
075: private static final L10N L = new L10N(ElementRefMapping.class);
076:
077: public ElementRefMapping(JAXBContextImpl context, Accessor accessor) {
078: super (context, accessor);
079: }
080:
081: // XXX this method probably shouldn't have side effects
082: public void putQNames(Map<QName, XmlMapping> map)
083: throws JAXBException {
084: Class cl = _accessor.getType();
085:
086: // XXX process this
087: XmlElementRef elementRef = _accessor
088: .getAnnotation(XmlElementRef.class);
089:
090: if (Collection.class.isAssignableFrom(cl)) {
091: if (_accessor.getGenericType() instanceof ParameterizedType) {
092: ParameterizedType ptype = (ParameterizedType) _accessor
093: .getGenericType();
094: Type[] args = ptype.getActualTypeArguments();
095:
096: if (args.length != 1)
097: throw new JAXBException(
098: L
099: .l(
100: "Collections annotated with @XmlElementRef must be parameterized: {0}",
101: _accessor.getName()));
102: else if (args[0] instanceof Class)
103: cl = (Class) args[0];
104: else
105: throw new JAXBException(
106: L
107: .l(
108: "Unknown type {0} on field or property {1}",
109: args[0], _accessor
110: .getName()));
111: } else
112: throw new JAXBException(
113: L
114: .l(
115: "Collections annotated with @XmlElementRef must be parameterized: {0}",
116: _accessor.getName()));
117: } else if (cl.isArray())
118: cl = cl.getComponentType();
119:
120: List<ClassSkeleton> skeletons = _context.getRootElements(cl);
121:
122: if (skeletons.size() == 0)
123: throw new JAXBException(
124: L
125: .l(
126: "The type ({0}) of field {1} is unknown to this context",
127: cl, _accessor.getName()));
128:
129: Map<QName, Property> qnameToPropertyMap = new HashMap<QName, Property>();
130: Map<Class, Property> classToPropertyMap = new HashMap<Class, Property>();
131:
132: for (int i = 0; i < skeletons.size(); i++) {
133: ClassSkeleton skeleton = skeletons.get(i);
134: map.put(skeleton.getElementName(), this );
135:
136: QName qname = skeleton.getElementName();
137: Property property = _context.createProperty(skeleton
138: .getType());
139:
140: qnameToPropertyMap.put(qname, property);
141: classToPropertyMap.put(skeleton.getType(), property);
142: }
143:
144: _property = new MultiProperty(qnameToPropertyMap,
145: classToPropertyMap);
146:
147: if (List.class.isAssignableFrom(_accessor.getType()))
148: _property = new ListProperty(_property);
149:
150: else if (_accessor.getType().isArray()) {
151: Class cType = _accessor.getType().getComponentType();
152: _property = ArrayProperty.createArrayProperty(_property,
153: cType);
154: }
155: }
156:
157: public void generateSchema(XMLStreamWriter out)
158: throws JAXBException, XMLStreamException {
159: out.writeEmptyElement(XML_SCHEMA_PREFIX, "element",
160: W3C_XML_SCHEMA_NS_URI);
161:
162: XmlElementRef elementRef = _accessor
163: .getAnnotation(XmlElementRef.class);
164:
165: if (_property.getMaxOccurs() != null)
166: out.writeAttribute("maxOccurs", _property.getMaxOccurs());
167:
168: // XXX
169: out.writeAttribute("ref", "XXX");
170: }
171:
172: public QName getQName(Object obj) throws JAXBException {
173: if (obj instanceof JAXBElement) {
174: JAXBElement element = (JAXBElement) obj;
175:
176: return element.getName();
177: } else {
178: ClassSkeleton skeleton = _context
179: .findSkeletonForObject(obj);
180:
181: if (skeleton == null || skeleton.getElementName() == null)
182: throw new JAXBException(L.l(
183: "Cannot find root element name for object {0}",
184: obj));
185:
186: return skeleton.getElementName();
187: }
188: }
189: }
|