001 package railo.runtime.type; 002 003 import java.util.HashMap; 004 import java.util.Map; 005 006 import railo.commons.lang.CFTypes; 007 import railo.commons.lang.StringUtil; 008 import railo.runtime.ComponentImpl; 009 import railo.runtime.PageContext; 010 import railo.runtime.component.Property; 011 import railo.runtime.exp.ExpressionException; 012 import railo.runtime.exp.PageException; 013 import railo.runtime.type.Collection.Key; 014 import railo.runtime.type.util.PropertyFactory; 015 016 public final class UDFAddProperty extends UDFGSProperty { 017 018 private final Property prop; 019 //private ComponentScope scope; 020 021 private final Key propName; 022 023 private static final Object NULL=new Object(); 024 025 public UDFAddProperty(ComponentImpl component,Property prop) { 026 super(component,"add"+StringUtil.ucFirst(PropertyFactory.getSingularName(prop)),getFunctionArgument(prop),CFTypes.TYPE_ANY,"wddx"); 027 this.prop=prop; 028 this.propName=KeyImpl.getInstance(prop.getName()); 029 } 030 031 private static FunctionArgument[] getFunctionArgument(Property prop) { 032 String t = PropertyFactory.getType(prop); 033 FunctionArgument value = new FunctionArgumentImpl(KeyImpl.init(PropertyFactory.getSingularName(prop)),"any",CFTypes.TYPE_ANY,true); 034 if("struct".equalsIgnoreCase(t)){ 035 FunctionArgument key = new FunctionArgumentImpl(KeyImpl.KEY,"string",CFTypes.TYPE_STRING,true); 036 return new FunctionArgument[]{key,value}; 037 } 038 return new FunctionArgument[]{value}; 039 } 040 041 /** 042 * @see railo.runtime.type.UDF#duplicate() 043 */ 044 public UDF duplicate(ComponentImpl c) { 045 return new UDFAddProperty(c,prop); 046 } 047 048 049 public UDF duplicate() { 050 return duplicate(component); 051 } 052 053 /** 054 * @see railo.runtime.type.UDF#call(railo.runtime.PageContext, java.lang.Object[], boolean) 055 */ 056 public Object call(PageContext pageContext, Object[] args,boolean doIncludePath) throws PageException { 057 // struct 058 if(this.arguments.length==2) { 059 if(args.length<2) 060 throw new ExpressionException("The function "+getFunctionName()+" need 2 arguments, only "+args.length+" argment"+(args.length==1?" is":"s are")+" passed in."); 061 return _call(pageContext, args[0], args[1]); 062 } 063 // array 064 else if(this.arguments.length==1) { 065 if(args.length<1) 066 throw new ExpressionException("The parameter "+this.arguments[0].getName()+" to function "+getFunctionName()+" is required but was not passed in."); 067 return _call(pageContext, null, args[0]); 068 } 069 070 // never reached 071 return component; 072 073 } 074 075 /** 076 * @see railo.runtime.type.UDF#callWithNamedValues(railo.runtime.PageContext, railo.runtime.type.Struct, boolean) 077 */ 078 public Object callWithNamedValues(PageContext pageContext, Struct values,boolean doIncludePath) throws PageException { 079 UDFImpl.argumentCollection(values,getFunctionArguments()); 080 081 082 // struct 083 if(this.arguments.length==2) { 084 Key keyName = arguments[0].getName(); 085 Key valueName = arguments[1].getName(); 086 Object key = values.get(keyName,null); 087 Object value = values.get(valueName,null); 088 if(key==null) 089 throw new ExpressionException("The parameter "+keyName+" to function "+getFunctionName()+" is required but was not passed in."); 090 if(value==null) 091 throw new ExpressionException("The parameter "+valueName+" to function "+getFunctionName()+" is required but was not passed in."); 092 093 return _call(pageContext, key, value); 094 } 095 // array 096 else if(this.arguments.length==1) { 097 Key valueName = arguments[0].getName(); 098 Object value = values.get(valueName,null); 099 if(value==null){ 100 Key[] keys = values.keys(); 101 if(keys.length==1) { 102 value=values.get(keys[0]); 103 } 104 else throw new ExpressionException("The parameter "+valueName+" to function "+getFunctionName()+" is required but was not passed in."); 105 } 106 return _call(pageContext, null, value); 107 } 108 109 // never reached 110 return component; 111 } 112 113 114 private Object _call(PageContext pageContext, Object key, Object value) throws PageException { 115 116 117 Object propValue = component.getComponentScope().get(propName,null); 118 119 // struct 120 if(this.arguments.length==2) { 121 key=cast(arguments[0],key,1); 122 value=cast(arguments[1],value,2); 123 if(propValue==null){ 124 HashMap map=new HashMap(); 125 component.getComponentScope().setEL(propName,map); 126 propValue=map; 127 } 128 if(propValue instanceof Struct) { 129 ((Struct)propValue).set(KeyImpl.toKey(key), value); 130 } 131 else if(propValue instanceof Map) { 132 ((Map)propValue).put(key, value); 133 } 134 } 135 else { 136 value=cast(arguments[0],value,1); 137 if(propValue==null){ 138 Array arr=new ArrayImpl(); 139 component.getComponentScope().setEL(propName,arr); 140 propValue=arr; 141 } 142 if(propValue instanceof Array) { 143 ((Array)propValue).appendEL(value); 144 } 145 else if(propValue instanceof java.util.List) { 146 ((java.util.List)propValue).add(value); 147 } 148 } 149 return component; 150 } 151 152 /** 153 * @see railo.runtime.type.UDF#implementation(railo.runtime.PageContext) 154 */ 155 public Object implementation(PageContext pageContext) throws Throwable { 156 return null; 157 } 158 159 /** 160 * @see railo.runtime.type.UDF#getDefaultValue(railo.runtime.PageContext, int) 161 */ 162 public Object getDefaultValue(PageContext pc, int index) throws PageException { 163 return prop.getDefault(); 164 } 165 166 /** 167 * @see railo.runtime.type.UDF#getReturnTypeAsString() 168 */ 169 public String getReturnTypeAsString() { 170 return "any"; 171 } 172 }