001    package railo.runtime.net.rpc;
002    
003    import java.math.BigDecimal;
004    import java.util.ArrayList;
005    import java.util.Calendar;
006    import java.util.Date;
007    import java.util.HashMap;
008    import java.util.HashSet;
009    import java.util.Iterator;
010    import java.util.Map;
011    import java.util.Map.Entry;
012    import java.util.Set;
013    import java.util.TimeZone;
014    import java.util.Vector;
015    
016    import javax.xml.namespace.QName;
017    import javax.xml.rpc.encoding.TypeMapping;
018    
019    import org.apache.axis.Constants;
020    import org.apache.axis.types.Day;
021    import org.apache.axis.types.Duration;
022    import org.apache.axis.types.Entities;
023    import org.apache.axis.types.Entity;
024    import org.apache.axis.types.Language;
025    import org.apache.axis.types.Month;
026    import org.apache.axis.types.MonthDay;
027    import org.apache.axis.types.NCName;
028    import org.apache.axis.types.NMToken;
029    import org.apache.axis.types.NMTokens;
030    import org.apache.axis.types.Name;
031    import org.apache.axis.types.Token;
032    import org.apache.axis.types.URI;
033    import org.apache.axis.types.URI.MalformedURIException;
034    import org.apache.axis.types.Year;
035    import org.apache.axis.types.YearMonth;
036    
037    import railo.commons.lang.ClassException;
038    import railo.commons.lang.ClassUtil;
039    import railo.commons.lang.StringUtil;
040    import railo.runtime.Component;
041    import railo.runtime.ComponentScope;
042    import railo.runtime.ComponentWrap;
043    import railo.runtime.PageContext;
044    import railo.runtime.component.Property;
045    import railo.runtime.engine.ThreadLocalPageContext;
046    import railo.runtime.exp.ExpressionException;
047    import railo.runtime.exp.PageException;
048    import railo.runtime.interpreter.CFMLExpressionInterpreter;
049    import railo.runtime.op.Caster;
050    import railo.runtime.op.Decision;
051    import railo.runtime.op.date.DateCaster;
052    import railo.runtime.reflection.Reflector;
053    import railo.runtime.type.Array;
054    import railo.runtime.type.Collection;
055    import railo.runtime.type.Collection.Key;
056    import railo.runtime.type.KeyImpl;
057    import railo.runtime.type.Query;
058    import railo.runtime.type.QueryColumn;
059    import railo.runtime.type.QueryImpl;
060    import railo.runtime.type.Struct;
061    import railo.runtime.type.StructImpl;
062    import railo.runtime.type.UDF;
063    import railo.runtime.type.cfc.ComponentAccess;
064    import railo.runtime.type.dt.DateTime;
065    import railo.runtime.type.dt.TimeSpan;
066    import railo.runtime.type.scope.Argument;
067    import railo.runtime.type.util.ArrayUtil;
068    import railo.runtime.type.util.ComponentUtil;
069    import coldfusion.xml.rpc.QueryBean;
070    
071    /**
072     * Axis Type Caster
073     */
074    public final class AxisCaster {
075    
076            /**
077         * cast a value to a Axis Compatible Type
078         * @param type
079         * @param value
080         * @return Axis Compatible Type
081         * @throws PageException
082         */
083        public static Object toAxisType(TypeMapping tm,TimeZone tz,QName type, Object value, Class targetClass) throws PageException {
084                    return _toAxisType(tm, tz, type, value, targetClass,new HashSet<Object>());
085            }
086    
087        public static Object toAxisType(TypeMapping tm,Object value,Class targetClass) throws PageException {
088            return _toAxisType(tm,null,null, value, targetClass, new HashSet<Object>());
089        }
090            
091        /**
092         * cast a value to a Axis Compatible Type
093         * @param type
094         * @param value
095         * @return Axis Compatible Type
096         * @throws PageException
097         */
098        private static Object _toAxisType(TypeMapping tm,TimeZone tz,QName type, Object value, Class targetClass,Set<Object> done) throws PageException {
099            if(done.contains(value)){
100                            return null;// TODO not sure what in this case is the best solution.
101                    }
102            
103                    done.add(value);
104            try{
105            
106                    if(type!=null) {
107                            // XSD
108                            for(int i=0;i<Constants.URIS_SCHEMA_XSD.length;i++) {
109                                if(Constants.URIS_SCHEMA_XSD[i].equals(type.getNamespaceURI())) {
110                                    return toAxisTypeXSD(tm,tz,type, value,targetClass,done);
111                                }
112                            }
113                            //SOAP
114                            if(type.getNamespaceURI().indexOf("soap")!=-1) {
115                                return toAxisTypeSoap(tm,type, value,targetClass,done);
116                            }
117                            // Specials
118                            if(type.getLocalPart().equals("ArrayOf_xsd_anyType"))
119                                return toArrayList(tm,value,targetClass,done);
120                    }
121                    return _toAxisTypeSub(tm,value,targetClass,done);
122            
123            }
124            finally{
125                    done.remove(value);
126            }
127        }
128        
129        private static Object toAxisTypeSoap(TypeMapping tm,QName type, Object value, Class targetClass, Set<Object> done) throws PageException {
130            String local = type.getLocalPart();
131            
132            if(local.equals(Constants.SOAP_ARRAY.getLocalPart())) return toArrayList(tm,value,targetClass,done);
133            if(local.equals(Constants.SOAP_ARRAY12.getLocalPart())) return toArrayList(tm,value,targetClass,done);
134            if(local.equals(Constants.SOAP_ARRAY_ATTRS11.getLocalPart())) return toArrayList(tm,value,targetClass,done);
135            if(local.equals(Constants.SOAP_ARRAY_ATTRS12.getLocalPart())) return toArrayList(tm,value,targetClass,done);
136            if(local.equals(Constants.SOAP_BASE64.getLocalPart())) return Caster.toBinary(value);
137            if(local.equals(Constants.SOAP_BASE64BINARY.getLocalPart())) return Caster.toBinary(value);
138            if(local.equals(Constants.SOAP_BOOLEAN.getLocalPart())) return Caster.toBoolean(value);
139            if(local.equals(Constants.SOAP_BYTE.getLocalPart())) return Caster.toByte(value);
140            if(local.equals(Constants.SOAP_DECIMAL.getLocalPart())) return new BigDecimal(Caster.toDoubleValue(value));
141            if(local.equals(Constants.SOAP_DOUBLE.getLocalPart())) return Caster.toDouble(value);
142            if(local.equals(Constants.SOAP_FLOAT.getLocalPart())) return new Float(Caster.toDoubleValue(value));
143            if(local.equals(Constants.SOAP_INT.getLocalPart())) return Caster.toInteger(value);
144            if(local.equals(Constants.SOAP_INTEGER.getLocalPart())) return Caster.toInteger(value);
145            if(local.equals(Constants.SOAP_LONG.getLocalPart())) return Caster.toLong(value);
146            if(local.equals(Constants.SOAP_MAP.getLocalPart())) return toMap(tm,value,targetClass,done);
147            if(local.equals(Constants.SOAP_SHORT.getLocalPart())) return Caster.toShort(value);
148            if(local.equals(Constants.SOAP_STRING.getLocalPart())) return Caster.toString(value);
149            if(local.equals(Constants.SOAP_VECTOR.getLocalPart())) return toVector(tm,value,targetClass,done);
150            
151            // TODO SOAP_COMMON_ATTRS11, SOAP_COMMON_ATTRS12, SOAP_DOCUMENT, SOAP_ELEMENT
152            return _toAxisTypeSub(tm,value,targetClass,done);
153            
154            
155        }
156    
157        private static Object toAxisTypeXSD(TypeMapping tm,TimeZone tz,QName type, Object value, Class targetClass, Set<Object> done) throws PageException {
158            String local = type.getLocalPart();
159            if(local.equals(Constants.XSD_ANYSIMPLETYPE.getLocalPart())) return Caster.toString(value);
160            if(local.equals(Constants.XSD_ANYURI.getLocalPart())) return toURI(value);
161            if(local.equals(Constants.XSD_STRING.getLocalPart())) return Caster.toString(value);
162            if(local.equals(Constants.XSD_BASE64.getLocalPart())) return Caster.toBinary(value);
163            if(local.equals(Constants.XSD_BOOLEAN.getLocalPart())) return Caster.toBoolean(value);
164            if(local.equals(Constants.XSD_BYTE.getLocalPart())) return Caster.toByte(value);
165            if(local.equals(Constants.XSD_DATE.getLocalPart())) return Caster.toDate(value,null);
166            if(local.equals(Constants.XSD_DATETIME.getLocalPart())) return Caster.toDate(value,null);
167            if(local.equals(Constants.XSD_DAY.getLocalPart())) return toDay(value);
168            if(local.equals(Constants.XSD_DECIMAL.getLocalPart())) return new BigDecimal(Caster.toDoubleValue(value));
169            if(local.equals(Constants.XSD_DOUBLE.getLocalPart())) return Caster.toDouble(value);
170            if(local.equals(Constants.XSD_DURATION.getLocalPart())) return toDuration(value);
171            if(local.equals(Constants.XSD_ENTITIES.getLocalPart())) return toEntities(value);
172            if(local.equals(Constants.XSD_ENTITY.getLocalPart())) return toEntity(value);
173            if(local.equals(Constants.XSD_FLOAT.getLocalPart())) return new Float(Caster.toDoubleValue(value));
174            if(local.equals(Constants.XSD_HEXBIN.getLocalPart())) return Caster.toBinary(value);
175            if(local.equals(Constants.XSD_ID.getLocalPart())) return Caster.toString(value);
176            if(local.equals(Constants.XSD_IDREF.getLocalPart())) return Caster.toString(value);
177            if(local.equals(Constants.XSD_IDREFS.getLocalPart())) return Caster.toString(value);
178            if(local.equals(Constants.XSD_INT.getLocalPart())) return Caster.toInteger(value);
179            if(local.equals(Constants.XSD_INTEGER.getLocalPart())) return Caster.toInteger(value);
180            if(local.equals(Constants.XSD_LANGUAGE.getLocalPart())) return toLanguage(value);
181            if(local.equals(Constants.XSD_LONG.getLocalPart())) return Caster.toLong(value);
182            if(local.equals(Constants.XSD_MONTH.getLocalPart())) return toMonth(value);
183            if(local.equals(Constants.XSD_MONTHDAY.getLocalPart())) return toMonthDay(value);
184            if(local.equals(Constants.XSD_NAME.getLocalPart())) return toName(value);
185            if(local.equals(Constants.XSD_NCNAME.getLocalPart())) return toNCName(value);
186            if(local.equals(Constants.XSD_NEGATIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
187            if(local.equals(Constants.XSD_NMTOKEN.getLocalPart())) return toNMToken(value);
188            if(local.equals(Constants.XSD_NMTOKENS.getLocalPart())) return toNMTokens(value);
189            if(local.equals(Constants.XSD_NONNEGATIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
190            if(local.equals(Constants.XSD_NONPOSITIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
191            if(local.equals(Constants.XSD_NORMALIZEDSTRING.getLocalPart())) return Caster.toString(value);
192            if(local.equals(Constants.XSD_POSITIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
193            if(local.equals(Constants.XSD_QNAME.getLocalPart())) return toQName(value);
194            if(local.equals(Constants.XSD_SCHEMA.getLocalPart())) return toQName(value);
195            if(local.equals(Constants.XSD_SHORT.getLocalPart())) return Caster.toShort(value);
196            if(local.equals(Constants.XSD_TIME.getLocalPart())) return DateCaster.toTime(tz,value);
197            if(local.equals(Constants.XSD_TIMEINSTANT1999.getLocalPart())) return DateCaster.toTime(tz,value);
198            if(local.equals(Constants.XSD_TIMEINSTANT2000.getLocalPart())) return DateCaster.toTime(tz,value);
199            if(local.equals(Constants.XSD_TOKEN.getLocalPart())) return toToken(value);
200            if(local.equals(Constants.XSD_UNSIGNEDBYTE.getLocalPart())) return Caster.toByte(value);
201            if(local.equals(Constants.XSD_UNSIGNEDINT.getLocalPart())) return Caster.toInteger(value);
202            if(local.equals(Constants.XSD_UNSIGNEDLONG.getLocalPart())) return Caster.toLong(value);
203            if(local.equals(Constants.XSD_UNSIGNEDSHORT.getLocalPart())) return Caster.toShort(value);
204            if(local.equals(Constants.XSD_YEAR.getLocalPart())) return toYear(value);
205            if(local.equals(Constants.XSD_YEARMONTH.getLocalPart())) return toYearMonth(value);
206            return _toAxisTypeSub(tm,value,targetClass,done);
207        }
208    
209        private static ArrayList<Object> toArrayList(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
210            Array arr = Caster.toArray(value);
211            ArrayList<Object> al=new ArrayList<Object>();
212            int len=arr.size();
213            Object o;
214            for(int i=0;i<len;i++) {
215                o=arr.get(i+1,null);
216                al.add(i,_toAxisType(tm,null,null,o,targetClass,done));
217            }
218            return al;
219        }
220        private static Object[] toNativeArray(TypeMapping tm,Object value,Class targetClass, Set<Object> done) throws PageException {
221            Object[] objs = Caster.toNativeArray(value);
222            Object[] rtns;
223            Class componentType = null;
224            if(targetClass!=null) {
225                    componentType = targetClass.getComponentType();
226            }
227            
228            if(componentType!=null) 
229                    rtns = (Object[]) java.lang.reflect.Array.newInstance(componentType, objs.length);
230            else 
231                    rtns = new Object[objs.length];
232            
233            for(int i=0;i<objs.length;i++) {
234                    rtns[i]=_toAxisType(tm,null,null,objs[i],componentType,done);
235            }
236            return rtns;
237        }
238    
239        private static Vector<Object> toVector(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
240            Array arr = Caster.toArray(value);
241            Vector<Object> v=new Vector<Object>();
242            int len=arr.size();
243            Object o;
244            for(int i=0;i<len;i++) {
245                o=arr.get(i+1,null);
246                v.set(i,_toAxisType(tm,null,null,o,targetClass,done));
247            }
248            return v;
249        }
250    
251        private static Object toPojo(TypeMapping tm,Component comp, Class targetClass, Set<Object> done) throws PageException {
252    
253            PageContext pc = ThreadLocalPageContext.get(); 
254            
255                try {
256                    return _toPojo(pc, tm, comp,targetClass,done);
257                            
258                    }
259                    catch (Exception e) {
260                            throw Caster.toPageException(e);
261                    }
262                    /*finally {
263                            //pc.removeLastPageSource(true);
264                    }*/
265        }
266        
267        private static Object _toPojo(PageContext pc, TypeMapping tm,Component comp, Class targetClass, Set<Object> done) throws PageException {//print.ds();System.exit(0);
268            ComponentAccess ca = ComponentUtil.toComponentAccess(comp);
269            comp=ComponentWrap.toComponentWrap(Component.ACCESS_PRIVATE,ca);
270                    ComponentScope scope = ca.getComponentScope();
271            
272            Property[] props=comp.getProperties(false);
273            //Map rtn=new HashTable();
274            Object obj=null;
275                    try {
276                            obj = ClassUtil.loadInstance(ComponentUtil.getServerComponentPropertiesClass(pc,comp));
277                    } catch (ClassException e) {
278                            throw Caster.toPageException(e);
279                    }
280            
281            //PageContext pc = ThreadLocalPageContext.get();
282            Property p;
283            Object v;
284            Collection.Key k;
285                    CFMLExpressionInterpreter interpreter = new CFMLExpressionInterpreter();
286            for(int i=0;i<props.length;i++){
287                    p=props[i];
288                    k=Caster.toKey(p.getName());
289            // value
290                    v=scope.get(k,null);
291                    if(v==null)v=comp.get(k, null);
292            // default
293                    
294                    if(v!=null)v=Caster.castTo(pc, p.getType(), v, false);
295                    else{
296                            if(!StringUtil.isEmpty(p.getDefault())){
297                                    try {
298                                            v=Caster.castTo(pc, p.getType(), p.getDefault(), false);
299                                            
300                                    }
301                                    catch(PageException pe) {
302                                            try {
303                                                    v=interpreter.interpret(pc, p.getDefault());
304                                                    v=Caster.castTo(pc, p.getType(), v, false);
305                                            }
306                                    catch(PageException pe2) {
307                                                    throw new ExpressionException("can not use default value ["+p.getDefault()+"] for property ["+p.getName()+"] with type ["+p.getType()+"]");
308                                    }
309                                    }
310                            }
311                    }
312                    
313            // set or throw
314                    if(v==null) {
315                            if(p.isRequired())throw new ExpressionException("required property ["+p.getName()+"] is not defined");
316                    }
317                    else {
318                            Reflector.callSetter(obj, p.getName().toLowerCase(), _toAxisType(tm,null,null,v,targetClass,done));     
319                    }
320            }
321            return obj;
322        }
323        
324        private static QueryBean toQueryBean(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
325            Query query = Caster.toQuery(value);
326                    int recordcount=query.getRecordcount();
327            String[] columnList = query.getColumns();
328            QueryColumn[] columns=new QueryColumn[columnList.length];
329            Object[][] data = new Object[recordcount][columnList.length];
330            
331            for(int i=0;i<columnList.length;i++) {
332                    columns[i]=query.getColumn(columnList[i]);
333            }
334            
335            int row;
336            for(row=1;row<=recordcount;row++) {
337                for(int i=0;i<columns.length;i++) {
338                    data[row-1][i]=_toAxisType(tm,null,null,columns[i].get(row,null),targetClass,done);
339                }
340            }
341            
342            QueryBean qb = new QueryBean();
343            qb.setColumnList(columnList);
344            qb.setData(data);
345            return qb;
346            
347        }
348        
349    
350        
351        private static Map<String,Object> toMap(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
352            Struct src = Caster.toStruct(value);
353            Map<String,Object> trg=new HashMap<String,Object>();
354            Iterator<Entry<Key, Object>> it = src.entryIterator();
355            Entry<Key, Object> e;
356            while(it.hasNext()) {
357                    e = it.next();
358                trg.put(e.getKey().getString(),_toAxisType(tm,null,null,e.getValue(),targetClass,done));
359    
360            }
361            return trg;
362            
363        }
364    
365        private static Object _toAxisTypeSub(TypeMapping tm,Object value,Class targetClass,Set<Object> done) throws PageException {
366            // Date
367            if(value instanceof Date) {// not set to Decision.isDate(value)
368                    return new Date(((Date)value).getTime());
369            }
370            
371            // Array
372            if(Decision.isArray(value) && !(value instanceof Argument)) {
373                    if(value instanceof byte[]) return value;
374                    return toNativeArray(tm,value,targetClass,done);
375            }
376            // Struct
377            if(Decision.isStruct(value)) {
378                    if(value instanceof Component) {
379                            Object pojo= toPojo(tm,(Component)value,targetClass,done);
380                            try     {       
381                                    QName name = new QName("http://rpc.xml.coldfusion",pojo.getClass().getName());
382                                    TypeMappingUtil.registerBeanTypeMapping(tm, pojo.getClass(), name);
383                                    
384                            }
385                            catch(Throwable fault){
386                                    throw Caster.toPageException(fault);
387                            }
388                            return pojo;
389                    }
390                    return toMap(tm,value,targetClass,done);
391            }
392            // Query
393            if(Decision.isQuery(value)) return toQueryBean(tm,value,targetClass,done);
394            // Other
395            return value;
396        }
397        
398        public static Class toAxisTypeClass(Class clazz) {
399            if(Query.class==clazz) return QueryBean.class;
400            if(Array.class==clazz) return Object[].class;
401            if(Struct.class==clazz) return Map.class;
402            return clazz;
403        }
404        
405        private static Object toURI(Object value) throws PageException {
406            if(value instanceof URI) return value;
407            if(value instanceof java.net.URI) return value;
408            try {
409                return new URI(Caster.toString(value));
410            } catch (MalformedURIException e) {
411                throw Caster.toPageException(e);
412            }
413        }
414    
415        private static Token toToken(Object value) throws PageException {
416            if(value instanceof Token) return (Token) value;
417            return new Token(Caster.toString(value));
418        }
419        
420        private static QName toQName(Object value) throws PageException {
421            if(value instanceof QName) return (QName) value;
422            return new QName(Caster.toString(value));
423        }
424    
425        private static NMTokens toNMTokens(Object value) throws PageException {
426            if(value instanceof NMTokens) return (NMTokens) value;
427            return new NMTokens(Caster.toString(value));
428        }
429        
430        private static NMToken toNMToken(Object value) throws PageException {
431            if(value instanceof NMToken) return (NMToken) value;
432            return new NMToken(Caster.toString(value));
433        }
434        private static NCName toNCName(Object value) throws PageException {
435            if(value instanceof NCName) return (NCName) value;
436            return new NCName(Caster.toString(value));
437        }
438    
439        private static Name toName(Object value) throws PageException {
440            if(value instanceof Name) return (Name) value;
441            return new Name(Caster.toString(value));
442        }
443    
444        private static Language toLanguage(Object value) throws PageException {
445            if(value instanceof Language) return (Language) value;
446            return new Language(Caster.toString(value));
447        }
448    
449        private static Entities toEntities(Object value) throws PageException {
450            if(value instanceof Entities) return (Entities) value;
451            return new Entities(Caster.toString(value));
452        }
453        
454        private static Entity toEntity(Object value) throws PageException {
455            if(value instanceof Entity) return (Entity) value;
456            return new Entity(Caster.toString(value));
457        }
458    
459        private static Day toDay(Object value) throws PageException {
460            if(value instanceof Day) return (Day) value;
461            if(Decision.isDateSimple(value,false)) {
462                return new Day(Caster.toDate(value,null).getDate());
463            }
464            
465            try {
466                return new Day(Caster.toIntValue(value));
467            } 
468            catch (Exception e) {
469                try {
470                    return new Day(Caster.toString(value));
471                } catch (NumberFormatException nfe) {
472                    throw Caster.toPageException(nfe);
473                } 
474                catch (ExpressionException ee) {
475                    throw ee;
476                }
477            }
478        }
479    
480        private static Year toYear(Object value) throws PageException {
481            if(value instanceof Year) return (Year) value;
482            if(Decision.isDateSimple(value,false)) {
483                return new Year(Caster.toDate(value,null).getYear());
484            }
485            try {
486                return new Year(Caster.toIntValue(value));
487            } 
488            catch (Exception e) {
489                try {
490                    return new Year(Caster.toString(value));
491                } catch (NumberFormatException nfe) {
492                    throw Caster.toPageException(nfe);
493                } 
494                catch (ExpressionException ee) {
495                    throw ee;
496                }
497            }
498        }
499    
500        private static Month toMonth(Object value) throws PageException {
501            if(value instanceof Month) return (Month) value;
502            if(Decision.isDateSimple(value,false)) {
503                return new Month(Caster.toDate(value,null).getMonth());
504            }
505            try {
506                return new Month(Caster.toIntValue(value));
507            } 
508            catch (Exception e) {
509                try {
510                    return new Month(Caster.toString(value));
511                } catch (NumberFormatException nfe) {
512                    throw Caster.toPageException(nfe);
513                } 
514                catch (ExpressionException ee) {
515                    throw ee;
516                }
517            }
518        }
519    
520        private static YearMonth toYearMonth(Object value) throws PageException {
521            if(value instanceof YearMonth) return (YearMonth) value;
522            if(Decision.isDateSimple(value,false)) {
523                DateTime dt = Caster.toDate(value,null);
524                return new YearMonth(dt.getYear(),dt.getMonth());
525            }
526            
527            try {
528                return new YearMonth(Caster.toString(value));
529            } catch (NumberFormatException nfe) {
530                throw Caster.toPageException(nfe);
531            } 
532            catch (ExpressionException ee) {
533                throw ee;
534            }
535        }
536    
537        private static MonthDay toMonthDay(Object value) throws PageException {
538            if(value instanceof MonthDay) return (MonthDay) value;
539            if(Decision.isDateSimple(value,false)) {
540                DateTime dt = Caster.toDate(value,null);
541                return new MonthDay(dt.getMonth(),dt.getDate());
542            }
543            
544            try {
545                return new MonthDay(Caster.toString(value));
546            } catch (NumberFormatException nfe) {
547                throw Caster.toPageException(nfe);
548            } 
549            catch (ExpressionException ee) {
550                throw ee;
551            }
552        }
553    
554        private static Duration toDuration(Object value) throws PageException, IllegalArgumentException {
555            if(value instanceof Duration) return (Duration) value;
556            try {
557                TimeSpan ts = Caster.toTimespan(value);
558                return new Duration(true, 0, 0, ts.getDay(), ts.getHour(), ts.getMinute(), ts.getSecond());
559            } catch (PageException e) {
560                return new Duration(Caster.toString(value));
561            }
562        }
563    
564        public static Object toRailoType(PageContext pc, Object value) throws PageException {
565            pc=ThreadLocalPageContext.get(pc);
566            if(pc!=null && value instanceof Pojo) {
567                    try{
568                            ComponentAccess c = ComponentUtil.toComponentAccess(pc.loadComponent(value.getClass().getName()));
569                            ComponentWrap cw=ComponentWrap.toComponentWrap(Component.ACCESS_PRIVATE,c);
570                    
571                            // delete this scope data members
572                            Collection.Key[] keys = cw.keys();
573                            Object member;
574                            for(int i=0;i<keys.length;i++) {
575                                    member = cw.get(keys[i]);
576                                    if(member instanceof UDF) continue;
577                        cw.removeEL(keys[i]);
578                            }
579                            
580                            
581                            Property[] props = c.getProperties(false);
582                            Property prop;
583                            for(int i=0;i<props.length;i++){
584                                    prop=props[i];
585                                    try{
586                                            cw.set(pc, KeyImpl.init(prop.getName()), toRailoType(pc,Reflector.callGetter(value, prop.getName())));
587                                    }
588                                    catch(PageException pe){
589                                            pe.printStackTrace();
590                                    }
591                            }
592                            return c;
593                    }
594                    catch(Throwable t){
595                            return value;
596                    }
597            }
598            if(value instanceof Date || value instanceof Calendar) {// do not change to caster.isDate
599                    return Caster.toDate(value,null);
600            }
601            if(value instanceof Object[]) {
602                    Object[] arr=(Object[]) value;
603                    if(!ArrayUtil.isEmpty(arr)){
604                            boolean allTheSame=true;
605                            // byte
606                            if(arr[0] instanceof Byte){
607                                    for(int i=1;i<arr.length;i++){
608                                            if(!(arr[i] instanceof Byte)){
609                                                    allTheSame=false;
610                                                    break;
611                                            }
612                                    }
613                                    if(allTheSame){
614                                            byte[] bytes=new byte[arr.length];
615                                            for(int i=0;i<arr.length;i++){
616                                            bytes[i]=Caster.toByteValue(arr[i]);
617                                    }
618                                            return bytes;
619                                    }
620                            }
621                    }
622            }
623            if(value instanceof Byte[]) {
624                    Byte[] arr=(Byte[]) value;
625                    if(!ArrayUtil.isEmpty(arr)){
626                                    byte[] bytes=new byte[arr.length];
627                                    for(int i=0;i<arr.length;i++){
628                                    bytes[i]=arr[i].byteValue();
629                            }
630                                    return bytes;
631                    }
632            }
633            if(value instanceof byte[]) {
634                    return value;
635            }
636            if(Decision.isArray(value)) {
637                Array a = Caster.toArray(value);
638                int len=a.size();
639                Object o;
640                for(int i=1;i<=len;i++) {
641                    o=a.get(i,null);
642                    if(o!=null)a.setEL(i,toRailoType(pc,o));
643                }
644                return a;
645            }
646            if(value instanceof Map) {
647                    Struct sct = new StructImpl();
648                Iterator it=((Map)value).entrySet().iterator();
649                Map.Entry entry;
650                while(it.hasNext()) {
651                    entry=(Entry) it.next();
652                    sct.setEL(Caster.toString(entry.getKey()),toRailoType(pc,entry.getValue()));
653                }
654                return sct;
655                    
656                    
657                    //return StructUtil.copyToStruct((Map)value);
658            }
659            if(isQueryBean(value)) {
660                    QueryBean qb = (QueryBean) value;
661                String[] strColumns = qb.getColumnList();
662                Object[][] data = qb.getData();
663                int recorcount=data.length;
664                Query qry=new QueryImpl(strColumns,recorcount,"QueryBean");
665                QueryColumn[] columns=new QueryColumn[strColumns.length];
666                for(int i=0;i<columns.length;i++) {
667                    columns[i]=qry.getColumn(strColumns[i]);
668                }
669                
670                int row;
671                for(row=1;row<=recorcount;row++) {
672                    for(int i=0;i<columns.length;i++) {
673                            columns[i].set(row,toRailoType(pc,data[row-1][i]));
674                    }
675                }
676                return qry;
677            }
678            if(Decision.isQuery(value)) {
679                Query q = Caster.toQuery(value);
680                int recorcount=q.getRecordcount();
681                String[] strColumns = q.getColumns();
682                
683                QueryColumn col;
684                int row;
685                for(int i=0;i<strColumns.length;i++) {
686                    col=q.getColumn(strColumns[i]);
687                    for(row=1;row<=recorcount;row++) {
688                        col.set(row,toRailoType(pc,col.get(row,null)));
689                    }
690                }
691                return q;
692            }
693            return value;
694        }
695    
696            private static boolean isQueryBean(Object value) {
697                    return (value instanceof QueryBean);
698            }
699    
700    
701    }