1 /* 2 * Copyright (c) 1997, 2012, 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.api.impl.s2j; 27 28 import java.util.ArrayList; 29 import java.util.Collection; 30 import java.util.List; 31 32 import javax.xml.namespace.QName; 33 34 import com.sun.tools.internal.xjc.api.Mapping; 35 import com.sun.tools.internal.xjc.api.Property; 36 import com.sun.tools.internal.xjc.model.CClassInfo; 37 import com.sun.tools.internal.xjc.model.CElement; 38 import com.sun.tools.internal.xjc.model.CElementInfo; 39 import com.sun.tools.internal.xjc.model.CElementPropertyInfo; 40 import com.sun.tools.internal.xjc.model.CPropertyInfo; 41 import com.sun.tools.internal.xjc.model.CReferencePropertyInfo; 42 import com.sun.tools.internal.xjc.model.CTypeRef; 43 import com.sun.xml.internal.bind.v2.model.core.ClassInfo; 44 import com.sun.xml.internal.bind.v2.model.core.ReferencePropertyInfo; 45 46 import com.sun.xml.internal.xsom.XSComplexType; 47 import com.sun.xml.internal.xsom.XSComponent; 48 import com.sun.xml.internal.xsom.XSContentType; 49 import com.sun.xml.internal.xsom.XSModelGroup; 50 import com.sun.xml.internal.xsom.XSParticle; 51 import com.sun.xml.internal.xsom.XSTerm; 52 53 /** 54 * Partial common implementation between {@link ElementMappingImpl} and {@link BeanMappingImpl} 55 * 56 * @author Kohsuke Kawaguchi 57 */ 58 abstract class AbstractMappingImpl<InfoT extends CElement> implements Mapping { 59 60 protected final JAXBModelImpl parent; 61 protected final InfoT clazz; 62 /** 63 * Lazily computed. 64 * 65 * @see #getWrapperStyleDrilldown() 66 */ 67 private List<Property> drilldown = null; 68 private boolean drilldownComputed = false; 69 70 protected AbstractMappingImpl(JAXBModelImpl parent, InfoT clazz) { 71 this.parent = parent; 72 this.clazz = clazz; 73 } 74 75 public final QName getElement() { 76 return clazz.getElementName(); 77 } 78 79 public final String getClazz() { 80 return clazz.getType().fullName(); 81 } 82 83 public final List<? extends Property> getWrapperStyleDrilldown() { 84 if (!drilldownComputed) { 85 drilldownComputed = true; 86 drilldown = calcDrilldown(); 87 } 88 return drilldown; 89 } 90 91 protected abstract List<Property> calcDrilldown(); 92 93 /** 94 * Derived classes can use this method to implement {@link #calcDrilldown}. 95 */ 96 protected List<Property> buildDrilldown(CClassInfo typeBean) { 97 //JAXWS 2.1 spec 2.3.1.2: 98 //Wrapper style if the wrapper elements only contain child elements, 99 //they must not contain xsd:choice 100 if (containingChoice(typeBean)) { 101 return null; 102 } 103 104 List<Property> result; 105 106 CClassInfo bc = typeBean.getBaseClass(); 107 if (bc != null) { 108 result = buildDrilldown(bc); 109 if (result == null) { 110 return null; // aborted 111 } 112 } else { 113 result = new ArrayList<Property>(); 114 } 115 116 for (CPropertyInfo p : typeBean.getProperties()) { 117 if (p instanceof CElementPropertyInfo) { 118 CElementPropertyInfo ep = (CElementPropertyInfo) p; 119 // wrong. A+,B,C is eligible for drill-down. 120 // if(ep.isCollection()) 121 // // content model like A+,B,C is not eligible 122 // return null; 123 124 List<? extends CTypeRef> ref = ep.getTypes(); 125 if (ref.size() != 1) {// content model like (A|B),C is not eligible 126 return null; 127 } 128 129 result.add(createPropertyImpl(ep, ref.get(0).getTagName())); 130 } else if (p instanceof ReferencePropertyInfo) { 131 CReferencePropertyInfo rp = (CReferencePropertyInfo) p; 132 133 Collection<CElement> elements = rp.getElements(); 134 if (elements.size() != 1) { 135 return null; 136 } 137 138 CElement ref = elements.iterator().next(); 139 if (ref instanceof ClassInfo) { 140 result.add(createPropertyImpl(rp, ref.getElementName())); 141 } else { 142 CElementInfo eref = (CElementInfo) ref; 143 if (!eref.getSubstitutionMembers().isEmpty()) { 144 return null; // elements with a substitution group isn't qualified for the wrapper style 145 } 146 // JAX-WS doesn't want to see JAXBElement, so we have to hide it for them. 147 ElementAdapter fr; 148 if (rp.isCollection()) { 149 fr = new ElementCollectionAdapter(parent.outline.getField(rp), eref); 150 } else { 151 fr = new ElementSingleAdapter(parent.outline.getField(rp), eref); 152 } 153 154 result.add(new PropertyImpl(this, 155 fr, eref.getElementName())); 156 } 157 } else {// to be eligible for the wrapper style, only elements are allowed. 158 // according to the JAX-RPC spec 2.3.1.2, element refs are disallowed 159 return null; 160 } 161 162 } 163 164 return result; 165 } 166 167 private boolean containingChoice(CClassInfo typeBean) { 168 XSComponent component = typeBean.getSchemaComponent(); 169 if (component instanceof XSComplexType) { 170 XSContentType contentType = ((XSComplexType) component).getContentType(); 171 XSParticle particle = contentType.asParticle(); 172 if (particle != null) { 173 XSTerm term = particle.getTerm(); 174 XSModelGroup modelGroup = term.asModelGroup(); 175 if (modelGroup != null) { 176 return (modelGroup.getCompositor() == XSModelGroup.Compositor.CHOICE); 177 } 178 } 179 } 180 181 return false; 182 } 183 184 private Property createPropertyImpl(CPropertyInfo p, QName tagName) { 185 return new PropertyImpl(this, 186 parent.outline.getField(p), tagName); 187 } 188 }