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.xml.internal.ws.model;
  27 
  28 import com.sun.xml.internal.bind.api.Bridge;
  29 import com.sun.xml.internal.bind.api.TypeReference;
  30 import com.sun.xml.internal.ws.api.model.JavaMethod;
  31 import com.sun.xml.internal.ws.api.model.Parameter;
  32 import com.sun.xml.internal.ws.api.model.ParameterBinding;
  33 import com.sun.xml.internal.ws.spi.db.RepeatedElementBridge;
  34 import com.sun.xml.internal.ws.spi.db.WrapperComposite;
  35 import com.sun.xml.internal.ws.spi.db.XMLBridge;
  36 import com.sun.xml.internal.ws.spi.db.TypeInfo;
  37 
  38 import javax.jws.WebParam.Mode;
  39 import javax.xml.namespace.QName;
  40 import javax.xml.ws.Holder;
  41 import java.util.List;
  42 
  43 /**
  44  * runtime Parameter that abstracts the annotated java parameter
  45  *
  46  * <p>
  47  * A parameter may be bound to a header, a body, or an attachment.
  48  * Note that when it's bound to a body, it's bound to a body,
  49  * it binds to the whole payload.
  50  *
  51  * <p>
  52  * Sometimes multiple Java parameters are packed into the payload,
  53  * in which case the subclass {@link WrapperParameter} is used.
  54  *
  55  * @author Vivek Pandey
  56  */
  57 public class ParameterImpl implements Parameter {
  58 
  59     private ParameterBinding binding;
  60     private ParameterBinding outBinding;
  61     private String partName;
  62     private final int index;
  63     private final Mode mode;
  64     /** @deprecated */
  65     private TypeReference typeReference;
  66     private TypeInfo typeInfo;
  67     private QName name;
  68     private final JavaMethodImpl parent;
  69 
  70     WrapperParameter wrapper;
  71     TypeInfo itemTypeInfo;
  72 
  73     public ParameterImpl(JavaMethodImpl parent, TypeInfo type, Mode mode, int index) {
  74         assert type != null;
  75 
  76         this.typeInfo = type;
  77         this.name = type.tagName;
  78         this.mode = mode;
  79         this.index = index;
  80         this.parent = parent;
  81     }
  82 
  83     public AbstractSEIModelImpl getOwner() {
  84         return parent.owner;
  85     }
  86 
  87     public JavaMethod getParent() {
  88         return parent;
  89     }
  90 
  91     /**
  92      * @return Returns the name.
  93      */
  94     public QName getName() {
  95         return name;
  96     }
  97 
  98     public XMLBridge getXMLBridge() {
  99         return getOwner().getXMLBridge(typeInfo);
 100     }
 101 
 102     public XMLBridge getInlinedRepeatedElementBridge() {
 103         TypeInfo itemType = getItemType();
 104         if (itemType != null && itemType.getWrapperType() == null) {
 105             XMLBridge xb = getOwner().getXMLBridge(itemType);
 106             if (xb != null) return new RepeatedElementBridge(typeInfo, xb);
 107         }
 108         return null;
 109     }
 110 
 111     public TypeInfo getItemType() {
 112         if (itemTypeInfo != null) return itemTypeInfo;
 113         //RpcLit cannot inline repeated element in wrapper
 114         if (parent.getBinding().isRpcLit() || wrapper == null) return null;
 115         //InlinedRepeatedElementBridge is only used for dynamic wrapper (no wrapper class)
 116         if (!WrapperComposite.class.equals(wrapper.getTypeInfo().type)) return null;
 117         if (!getBinding().isBody()) return null;
 118         itemTypeInfo = typeInfo.getItemType();
 119         return  itemTypeInfo;
 120     }
 121 
 122     /**  @deprecated  */
 123     public Bridge getBridge() {
 124         return getOwner().getBridge(typeReference);
 125     }
 126     /**  @deprecated  */
 127     protected Bridge getBridge(TypeReference typeRef) {
 128         return getOwner().getBridge(typeRef);
 129     }
 130 
 131     /**
 132      * TODO: once the model gets JAXBContext, shouldn't {@link Bridge}s
 133      * be made available from model objects?
 134      * @deprecated use getTypeInfo
 135      * @return Returns the TypeReference associated with this Parameter
 136      */
 137     public TypeReference getTypeReference() {
 138         return typeReference;
 139     }
 140     public TypeInfo getTypeInfo() {
 141         return typeInfo;
 142     }
 143 
 144     /**
 145      * Sometimes we need to overwrite the typeReferenc, such as during patching for rpclit
 146      * @see AbstractSEIModelImpl#applyRpcLitParamBinding(JavaMethodImpl, WrapperParameter, WSDLBoundPortType, WebParam.Mode)
 147      * @deprecated
 148      */
 149     void setTypeReference(TypeReference type){
 150         typeReference = type;
 151         name = type.tagName;
 152     }
 153 
 154 
 155     public Mode getMode() {
 156         return mode;
 157     }
 158 
 159     public int getIndex() {
 160         return index;
 161     }
 162 
 163     /**
 164      * @return true if {@code this instanceof} {@link WrapperParameter}.
 165      */
 166     public boolean isWrapperStyle() {
 167         return false;
 168     }
 169 
 170     public boolean isReturnValue() {
 171         return index==-1;
 172     }
 173 
 174     /**
 175      * @return the Binding for this Parameter
 176      */
 177     public ParameterBinding getBinding() {
 178         if(binding == null)
 179             return ParameterBinding.BODY;
 180         return binding;
 181     }
 182 
 183     /**
 184      * @param binding
 185      */
 186     public void setBinding(ParameterBinding binding) {
 187         this.binding = binding;
 188     }
 189 
 190     public void setInBinding(ParameterBinding binding){
 191         this.binding = binding;
 192     }
 193 
 194     public void setOutBinding(ParameterBinding binding){
 195         this.outBinding = binding;
 196     }
 197 
 198     public ParameterBinding getInBinding(){
 199         return binding;
 200     }
 201 
 202     public ParameterBinding getOutBinding(){
 203         if(outBinding == null)
 204             return binding;
 205         return outBinding;
 206     }
 207 
 208     public boolean isIN() {
 209         return mode==Mode.IN;
 210     }
 211 
 212     public boolean isOUT() {
 213         return mode==Mode.OUT;
 214     }
 215 
 216     public boolean isINOUT() {
 217         return mode==Mode.INOUT;
 218     }
 219 
 220     /**
 221      * If true, this parameter maps to the return value of a method invocation.
 222      *
 223      * <p>
 224      * {@link JavaMethodImpl#getResponseParameters()} is guaranteed to have
 225      * at most one such {@link ParameterImpl}. Note that there coule be none,
 226      * in which case the method returns {@code void}.
 227      */
 228     public boolean isResponse() {
 229         return index == -1;
 230     }
 231 
 232 
 233     /**
 234      * Gets the holder value if applicable. To be called for inbound client side
 235      * message.
 236      *
 237      * @param obj
 238      * @return the holder value if applicable.
 239      */
 240     public Object getHolderValue(Object obj) {
 241         if (obj != null && obj instanceof Holder)
 242             return ((Holder) obj).value;
 243         return obj;
 244     }
 245 
 246     public String getPartName() {
 247         if(partName == null)
 248             return name.getLocalPart();
 249         return partName;
 250     }
 251 
 252     public void setPartName(String partName) {
 253         this.partName = partName;
 254     }
 255 
 256     void fillTypes(List<TypeInfo> types) {
 257         TypeInfo itemType = getItemType();
 258         if (itemType != null) {
 259             types.add(itemType);
 260             if (itemType.getWrapperType() != null) types.add(getTypeInfo());
 261         } else {
 262             types.add(getTypeInfo());
 263         }
 264     }
 265 }