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.Component;
009    import railo.runtime.ComponentImpl;
010    import railo.runtime.PageContext;
011    import railo.runtime.component.Property;
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 UDFHasProperty extends UDFGSProperty {
021    
022            private final Property prop;
023            //private ComponentScope scope;
024            
025            private final Key propName;
026            
027            //private static final String NULL="sdsdsdfsfsfjkln fsdfsa";
028    
029            public UDFHasProperty(ComponentImpl component,Property prop)  {
030                    super(component,"has"+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                            FunctionArgument key = new FunctionArgumentImpl(KeyConstants._key,"string",CFTypes.TYPE_STRING,false);
040                            return new FunctionArgument[]{key};
041                    }
042                    FunctionArgument value = new FunctionArgumentImpl(KeyImpl.init(PropertyFactory.getSingularName(prop)),"any",CFTypes.TYPE_ANY,false);
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 UDFHasProperty(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) return has(pageContext);
064                    return has(pageContext, args[0]);
065            }
066    
067            @Override
068            public Object callWithNamedValues(PageContext pageContext, Struct values,boolean doIncludePath) throws PageException {
069                    UDFImpl.argumentCollection(values,getFunctionArguments());
070                    Key key = arguments[0].getName();
071                    Object value = values.get(key,null);
072                    if(value==null){
073                            Key[] keys = CollectionUtil.keys(values);
074                            if(keys.length>0) {
075                                    value=values.get(keys[0]);
076                            }
077                            else return has(pageContext);
078                    }
079                    
080                    return has(pageContext, value);
081            }
082            
083            private boolean has(PageContext pageContext) {
084                    Object propValue = component.getComponentScope().get(propName,null);
085                    
086                    // struct
087                    if(isStruct()) {
088                            if(propValue instanceof Map) {
089                                    return !((Map)propValue).isEmpty();
090                            }
091                            return false;
092                    }
093                    
094                            //Object o;
095                            if(propValue instanceof Array) {
096                                    Array arr = ((Array)propValue);
097                                    return arr.size()>0;
098                            }
099                            else if(propValue instanceof java.util.List) {
100                                    
101                                    return ((java.util.List)propValue).size()>0;
102                            }
103                            return propValue instanceof Component;
104                    
105            }
106            
107            private boolean has(PageContext pageContext, Object value) throws PageException {
108                    Object propValue = component.getComponentScope().get(propName,null);
109                    
110                    // struct
111                    if(isStruct()) {
112                            String strKey = Caster.toString(value);
113                            //if(strKey==NULL) throw new ;
114                            
115                            if(propValue instanceof Struct) {
116                                    return ((Struct)propValue).containsKey(KeyImpl.getInstance(strKey));
117                            }
118                            else if(propValue instanceof Map) {
119                                    return ((Map)propValue).containsKey(strKey);
120                            }
121                            return false;
122                    }
123                    
124                            Object o;
125                            
126                            if(propValue instanceof Array) {
127                                    Array arr = ((Array)propValue);
128                                    Iterator<Object> it = arr.valueIterator();
129                                    while(it.hasNext()){
130                                            if(ORMUtil.equals(value,it.next()))return true;
131                                    }
132                            }
133                            else if(propValue instanceof java.util.List) {
134                                    Iterator it=((java.util.List)propValue).iterator();
135                                    while(it.hasNext()){
136                                            o = it.next();
137                                            if(ORMUtil.equals(value,o))return true;
138                                    }
139                            }
140                            return false;
141                    
142            }
143    
144            @Override
145            public Object implementation(PageContext pageContext) throws Throwable {
146                    return null;
147            }
148            
149            @Override
150            public Object getDefaultValue(PageContext pc, int index) throws PageException {
151                    return prop.getDefault();
152            }
153            
154            @Override
155            public Object getDefaultValue(PageContext pc, int index, Object defaultValue) throws PageException {
156                    return prop.getDefault();
157            }
158    
159            @Override
160            public String getReturnTypeAsString() {
161                    return "boolean";
162            }
163    }