001    /**
002     * Implements the Cold Fusion 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.Struct;
017    import railo.runtime.type.comparator.ExceptionComparator;
018    import railo.runtime.type.comparator.NumberSortRegisterComparator;
019    import railo.runtime.type.comparator.SortRegister;
020    import railo.runtime.type.comparator.SortRegisterComparator;
021    
022    public final class StructSort implements Function {
023            public static Array call(PageContext pc , Struct base) throws PageException {
024                    return call(pc,base,"text","asc",null);
025            }
026            public static Array call(PageContext pc , Struct base, String sortType) throws PageException {
027                    return call(pc,base,sortType,"asc",null);
028            }
029            public static Array call(PageContext pc , Struct base, String sortType, String sortOrder) throws PageException {
030                    return call(pc,base,sortType,sortOrder,null);
031            }
032            public static Array call(PageContext pc , Struct base, String sortType, String sortOrder, String pathToSubElement) throws PageException {
033    
034                    boolean isAsc=true;
035                    PageException ee=null;
036                    if(sortOrder.equalsIgnoreCase("asc"))isAsc=true;
037                    else if(sortOrder.equalsIgnoreCase("desc"))isAsc=false;
038                    else throw new ExpressionException("invalid sort order type ["+sortOrder+"], sort order types are [asc and desc]");
039                    
040                    String[] keys = base.keysAsString();
041                    SortRegister[] arr=new SortRegister[keys.length];
042                    boolean hasSubDef=pathToSubElement!=null;
043                    
044                    for(int i=0;i<keys.length;i++) {
045                        Object value=base.get(keys[i],null);
046                        
047                        if(hasSubDef) {
048                            value=VariableInterpreter.getVariable(pc,Caster.toCollection(value),pathToSubElement);
049                        }               
050                        arr[i]=new SortRegister(i,value);
051                    }
052                    
053                    ExceptionComparator comp=null;
054                    // text
055                    if(sortType.equalsIgnoreCase("text")) comp=new SortRegisterComparator(isAsc,false);
056                    
057                    // text no case
058                    else if(sortType.equalsIgnoreCase("textnocase")) comp=new SortRegisterComparator(isAsc,true);                   
059                    
060                    // numeric
061                    else if(sortType.equalsIgnoreCase("numeric")) comp=new NumberSortRegisterComparator(isAsc);
062                            
063                    else {
064                            throw new ExpressionException("invalid sort type ["+sortType+"], sort types are [text, textNoCase, numeric]");
065                    }
066                    
067                    Arrays.sort(arr,0,arr.length,comp);
068                    ee=comp.getPageException();
069                    
070                    if(ee!=null) {
071                            throw ee;
072                    }
073                    
074                    Array rtn=new ArrayImpl();
075                    for(int i=0;i<arr.length;i++) {
076                        rtn.append(keys[arr[i].getOldPosition()]);
077                    }
078                    return rtn;
079                            
080            }
081            
082            
083            
084            
085    }