001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: package com.sun.tools.xjc.generator.bean.field;
037:
038: import java.util.ArrayList;
039: import java.util.Arrays;
040: import java.util.List;
041:
042: import com.sun.codemodel.JBlock;
043: import com.sun.codemodel.JClass;
044: import com.sun.codemodel.JExpr;
045: import com.sun.codemodel.JExpression;
046: import com.sun.codemodel.JForLoop;
047: import com.sun.codemodel.JMethod;
048: import com.sun.codemodel.JOp;
049: import com.sun.codemodel.JType;
050: import com.sun.codemodel.JVar;
051: import com.sun.tools.xjc.generator.bean.ClassOutlineImpl;
052: import com.sun.tools.xjc.generator.bean.MethodWriter;
053: import com.sun.tools.xjc.model.CPropertyInfo;
054:
055: /**
056: * Realizes a property as an "indexed property"
057: * as specified in the JAXB spec.
058: *
059: * <p>
060: * We will generate the following set of methods:
061: * <pre>
062: * T[] getX();
063: * T getX( int idx );
064: * void setX(T[] values);
065: * void setX( int idx, T value );
066: * </pre>
067: *
068: * We still use List as our back storage.
069: * This renderer also handles boxing/unboxing if
070: * T is a boxed type.
071: *
072: * @author
073: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
074: */
075: final class ArrayField extends AbstractListField {
076:
077: class Accessor extends AbstractListField.Accessor {
078: protected Accessor(JExpression $target) {
079: super ($target);
080: }
081:
082: public void toRawValue(JBlock block, JVar $var) {
083: block.assign($var, codeModel.ref(Arrays.class)
084: .staticInvoke("asList")
085: .arg($target.invoke($getAll)));
086: }
087:
088: public void fromRawValue(JBlock block, String uniqueName,
089: JExpression $var) {
090: block.invoke($target, $setAll).arg(
091: $var.invoke("toArray").arg(
092: JExpr.newArray(exposedType, $var
093: .invoke("size"))));
094: }
095: }
096:
097: private JMethod $setAll;
098:
099: private JMethod $getAll;
100:
101: ArrayField(ClassOutlineImpl context, CPropertyInfo prop) {
102: super (context, prop, false);
103: generate();
104: }
105:
106: public void generateAccessors() {
107:
108: MethodWriter writer = outline.createMethodWriter();
109: Accessor acc = create(JExpr._this ());
110:
111: JVar $idx, $value;
112: JBlock body;
113: JType arrayType = exposedType.array();
114:
115: // [RESULT] T[] getX() {
116: // if( <var>==null ) return new T[0];
117: // return (T[]) <var>.toArray(new T[<var>.size()]);
118: // }
119: $getAll = writer.declareMethod(exposedType.array(), "get"
120: + prop.getName(true));
121: writer.javadoc().append(prop.javadoc);
122: body = $getAll.body();
123:
124: body._if(acc.ref(true).eq(JExpr._null()))._then()._return(
125: JExpr.newArray(exposedType, 0));
126:
127: if (primitiveType == null) {
128: body._return(JExpr.cast(arrayType, acc.ref(true).invoke(
129: "toArray").arg(
130: JExpr.newArray(implType, acc.ref(true).invoke(
131: "size")))));
132: } else {
133: // need to copy them manually to unbox values
134: // [RESULT]
135: // T[] r = new T[<ref>.size()];
136: // for( int i=0; i<r.length; i++ )
137: // r[i] = unbox(<ref>.get(i));
138: JVar $r = body.decl(exposedType.array(), "r",
139: JExpr.newArray(exposedType, acc.ref(true).invoke(
140: "size")));
141: JForLoop loop = body._for();
142: JVar $i = loop.init(codeModel.INT, "__i", JExpr.lit(0));
143: loop.test($i.lt($r.ref("length")));
144: loop.update($i.incr());
145: loop.body().assign(
146: $r.component($i),
147: primitiveType.unwrap(acc.ref(true).invoke("get")
148: .arg($i)));
149: body._return($r);
150: }
151:
152: List<Object> returnTypes = listPossibleTypes(prop);
153: writer.javadoc().addReturn().append("array of\n").append(
154: returnTypes);
155:
156: // [RESULT]
157: // ET getX(int idx) {
158: // if( <var>==null ) throw new IndexOutOfBoundsException();
159: // return unbox(<var>.get(idx));
160: // }
161: JMethod $get = writer.declareMethod(exposedType, "get"
162: + prop.getName(true));
163: $idx = writer.addParameter(codeModel.INT, "idx");
164:
165: $get.body()._if(acc.ref(true).eq(JExpr._null()))._then()
166: ._throw(
167: JExpr._new(codeModel
168: .ref(IndexOutOfBoundsException.class)));
169:
170: writer.javadoc().append(prop.javadoc);
171: $get.body()._return(
172: acc.unbox(acc.ref(true).invoke("get").arg($idx)));
173:
174: writer.javadoc().addReturn().append("one of\n").append(
175: returnTypes);
176:
177: // [RESULT] int getXLength() {
178: // if( <var>==null ) throw new IndexOutOfBoundsException();
179: // return <ref>.size();
180: // }
181: JMethod $getLength = writer.declareMethod(codeModel.INT, "get"
182: + prop.getName(true) + "Length");
183: $getLength.body()._if(acc.ref(true).eq(JExpr._null()))._then()
184: ._return(JExpr.lit(0));
185: $getLength.body()._return(acc.ref(true).invoke("size"));
186:
187: // [RESULT] void setX(ET[] values) {
188: // clear();
189: // int len = values.length;
190: // for( int i=0; i<len; i++ )
191: // <ref>.add(values[i]);
192: // }
193: $setAll = writer.declareMethod(codeModel.VOID, "set"
194: + prop.getName(true));
195:
196: writer.javadoc().append(prop.javadoc);
197:
198: $value = writer.addParameter(exposedType.array(), "values");
199: $setAll.body().invoke(acc.ref(false), "clear");
200: JVar $len = $setAll.body().decl(codeModel.INT, "len",
201: $value.ref("length"));
202: JForLoop _for = $setAll.body()._for();
203: JVar $i = _for.init(codeModel.INT, "i", JExpr.lit(0));
204: _for.test(JOp.lt($i, $len));
205: _for.update($i.incr());
206: _for.body().invoke(acc.ref(true), "add").arg(
207: castToImplType(acc.box($value.component($i))));
208:
209: writer.javadoc().addParam($value).append(
210: "allowed objects are\n").append(returnTypes);
211:
212: // [RESULT] ET setX(int,ET)
213: JMethod $set = writer.declareMethod(exposedType, "set"
214: + prop.getName(true));
215: $idx = writer.addParameter(codeModel.INT, "idx");
216: $value = writer.addParameter(exposedType, "value");
217:
218: writer.javadoc().append(prop.javadoc);
219:
220: body = $set.body();
221: body._return(acc.unbox(acc.ref(true).invoke("set").arg($idx)
222: .arg(castToImplType(acc.box($value)))));
223:
224: writer.javadoc().addParam($value).append("allowed object is\n")
225: .append(returnTypes);
226: }
227:
228: protected JClass getCoreListType() {
229: return codeModel.ref(ArrayList.class).narrow(
230: exposedType.boxify());
231: }
232:
233: public Accessor create(JExpression targetObject) {
234: return new Accessor(targetObject);
235: }
236: }
|