001 package railo.runtime.type; 002 003 import java.util.Iterator; 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.op.Caster; 014 import railo.runtime.orm.ORMUtil; 015 import railo.runtime.type.Collection.Key; 016 import railo.runtime.type.util.CollectionUtil; 017 import railo.runtime.type.util.KeyConstants; 018 import railo.runtime.type.util.PropertyFactory; 019 020 public final class UDFRemoveProperty extends UDFGSProperty { 021 022 private final Property prop; 023 //private ComponentScope scope; 024 025 private final Key propName; 026 027 private static final Object NULL=new Object(); 028 029 public UDFRemoveProperty(ComponentImpl component,Property prop) { 030 super(component,"remove"+StringUtil.ucFirst(PropertyFactory.getSingularName(prop)),getFunctionArgument(prop),CFTypes.TYPE_BOOLEAN,"wddx"); 031 this.prop=prop; 032 this.propName=KeyImpl.getInstance(prop.getName()); 033 } 034 035 private static FunctionArgument[] getFunctionArgument(Property prop) { 036 String t = PropertyFactory.getType(prop); 037 038 if("struct".equalsIgnoreCase(t)){ 039 FunctionArgumentImpl key = new FunctionArgumentImpl(KeyConstants._key,"string",CFTypes.TYPE_STRING,true); 040 return new FunctionArgument[]{key}; 041 } 042 FunctionArgumentImpl value = new FunctionArgumentImpl(KeyImpl.init(PropertyFactory.getSingularName(prop)),"any",CFTypes.TYPE_ANY,true); 043 return new FunctionArgument[]{value}; 044 } 045 046 private boolean isStruct() { 047 String t = PropertyFactory.getType(prop); 048 return "struct".equalsIgnoreCase(t); 049 } 050 051 @Override 052 public UDF duplicate(ComponentImpl c) { 053 return new UDFRemoveProperty(c,prop); 054 } 055 056 057 public UDF duplicate() { 058 return duplicate(component); 059 } 060 061 @Override 062 public Object call(PageContext pageContext, Object[] args,boolean doIncludePath) throws PageException { 063 if(args.length<1) 064 throw new ExpressionException("The parameter "+this.arguments[0].getName()+" to function "+getFunctionName()+" is required but was not passed in."); 065 066 return remove(pageContext, args[0]); 067 } 068 069 @Override 070 public Object callWithNamedValues(PageContext pageContext, Struct values,boolean doIncludePath) throws PageException { 071 UDFImpl.argumentCollection(values,getFunctionArguments()); 072 Key key = arguments[0].getName(); 073 Object value = values.get(key,null); 074 if(value==null){ 075 Key[] keys = CollectionUtil.keys(values); 076 if(keys.length==1) { 077 value=values.get(keys[0]); 078 } 079 else throw new ExpressionException("The parameter "+key+" to function "+getFunctionName()+" is required but was not passed in."); 080 } 081 082 return remove(pageContext, value); 083 } 084 085 086 private boolean remove(PageContext pageContext, Object value) throws PageException { 087 Object propValue = component.getComponentScope().get(propName,null); 088 value=cast(arguments[0],value,1); 089 090 // struct 091 if(isStruct()) { 092 String strKey = Caster.toString(value,null); 093 if(strKey==null) return false; 094 095 if(propValue instanceof Struct) { 096 return ((Struct)propValue).removeEL(KeyImpl.getInstance(strKey))!=null; 097 } 098 else if(propValue instanceof Map) { 099 return ((Map)propValue).remove(strKey)!=null; 100 } 101 return false; 102 } 103 104 Object o; 105 boolean has=false; 106 if(propValue instanceof Array) { 107 Array arr = ((Array)propValue); 108 Key[] keys = CollectionUtil.keys(arr); 109 for(int i=0;i<keys.length;i++){ 110 o=arr.get(keys[i],null); 111 if(ORMUtil.equals(value,o)){ 112 arr.removeEL(keys[i]); 113 has=true; 114 } 115 } 116 } 117 else if(propValue instanceof java.util.List) { 118 Iterator it=((java.util.List)propValue).iterator(); 119 while(it.hasNext()){ 120 o = it.next(); 121 if(ORMUtil.equals(value,o)){ 122 it.remove(); 123 has=true; 124 } 125 } 126 } 127 return has; 128 129 } 130 131 @Override 132 public Object implementation(PageContext pageContext) throws Throwable { 133 return null; 134 } 135 136 @Override 137 public Object getDefaultValue(PageContext pc, int index) throws PageException { 138 return prop.getDefault(); 139 } 140 141 @Override 142 public Object getDefaultValue(PageContext pc, int index, Object defaultValue) throws PageException { 143 return prop.getDefault(); 144 } 145 146 @Override 147 public String getReturnTypeAsString() { 148 return "boolean"; 149 } 150 }