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