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    }