001    package railo.runtime.functions.query;
002    
003    import java.util.Iterator;
004    import java.util.Map.Entry;
005    
006    import railo.commons.lang.StringUtil;
007    import railo.runtime.PageContext;
008    import railo.runtime.exp.DatabaseException;
009    import railo.runtime.exp.FunctionException;
010    import railo.runtime.exp.PageException;
011    import railo.runtime.functions.BIF;
012    import railo.runtime.op.Caster;
013    import railo.runtime.op.Decision;
014    import railo.runtime.type.Array;
015    import railo.runtime.type.ArrayImpl;
016    import railo.runtime.type.Collection.Key;
017    import railo.runtime.type.Query;
018    import railo.runtime.type.QueryImpl;
019    import railo.runtime.type.Struct;
020    import railo.runtime.type.util.ListUtil;
021    import railo.runtime.type.util.QueryUtil;
022    
023    /**
024     * Implements the CFML Function querynew
025     */
026    public final class QueryNew extends BIF {
027    
028            private static final long serialVersionUID = -4313766961671090938L;
029            
030            public static railo.runtime.type.Query call(PageContext pc , String columnList) throws DatabaseException {
031                return new QueryImpl(ListUtil.listToArrayTrim(columnList,","),0,"query");
032            }
033            public static railo.runtime.type.Query call(PageContext pc , String columnList, String columnTypeList) throws PageException {
034                    if(StringUtil.isEmpty(columnTypeList)) return call(pc, columnList);
035                    return new QueryImpl(ListUtil.listToArrayTrim(columnList,","),ListUtil.listToArrayTrim(columnTypeList,","),0,"query");
036            }
037            
038            public static railo.runtime.type.Query call(PageContext pc , String strColumnList, String strColumnTypeList, Object data) throws PageException {
039                    Array columnList = ListUtil.listToArrayTrim(strColumnList,",");
040                    railo.runtime.type.Query qry;
041                    if(StringUtil.isEmpty(strColumnTypeList))
042                            qry= new QueryImpl(columnList,0,"query");
043                    else
044                            qry= new QueryImpl(columnList,ListUtil.listToArrayTrim(strColumnTypeList,","),0,"query");
045                    
046                    if(data==null) return qry;
047                    return populate(pc, qry, data); 
048            }
049            
050            @Override
051            public Object invoke(PageContext pc, Object[] args) throws PageException {
052                    if(args.length==1)return call(pc,Caster.toString(args[0]));
053                    if(args.length==2)return call(pc,Caster.toString(args[0]),Caster.toString(args[1]));
054                    return call(pc,Caster.toString(args[0]),Caster.toString(args[1]),args[2]);
055            }
056            
057            public static Query populate(PageContext pc, Query qry,Object data) throws PageException {
058                    if(Decision.isArray(data))
059                            return _populate(pc,qry,Caster.toArray(data));
060                    else if(Decision.isStruct(data))
061                            return _populate(pc,qry,Caster.toStruct(data));
062                    else 
063                            throw new FunctionException(pc, "QueryNew", 3, "data", "the date must be defined as array of structs , array of arrays or struct of arrays");
064            }
065            
066            private static Query _populate(PageContext pc, Query qry,Struct data) throws PageException {
067                    Iterator<Entry<Key, Object>> it = data.entryIterator();
068                    Entry<Key, Object> e;
069                    Object v;
070                    Array arr;
071                    int rows = qry.getRecordcount();
072                    while(it.hasNext()){
073                            e = it.next();
074                            if(qry.getColumn(e.getKey(),null)!=null) {
075                                    v=e.getValue();
076                                    arr = Caster.toArray(v,null);
077                                    if(arr==null) arr=new ArrayImpl(new Object[]{v});
078                                    populateColumn(qry,e.getKey(),arr,rows);
079                            }
080                    }
081                    return qry; 
082            }
083            
084            private static void populateColumn(Query qry, Key column, Array data,int rows) throws PageException {
085                    Iterator<?> it = data.valueIterator();
086                    int row=rows;
087                    while(it.hasNext()){
088                            row++;
089                            if(row>qry.getRecordcount()) qry.addRow();
090                            qry.setAt(column, row, it.next());
091                    }
092            }
093            private static Query _populate(PageContext pc, Query qry,Array data) throws PageException {
094                    /*
095                     * 3 types of structures are supported
096                     * array - ["Urs","Weber"]
097                     * array of struct - [{firstname="Urs",lastname="Weber"},{firstname="Peter",lastname="Mueller"}]
098                     * array of array - [["Urs","Weber"],["Peter","Mueller"]]
099                     */
100                    
101                    // check if the array only contains simple values or mixed
102                    Iterator<?> it = data.valueIterator();
103                    Object o;
104                    boolean hasSimpleValues=false;
105                    while(it.hasNext()){
106                            o=it.next();
107                            if(!Decision.isStruct(o) && !Decision.isArray(o)) hasSimpleValues=true;
108                    }
109                    
110                    
111                    if(hasSimpleValues) {
112                            qry.addRow();
113                            populateRow(qry, data);
114                    }
115                    else {
116                            it = data.valueIterator();
117                            while(it.hasNext()){
118                                    o=it.next();
119                                    qry.addRow();
120                                    if(Decision.isStruct(o))populateRow(qry,Caster.toStruct(o));
121                                    else if(Decision.isArray(o))populateRow(qry,Caster.toArray(o));
122                                    else {
123                                            populateRow(qry,new ArrayImpl(new Object[]{o}));
124                                    }
125                            }
126                    }
127                    return qry;
128            }
129            
130            private static void populateRow(Query qry, Struct data) throws PageException {
131                    Key[] columns = QueryUtil.getColumnNames(qry);
132                    int row=qry.getRecordcount();
133                    Object value;
134                    for(int i=0;i<columns.length;i++){
135                            value=data.get(columns[i],null);
136                            if(value!=null) qry.setAt(columns[i], row, value);
137                    }
138                    
139            }
140            private static void populateRow(Query qry, Array data) throws PageException {
141                    Iterator<?> it = data.valueIterator();
142                    Key[] columns = QueryUtil.getColumnNames(qry);
143                    int row=qry.getRecordcount();
144                    int index=-1;
145                    while(it.hasNext()){
146                            index++;
147                            if(index>=columns.length) break;
148                            qry.setAt(columns[index], row, it.next());
149                    }
150            }
151    }