001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.xjc.dv;
019:
020: import java.util.logging.Level;
021: import java.util.logging.Logger;
022:
023: import javax.xml.bind.DatatypeConverter;
024: import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
025: import javax.xml.namespace.NamespaceContext;
026: import javax.xml.namespace.QName;
027:
028: import org.xml.sax.ErrorHandler;
029:
030: import com.sun.codemodel.JConditional;
031: import com.sun.codemodel.JDefinedClass;
032: import com.sun.codemodel.JDocComment;
033: import com.sun.codemodel.JExpr;
034: import com.sun.codemodel.JExpression;
035: import com.sun.codemodel.JFieldRef;
036: import com.sun.codemodel.JMethod;
037: import com.sun.codemodel.JOp;
038: import com.sun.codemodel.JType;
039: import com.sun.tools.xjc.Options;
040: import com.sun.tools.xjc.Plugin;
041: import com.sun.tools.xjc.outline.ClassOutline;
042: import com.sun.tools.xjc.outline.FieldOutline;
043: import com.sun.tools.xjc.outline.Outline;
044: import com.sun.tools.xjc.util.NamespaceContextAdapter;
045: import com.sun.xml.xsom.XSAttributeDecl;
046: import com.sun.xml.xsom.XSAttributeUse;
047: import com.sun.xml.xsom.XSElementDecl;
048: import com.sun.xml.xsom.XSParticle;
049: import com.sun.xml.xsom.XSTerm;
050: import com.sun.xml.xsom.XSType;
051: import com.sun.xml.xsom.XmlString;
052:
053: import org.apache.cxf.common.logging.LogUtils;
054:
055: /**
056: * Modifies the JAXB code model to initialise fields mapped from schema elements
057: * with their default value.
058: */
059: public class DefaultValuePlugin extends Plugin {
060:
061: private static final Logger LOG = LogUtils
062: .getL7dLogger(DefaultValuePlugin.class);
063:
064: public DefaultValuePlugin() {
065: }
066:
067: public String getOptionName() {
068: return "Xdv";
069: }
070:
071: public String getUsage() {
072: return " -Xdv : Initialize fields mapped from elements with their default values";
073: }
074:
075: public boolean run(Outline outline, Options opt,
076: ErrorHandler errorHandler) {
077: LOG.fine("Running default value plugin.");
078: for (ClassOutline co : outline.getClasses()) {
079: for (FieldOutline f : co.getDeclaredFields()) {
080:
081: // Use XML schema object model to determine if field is mapped
082: // from an element (attributes default values are handled
083: // natively) and get its default value.
084:
085: XmlString xmlDefaultValue = null;
086: XSType xsType = null;
087: boolean isElement = false;
088:
089: if (f.getPropertyInfo().getSchemaComponent() instanceof XSParticle) {
090: XSParticle particle = (XSParticle) f
091: .getPropertyInfo().getSchemaComponent();
092: XSTerm term = particle.getTerm();
093: XSElementDecl element = null;
094:
095: if (term.isElementDecl()) {
096: element = particle.getTerm().asElementDecl();
097: xmlDefaultValue = element.getDefaultValue();
098: xsType = element.getType();
099: isElement = true;
100: }
101: } else if (f.getPropertyInfo().getSchemaComponent() instanceof XSAttributeUse) {
102: XSAttributeUse attributeUse = (XSAttributeUse) f
103: .getPropertyInfo().getSchemaComponent();
104: XSAttributeDecl decl = attributeUse.getDecl();
105: xmlDefaultValue = decl.getDefaultValue();
106: xsType = decl.getType();
107: }
108:
109: if (null == xmlDefaultValue
110: || null == xmlDefaultValue.value) {
111: continue;
112: }
113:
114: JExpression dvExpr = getDefaultValueExpression(f, co,
115: outline, xsType, isElement, xmlDefaultValue);
116:
117: if (null == dvExpr) {
118: continue;
119: }
120:
121: updateGetter(co, f, co.implClass, dvExpr);
122:
123: }
124: }
125:
126: return true;
127: }
128:
129: JExpression getDefaultValueExpression(FieldOutline f,
130: ClassOutline co, Outline outline, XSType xsType,
131: boolean isElement, XmlString xmlDefaultValue) {
132: JType type = f.getRawType();
133: String typeName = type.fullName();
134: String defaultValue = xmlDefaultValue.value;
135:
136: JExpression dv = null;
137:
138: if ("java.lang.Boolean".equals(typeName) && isElement) {
139: dv = JExpr
140: .direct(Boolean.valueOf(defaultValue) ? "Boolean.TRUE"
141: : "Boolean.FALSE");
142: } else if ("java.lang.Byte".equals(typeName) && isElement) {
143: dv = JExpr._new(type).arg(
144: JExpr.cast(type.unboxify(), JExpr.lit(new Byte(
145: Short.valueOf(defaultValue).byteValue()))));
146: } else if ("java.lang.Double".equals(typeName) && isElement) {
147: dv = JExpr._new(type).arg(
148: JExpr.lit(new Double(Double.valueOf(defaultValue)
149: .doubleValue())));
150: } else if ("java.lang.Float".equals(typeName) && isElement) {
151: dv = JExpr._new(type).arg(
152: JExpr.lit(new Float(Float.valueOf(defaultValue)
153: .floatValue())));
154: } else if ("java.lang.Integer".equals(typeName) && isElement) {
155: dv = JExpr._new(type).arg(
156: JExpr.lit(new Integer(Integer.valueOf(defaultValue)
157: .intValue())));
158: } else if ("java.lang.Long".equals(typeName) && isElement) {
159: dv = JExpr._new(type).arg(
160: JExpr.lit(new Long(Long.valueOf(defaultValue)
161: .longValue())));
162: } else if ("java.lang.Short".equals(typeName) && isElement) {
163: dv = JExpr
164: ._new(type)
165: .arg(
166: JExpr
167: .cast(
168: type.unboxify(),
169: JExpr
170: .lit(new Short(
171: Short
172: .valueOf(
173: defaultValue)
174: .shortValue()))));
175: } else if ("java.lang.String".equals(type.fullName())
176: && isElement) {
177: dv = JExpr.lit(defaultValue);
178: } else if ("java.math.BigInteger".equals(type.fullName())
179: && isElement) {
180: dv = JExpr._new(type).arg(JExpr.lit(defaultValue));
181: } else if ("java.math.BigDecimal".equals(type.fullName())
182: && isElement) {
183: dv = JExpr._new(type).arg(JExpr.lit(defaultValue));
184: } else if ("byte[]".equals(type.fullName())
185: && xsType.isSimpleType() && isElement) {
186: while (!"anySimpleType".equals(xsType.getBaseType()
187: .getName())) {
188: xsType = xsType.getBaseType();
189: }
190: if ("base64Binary".equals(xsType.getName())) {
191: dv = outline.getCodeModel()
192: .ref(DatatypeConverter.class).staticInvoke(
193: "parseBase64Binary").arg(defaultValue);
194: } else if ("hexBinary".equals(xsType.getName())) {
195: dv = JExpr._new(
196: outline.getCodeModel().ref(
197: HexBinaryAdapter.class)).invoke(
198: "unmarshal").arg(defaultValue);
199: }
200: } else if ("javax.xml.namespace.QName".equals(typeName)) {
201: NamespaceContext nsc = new NamespaceContextAdapter(
202: xmlDefaultValue);
203: QName qn = DatatypeConverter.parseQName(
204: xmlDefaultValue.value, nsc);
205: dv = JExpr._new(outline.getCodeModel().ref(QName.class))
206: .arg(qn.getNamespaceURI()).arg(qn.getLocalPart())
207: .arg(qn.getPrefix());
208: } else if ("javax.xml.datatype.Duration".equals(typeName)) {
209: dv = outline.getCodeModel().ref(
210: org.apache.cxf.jaxb.DatatypeFactory.class)
211: .staticInvoke("createDuration").arg(defaultValue);
212: }
213: // TODO: GregorianCalendar, ...
214: return dv;
215: }
216:
217: private void updateGetter(ClassOutline co, FieldOutline fo,
218: JDefinedClass dc, JExpression dvExpr) {
219:
220: String fieldName = fo.getPropertyInfo().getName(false);
221: JType type = fo.getRawType();
222: String typeName = type.fullName();
223:
224: String getterName = ("java.lang.Boolean".equals(typeName) ? "is"
225: : "get")
226: + fo.getPropertyInfo().getName(true);
227:
228: JMethod method = dc.getMethod(getterName, new JType[0]);
229: JDocComment doc = method.javadoc();
230: int mods = method.mods().getValue();
231: JType mtype = method.type();
232:
233: if (LOG.isLoggable(Level.FINE)) {
234: LOG.fine("Updating getter: " + getterName);
235: }
236: // remove existing method and define new one
237:
238: dc.methods().remove(method);
239:
240: method = dc.method(mods, mtype, getterName);
241: method.javadoc().append(doc);
242:
243: JFieldRef fr = JExpr.ref(fieldName);
244:
245: JExpression test = JOp.eq(JExpr._null(), fr);
246: JConditional jc = method.body()._if(test);
247: jc._then()._return(dvExpr);
248: jc._else()._return(fr);
249: }
250:
251: }
|