001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.internal.xjc.generator.bean.field;
027:
028: import java.util.ArrayList;
029: import java.util.Arrays;
030: import java.util.List;
031:
032: import com.sun.codemodel.internal.JBlock;
033: import com.sun.codemodel.internal.JClass;
034: import com.sun.codemodel.internal.JExpr;
035: import com.sun.codemodel.internal.JExpression;
036: import com.sun.codemodel.internal.JForLoop;
037: import com.sun.codemodel.internal.JMethod;
038: import com.sun.codemodel.internal.JOp;
039: import com.sun.codemodel.internal.JType;
040: import com.sun.codemodel.internal.JVar;
041: import com.sun.tools.internal.xjc.generator.bean.ClassOutlineImpl;
042: import com.sun.tools.internal.xjc.generator.bean.MethodWriter;
043: import com.sun.tools.internal.xjc.model.CPropertyInfo;
044:
045: /**
046: * Realizes a property as an "indexed property"
047: * as specified in the JAXB spec.
048: *
049: * <p>
050: * We will generate the following set of methods:
051: * <pre>
052: * T[] getX();
053: * T getX( int idx );
054: * void setX(T[] values);
055: * void setX( int idx, T value );
056: * </pre>
057: *
058: * We still use List as our back storage.
059: * This renderer also handles boxing/unboxing if
060: * T is a boxed type.
061: *
062: * @author
063: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
064: */
065: final class ArrayField extends AbstractListField {
066:
067: class Accessor extends AbstractListField.Accessor {
068: protected Accessor(JExpression $target) {
069: super ($target);
070: }
071:
072: public void toRawValue(JBlock block, JVar $var) {
073: block.assign($var, codeModel.ref(Arrays.class)
074: .staticInvoke("asList")
075: .arg($target.invoke($getAll)));
076: }
077:
078: public void fromRawValue(JBlock block, String uniqueName,
079: JExpression $var) {
080: block.invoke($target, $setAll).arg(
081: $var.invoke("toArray").arg(
082: JExpr.newArray(exposedType, $var
083: .invoke("size"))));
084: }
085: }
086:
087: private JMethod $setAll;
088:
089: private JMethod $getAll;
090:
091: ArrayField(ClassOutlineImpl context, CPropertyInfo prop) {
092: super (context, prop, false);
093: generate();
094: }
095:
096: public void generateAccessors() {
097:
098: MethodWriter writer = outline.createMethodWriter();
099: Accessor acc = create(JExpr._this ());
100:
101: JVar $idx, $value;
102: JBlock body;
103: JType arrayType = exposedType.array();
104:
105: // [RESULT] T[] getX() {
106: // if( <var>==null ) return new T[0];
107: // return (T[]) <var>.toArray(new T[<var>.size()]);
108: // }
109: $getAll = writer.declareMethod(exposedType.array(), "get"
110: + prop.getName(true));
111: writer.javadoc().append(prop.javadoc);
112: body = $getAll.body();
113:
114: body._if(acc.ref(true).eq(JExpr._null()))._then()._return(
115: JExpr.newArray(exposedType, 0));
116:
117: if (primitiveType == null) {
118: body._return(JExpr.cast(arrayType, acc.ref(true).invoke(
119: "toArray").arg(
120: JExpr.newArray(implType, acc.ref(true).invoke(
121: "size")))));
122: } else {
123: // need to copy them manually to unbox values
124: // [RESULT]
125: // T[] r = new T[<ref>.size()];
126: // for( int i=0; i<r.length; i++ )
127: // r[i] = unbox(<ref>.get(i));
128: JVar $r = body.decl(exposedType.array(), "r",
129: JExpr.newArray(exposedType, acc.ref(true).invoke(
130: "size")));
131: JForLoop loop = body._for();
132: JVar $i = loop.init(codeModel.INT, "__i", JExpr.lit(0));
133: loop.test($i.lt($r.ref("length")));
134: loop.update($i.incr());
135: loop.body().assign(
136: $r.component($i),
137: primitiveType.unwrap(acc.ref(true).invoke("get")
138: .arg($i)));
139: body._return($r);
140: }
141:
142: List<Object> returnTypes = listPossibleTypes(prop);
143: writer.javadoc().addReturn().append("array of\n").append(
144: returnTypes);
145:
146: // [RESULT]
147: // ET getX(int idx) {
148: // if( <var>==null ) throw new IndexOutOfBoundsException();
149: // return unbox(<var>.get(idx));
150: // }
151: JMethod $get = writer.declareMethod(exposedType, "get"
152: + prop.getName(true));
153: $idx = writer.addParameter(codeModel.INT, "idx");
154:
155: $get.body()._if(acc.ref(true).eq(JExpr._null()))._then()
156: ._throw(
157: JExpr._new(codeModel
158: .ref(IndexOutOfBoundsException.class)));
159:
160: writer.javadoc().append(prop.javadoc);
161: $get.body()._return(
162: acc.unbox(acc.ref(true).invoke("get").arg($idx)));
163:
164: writer.javadoc().addReturn().append("one of\n").append(
165: returnTypes);
166:
167: // [RESULT] int getXLength() {
168: // if( <var>==null ) throw new IndexOutOfBoundsException();
169: // return <ref>.size();
170: // }
171: JMethod $getLength = writer.declareMethod(codeModel.INT, "get"
172: + prop.getName(true) + "Length");
173: $getLength.body()._if(acc.ref(true).eq(JExpr._null()))._then()
174: ._return(JExpr.lit(0));
175: $getLength.body()._return(acc.ref(true).invoke("size"));
176:
177: // [RESULT] void setX(ET[] values) {
178: // clear();
179: // int len = values.length;
180: // for( int i=0; i<len; i++ )
181: // <ref>.add(values[i]);
182: // }
183: $setAll = writer.declareMethod(codeModel.VOID, "set"
184: + prop.getName(true));
185:
186: writer.javadoc().append(prop.javadoc);
187:
188: $value = writer.addParameter(exposedType.array(), "values");
189: $setAll.body().invoke(acc.ref(false), "clear");
190: JVar $len = $setAll.body().decl(codeModel.INT, "len",
191: $value.ref("length"));
192: JForLoop _for = $setAll.body()._for();
193: JVar $i = _for.init(codeModel.INT, "i", JExpr.lit(0));
194: _for.test(JOp.lt($i, $len));
195: _for.update($i.incr());
196: _for.body().invoke(acc.ref(true), "add").arg(
197: castToImplType(acc.box($value.component($i))));
198:
199: writer.javadoc().addParam($value).append(
200: "allowed objects are\n").append(returnTypes);
201:
202: // [RESULT] ET setX(int,ET)
203: JMethod $set = writer.declareMethod(exposedType, "set"
204: + prop.getName(true));
205: $idx = writer.addParameter(codeModel.INT, "idx");
206: $value = writer.addParameter(exposedType, "value");
207:
208: writer.javadoc().append(prop.javadoc);
209:
210: body = $set.body();
211: body._return(acc.unbox(acc.ref(true).invoke("set").arg($idx)
212: .arg(castToImplType(acc.box($value)))));
213:
214: writer.javadoc().addParam($value).append("allowed object is\n")
215: .append(returnTypes);
216: }
217:
218: protected JClass getCoreListType() {
219: return codeModel.ref(ArrayList.class).narrow(
220: exposedType.boxify());
221: }
222:
223: public Accessor create(JExpression targetObject) {
224: return new Accessor(targetObject);
225: }
226: }
|