001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.type; 020 021import java.util.HashMap; 022import java.util.Map; 023 024import lucee.commons.lang.CFTypes; 025import lucee.commons.lang.StringUtil; 026import lucee.runtime.ComponentImpl; 027import lucee.runtime.PageContext; 028import lucee.runtime.component.Property; 029import lucee.runtime.exp.ExpressionException; 030import lucee.runtime.exp.PageException; 031import lucee.runtime.type.Collection.Key; 032import lucee.runtime.type.util.CollectionUtil; 033import lucee.runtime.type.util.KeyConstants; 034import lucee.runtime.type.util.PropertyFactory; 035import lucee.runtime.type.util.UDFUtil; 036 037public final class UDFAddProperty extends UDFGSProperty { 038 039 private final Property prop; 040 //private ComponentScope scope; 041 042 private final Key propName; 043 044 private static final Object NULL=new Object(); 045 046 public UDFAddProperty(ComponentImpl component,Property prop) { 047 super(component,"add"+StringUtil.ucFirst(PropertyFactory.getSingularName(prop)),getFunctionArgument(prop),CFTypes.TYPE_ANY,"wddx"); 048 this.prop=prop; 049 this.propName=KeyImpl.getInstance(prop.getName()); 050 } 051 052 private static FunctionArgument[] getFunctionArgument(Property prop) { 053 String t = PropertyFactory.getType(prop); 054 FunctionArgument value = new FunctionArgumentImpl(KeyImpl.init(PropertyFactory.getSingularName(prop)),"any",CFTypes.TYPE_ANY,true); 055 if("struct".equalsIgnoreCase(t)){ 056 FunctionArgument key = new FunctionArgumentImpl(KeyConstants._key,"string",CFTypes.TYPE_STRING,true); 057 return new FunctionArgument[]{key,value}; 058 } 059 return new FunctionArgument[]{value}; 060 } 061 062 public UDF duplicate() { 063 return new UDFAddProperty(component,prop); 064 } 065 066 @Override 067 public Object call(PageContext pageContext, Object[] args,boolean doIncludePath) throws PageException { 068 // struct 069 if(this.arguments.length==2) { 070 if(args.length<2) 071 throw new ExpressionException("The function "+getFunctionName()+" need 2 arguments, only "+args.length+" argment"+(args.length==1?" is":"s are")+" passed in."); 072 return _call(pageContext, args[0], args[1]); 073 } 074 // array 075 else if(this.arguments.length==1) { 076 if(args.length<1) 077 throw new ExpressionException("The parameter "+this.arguments[0].getName()+" to function "+getFunctionName()+" is required but was not passed in."); 078 return _call(pageContext, null, args[0]); 079 } 080 081 // never reached 082 return component; 083 084 } 085 086 @Override 087 public Object callWithNamedValues(PageContext pageContext, Struct values,boolean doIncludePath) throws PageException { 088 UDFUtil.argumentCollection(values,getFunctionArguments()); 089 090 091 // struct 092 if(this.arguments.length==2) { 093 Key keyName = arguments[0].getName(); 094 Key valueName = arguments[1].getName(); 095 Object key = values.get(keyName,null); 096 Object value = values.get(valueName,null); 097 if(key==null) 098 throw new ExpressionException("The parameter "+keyName+" to function "+getFunctionName()+" is required but was not passed in."); 099 if(value==null) 100 throw new ExpressionException("The parameter "+valueName+" to function "+getFunctionName()+" is required but was not passed in."); 101 102 return _call(pageContext, key, value); 103 } 104 // array 105 else if(this.arguments.length==1) { 106 Key valueName = arguments[0].getName(); 107 Object value = values.get(valueName,null); 108 if(value==null){ 109 Key[] keys = CollectionUtil.keys(values); 110 if(keys.length==1) { 111 value=values.get(keys[0]); 112 } 113 else throw new ExpressionException("The parameter "+valueName+" to function "+getFunctionName()+" is required but was not passed in."); 114 } 115 return _call(pageContext, null, value); 116 } 117 118 // never reached 119 return component; 120 } 121 122 123 private Object _call(PageContext pageContext, Object key, Object value) throws PageException { 124 125 126 Object propValue = component.getComponentScope().get(propName,null); 127 128 // struct 129 if(this.arguments.length==2) { 130 key=cast(pageContext,arguments[0],key,1); 131 value=cast(pageContext,arguments[1],value,2); 132 if(propValue==null){ 133 HashMap map=new HashMap(); 134 component.getComponentScope().setEL(propName,map); 135 propValue=map; 136 } 137 if(propValue instanceof Struct) { 138 ((Struct)propValue).set(KeyImpl.toKey(key), value); 139 } 140 else if(propValue instanceof Map) { 141 ((Map)propValue).put(key, value); 142 } 143 } 144 else { 145 value=cast(pageContext,arguments[0],value,1); 146 if(propValue==null){ 147 /* jira2049 148 PageContext pc = ThreadLocalPageContext.get(); 149 ORMSession sess = ORMUtil.getSession(pc); 150 SessionImpl s=(SessionImpl) sess.getRawSession(); 151 propValue=new PersistentList(s); 152 component.getComponentScope().setEL(propName,propValue);*/ 153 Array arr=new ArrayImpl(); 154 component.getComponentScope().setEL(propName,arr); 155 propValue=arr; 156 } 157 if(propValue instanceof Array) { 158 ((Array)propValue).appendEL(value); 159 } 160 else if(propValue instanceof java.util.List) { 161 ((java.util.List)propValue).add(value); 162 } 163 } 164 return component; 165 } 166 167 @Override 168 public Object implementation(PageContext pageContext) throws Throwable { 169 return null; 170 } 171 172 @Override 173 public Object getDefaultValue(PageContext pc, int index) throws PageException { 174 return prop.getDefault(); 175 } 176 177 @Override 178 public Object getDefaultValue(PageContext pc, int index, Object defaultValue) throws PageException { 179 return prop.getDefault(); 180 } 181 182 @Override 183 public String getReturnTypeAsString() { 184 return "any"; 185 } 186}