1 /* 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.internal.xjc.generator.bean.field; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 31 import com.sun.codemodel.internal.JBlock; 32 import com.sun.codemodel.internal.JClass; 33 import com.sun.codemodel.internal.JExpr; 34 import com.sun.codemodel.internal.JExpression; 35 import com.sun.codemodel.internal.JMethod; 36 import com.sun.codemodel.internal.JType; 37 import com.sun.codemodel.internal.JVar; 38 import com.sun.tools.internal.xjc.generator.bean.ClassOutlineImpl; 39 import com.sun.tools.internal.xjc.generator.bean.MethodWriter; 40 import com.sun.tools.internal.xjc.model.CElement; 41 import com.sun.tools.internal.xjc.model.CPropertyInfo; 42 import com.sun.tools.internal.xjc.model.CReferencePropertyInfo; 43 import com.sun.tools.internal.xjc.model.Aspect; 44 import com.sun.xml.internal.bind.api.impl.NameConverter; 45 import java.io.Serializable; 46 import java.util.Set; 47 48 /** 49 * Realizes a property as an untyped {@link List}. 50 * 51 * <pre> 52 * List getXXX(); 53 * </pre> 54 * 55 * <h2>Default value handling</h2> 56 * <p> 57 * Since unmarshaller just adds new values into the storage, 58 * we can't fill the storage by default values at the time of 59 * instanciation. (or oherwise values found in the document will 60 * be appended to default values, where it should overwrite them.) 61 * <p> 62 * Therefore, when the object is created, the storage will be empty. 63 * When the getXXX method is called, we'll check if the storage is 64 * modified in anyway. If it is modified, it must mean that the values 65 * are found in the document, so we just return it. 66 * 67 * Otherwise we will fill in default values and return it to the user. 68 * 69 * <p> 70 * When a list has default values, its dirty flag is set to true. 71 * Marshaller will check this and treat it appropriately. 72 * 73 * 74 * @author 75 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 76 */ 77 public class NoExtendedContentField extends AbstractListField { 78 79 /** 80 * A concrete class that implements the List interface. 81 * An instance of this class will be used to store data 82 * for this field. 83 */ 84 private final JClass coreList; 85 86 /** List getFIELD() method. */ 87 private JMethod $get; 88 89 /** 90 * @param coreList 91 * A concrete class that implements the List interface. 92 * An instance of this class will be used to store data 93 * for this field. 94 */ 95 protected NoExtendedContentField(ClassOutlineImpl context, CPropertyInfo prop, JClass coreList) { 96 // the JAXB runtime picks ArrayList if the signature is List, 97 // so don't do eager allocation if it's ArrayList. 98 // otherwise we need to do eager allocation so that the collection type specified by the user 99 // will be used. 100 super(context, prop, false); 101 this.coreList = coreList; 102 generate(); 103 } 104 105 protected final JClass getCoreListType() { 106 return coreList; 107 } 108 109 @Override 110 public void generateAccessors() { 111 final MethodWriter writer = outline.createMethodWriter(); 112 final Accessor acc = create(JExpr._this()); 113 114 // [RESULT] 115 // List getXXX() { 116 // return <ref>; 117 // } 118 $get = writer.declareMethod(listT,"get"+prop.getName(true)); 119 writer.javadoc().append(prop.javadoc); 120 JBlock block = $get.body(); 121 fixNullRef(block); // avoid using an internal getter 122 block._return(acc.ref(true)); 123 124 String pname = NameConverter.standard.toVariableName(prop.getName(true)); 125 writer.javadoc().append( 126 "Gets the value of the "+pname+" property.\n\n"+ 127 "<p>\n" + 128 "This accessor method returns a reference to the live list,\n" + 129 "not a snapshot. Therefore any modification you make to the\n" + 130 "returned list will be present inside the JAXB object.\n" + 131 "This is why there is not a <CODE>set</CODE> method for the " +pname+ " property.\n" + 132 "\n"+ 133 "<p>\n" + 134 "For example, to add a new item, do as follows:\n"+ 135 "<pre>\n"+ 136 " get"+prop.getName(true)+"().add(newItem);\n"+ 137 "</pre>\n"+ 138 "\n\n" 139 ); 140 141 writer.javadoc().append( 142 "<p>\n" + 143 "Objects of the following type(s) are allowed in the list\n") 144 .append(listPossibleTypes(prop)); 145 } 146 147 public Accessor create(JExpression targetObject) { 148 return new Accessor(targetObject); 149 } 150 151 class Accessor extends AbstractListField.Accessor { 152 protected Accessor( JExpression $target ) { 153 super($target); 154 } 155 156 public void toRawValue(JBlock block, JVar $var) { 157 // [RESULT] 158 // $<var>.addAll(bean.getLIST()); 159 // list.toArray( array ); 160 block.assign($var,JExpr._new(codeModel.ref(ArrayList.class).narrow(getType(Aspect.EXPOSED).boxify())).arg( 161 $target.invoke($get) 162 )); 163 } 164 165 public void fromRawValue(JBlock block, String uniqueName, JExpression $var) { 166 // [RESULT] 167 // bean.getLIST().addAll($<var>); 168 JVar $list = block.decl(listT,uniqueName+'l',$target.invoke($get)); 169 block.invoke($list,"addAll").arg($var); 170 } 171 } 172 173 @Override 174 protected JType getType(final Aspect aspect) { 175 if (Aspect.IMPLEMENTATION.equals(aspect)) { 176 return super.getType(aspect); 177 } 178 179 if (prop instanceof CReferencePropertyInfo) { 180 Set<CElement> elements = ((CReferencePropertyInfo)prop).getElements(); 181 if ((elements != null) && (elements.size() > 0)) { 182 return codeModel.ref(Serializable.class); 183 } 184 } 185 186 return codeModel.ref(String.class); 187 } 188 }