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