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, Adam Megacz
028: */
029:
030: package com.caucho.jaxb.property;
031:
032: import java.io.IOException;
033:
034: import java.util.ArrayList;
035:
036: import static javax.xml.XMLConstants.*;
037:
038: import javax.xml.bind.JAXBException;
039: import javax.xml.bind.Marshaller;
040: import javax.xml.bind.Unmarshaller;
041: import javax.xml.bind.UnmarshalException;
042: import javax.xml.namespace.QName;
043: import javax.xml.stream.XMLStreamException;
044: import javax.xml.stream.XMLStreamReader;
045: import javax.xml.stream.XMLStreamWriter;
046:
047: import org.w3c.dom.Document;
048: import org.w3c.dom.Node;
049:
050: import com.caucho.jaxb.BinderImpl;
051: import com.caucho.jaxb.JAXBUtil;
052: import com.caucho.jaxb.NodeIterator;
053: import com.caucho.jaxb.mapping.Namer;
054: import com.caucho.jaxb.mapping.XmlMapping;
055: import com.caucho.jaxb.skeleton.ClassSkeleton;
056: import com.caucho.util.L10N;
057: import com.caucho.xml.stream.StaxUtil;
058:
059: /**
060: * helper class for properties that are represented as a "flat" CDATA block
061: */
062: public abstract class CDataProperty extends Property {
063: public static final L10N L = new L10N(CDataProperty.class);
064:
065: protected boolean _isNullable = true;
066:
067: protected abstract Object read(String in) throws IOException,
068: JAXBException;
069:
070: public String getMinOccurs() {
071: if (_isNullable)
072: return "0";
073:
074: return null;
075: }
076:
077: public Object readAttribute(XMLStreamReader in, int i)
078: throws IOException, JAXBException {
079: return read(in.getAttributeValue(i));
080: }
081:
082: public Object read(Unmarshaller u, XMLStreamReader in,
083: Object previous) throws IOException, XMLStreamException,
084: JAXBException {
085: return read(u, in, previous, null, null);
086: }
087:
088: public Object read(Unmarshaller u, XMLStreamReader in,
089: Object previous, ClassSkeleton attributed, Object parent)
090: throws IOException, XMLStreamException, JAXBException {
091: // Read any attributes that might represent fields in the parent object.
092: // Necessary for situations in which the read object has an XmlValue,
093: // but also has XmlAttributes.
094: if (attributed != null) {
095: for (int i = 0; i < in.getAttributeCount(); i++) {
096: QName attributeName = in.getAttributeName(i);
097: XmlMapping mapping = attributed
098: .getAttributeMapping(attributeName);
099:
100: if (mapping == null)
101: throw new UnmarshalException(L.l(
102: "Attribute {0} not found in {1}",
103: attributeName, attributed.getType()));
104:
105: mapping.readAttribute(in, i, parent);
106: }
107: }
108:
109: // Now read the actual value of the CData
110: in.next();
111:
112: Object ret = null;
113:
114: if (in.getEventType() == in.CHARACTERS) {
115: ret = read(in.getText());
116:
117: // essentially a nextTag() that handles end of document gracefully
118: while (in.hasNext()) {
119: in.next();
120:
121: if (in.getEventType() == in.END_ELEMENT)
122: break;
123: }
124: } else {
125: String nil = in.getAttributeValue(
126: W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
127:
128: if ("true".equals(nil)) // XXX nillable?
129: ret = getNilValue();
130:
131: else
132: ret = read(""); // Hack when we have something like <tag></tag>
133: }
134:
135: while (in.hasNext()) {
136: in.next();
137:
138: if (in.getEventType() == in.START_ELEMENT
139: || in.getEventType() == in.END_ELEMENT)
140: break;
141: }
142:
143: return ret;
144: }
145:
146: public Object bindFrom(BinderImpl binder, NodeIterator node,
147: Object previous) throws IOException, JAXBException {
148: Node root = node.getNode();
149:
150: Object ret = read(root.getTextContent());
151:
152: binder.bind(ret, root);
153:
154: return ret;
155: }
156:
157: public abstract String write(Object in) throws IOException,
158: JAXBException;
159:
160: public void write(Marshaller m, XMLStreamWriter out, Object value,
161: Namer namer, Object obj, ArrayList<XmlMapping> attributes)
162: throws IOException, XMLStreamException, JAXBException {
163: // This checks if obj != null (as opposed to value != null) because we
164: // may actually want to write something if the value is null. For example,
165: // we may write an xsi:nil="true".
166: if (obj != null) {
167: QName qname = namer.getQName(value);
168:
169: if (attributes != null || value != null)
170: StaxUtil.writeStartElement(out, qname);
171:
172: if (attributes != null) {
173: for (int i = 0; i < attributes.size(); i++) {
174: attributes.get(i).write(m, out, obj);
175: }
176: }
177:
178: if (attributes != null || value != null) {
179: out.writeCharacters(write(value));
180: StaxUtil.writeEndElement(out, qname);
181: }
182: }
183: }
184:
185: public void write(Marshaller m, XMLStreamWriter out, Object value,
186: Namer namer) throws IOException, XMLStreamException,
187: JAXBException {
188: write(m, out, value, namer, null);
189: }
190:
191: public void write(Marshaller m, XMLStreamWriter out, Object value,
192: Namer namer, Object obj) throws IOException,
193: XMLStreamException, JAXBException {
194: if (value != null) {
195: QName qname = namer.getQName(value);
196:
197: StaxUtil.writeStartElement(out, qname);
198: out.writeCharacters(write(value));
199: StaxUtil.writeEndElement(out, qname);
200: }
201: }
202:
203: public Node bindTo(BinderImpl binder, Node node, Object value,
204: Namer namer) throws IOException, JAXBException {
205: QName qname = namer.getQName(value);
206: QName name = JAXBUtil.qnameFromNode(node);
207:
208: if (!name.equals(qname)) {
209: Document doc = node.getOwnerDocument();
210: node = JAXBUtil.elementFromQName(qname, doc);
211: }
212:
213: node.setTextContent(write(value));
214:
215: binder.bind(value, node);
216:
217: return node;
218: }
219:
220: public String toString() {
221: return this.getClass().getSimpleName();
222: }
223: }
|