001    /**
002     * Implements the CFML Function structsort
003     */
004    package railo.runtime.functions.struct;
005    
006    import java.util.Arrays;
007    
008    import railo.runtime.PageContext;
009    import railo.runtime.exp.ExpressionException;
010    import railo.runtime.exp.PageException;
011    import railo.runtime.ext.function.Function;
012    import railo.runtime.interpreter.VariableInterpreter;
013    import railo.runtime.op.Caster;
014    import railo.runtime.type.Array;
015    import railo.runtime.type.ArrayImpl;
016    import railo.runtime.type.Collection;
017    import railo.runtime.type.Struct;
018    import railo.runtime.type.comparator.ExceptionComparator;
019    import railo.runtime.type.comparator.NumberSortRegisterComparator;
020    import railo.runtime.type.comparator.SortRegister;
021    import railo.runtime.type.comparator.SortRegisterComparator;
022    import railo.runtime.type.util.CollectionUtil;
023    
024    public final class StructSort implements Function {
025            public static Array call(PageContext pc , Struct base) throws PageException {
026                    return call(pc,base,"text","asc",null);
027            }
028            public static Array call(PageContext pc , Struct base, String sortType) throws PageException {
029                    return call(pc,base,sortType,"asc",null);
030            }
031            public static Array call(PageContext pc , Struct base, String sortType, String sortOrder) throws PageException {
032                    return call(pc,base,sortType,sortOrder,null);
033            }
034            public static Array call(PageContext pc , Struct base, String sortType, String sortOrder, String pathToSubElement) throws PageException {
035    
036                    boolean isAsc=true;
037                    PageException ee=null;
038                    if(sortOrder.equalsIgnoreCase("asc"))isAsc=true;
039                    else if(sortOrder.equalsIgnoreCase("desc"))isAsc=false;
040                    else throw new ExpressionException("invalid sort order type ["+sortOrder+"], sort order types are [asc and desc]");
041                    
042                    Collection.Key[] keys = CollectionUtil.keys(base);
043                    SortRegister[] arr=new SortRegister[keys.length];
044                    boolean hasSubDef=pathToSubElement!=null;
045                    
046                    for(int i=0;i<keys.length;i++) {
047                        Object value=base.get(keys[i],null);
048                        
049                        if(hasSubDef) {
050                            value=VariableInterpreter.getVariable(pc,Caster.toCollection(value),pathToSubElement);
051                        }               
052                        arr[i]=new SortRegister(i,value);
053                    }
054                    
055                    ExceptionComparator comp=null;
056                    // text
057                    if(sortType.equalsIgnoreCase("text")) comp=new SortRegisterComparator(isAsc,false);
058                    
059                    // text no case
060                    else if(sortType.equalsIgnoreCase("textnocase")) comp=new SortRegisterComparator(isAsc,true);                   
061                    
062                    // numeric
063                    else if(sortType.equalsIgnoreCase("numeric")) comp=new NumberSortRegisterComparator(isAsc);
064                            
065                    else {
066                            throw new ExpressionException("invalid sort type ["+sortType+"], sort types are [text, textNoCase, numeric]");
067                    }
068                    
069                    Arrays.sort(arr,0,arr.length,comp);
070                    ee=comp.getPageException();
071                    
072                    if(ee!=null) {
073                            throw ee;
074                    }
075                    
076                    Array rtn=new ArrayImpl();
077                    for(int i=0;i<arr.length;i++) {
078                        rtn.append(keys[arr[i].getOldPosition()].getString());
079                    }
080                    return rtn;
081                            
082            }
083            
084            
085            
086            
087    }