001    /**
002     * Implements the CFML Function arraysort
003     */
004    package railo.runtime.functions.arrays;
005    
006    import java.util.Comparator;
007    
008    import railo.runtime.PageContext;
009    import railo.runtime.exp.CasterException;
010    import railo.runtime.exp.ExpressionException;
011    import railo.runtime.exp.FunctionException;
012    import railo.runtime.exp.PageException;
013    import railo.runtime.exp.PageRuntimeException;
014    import railo.runtime.functions.BIF;
015    import railo.runtime.op.Caster;
016    import railo.runtime.type.Array;
017    import railo.runtime.type.Closure;
018    import railo.runtime.type.UDF;
019    import railo.runtime.type.util.ArrayUtil;
020    
021    public final class ArraySort extends BIF {
022    
023            private static final long serialVersionUID = -747941236369495141L;
024    
025            public static boolean call(PageContext pc , Array array, Object sortTypeOrClosure) throws PageException {
026                    return call(pc , array, sortTypeOrClosure, "asc",false);
027            }
028            public static boolean call(PageContext pc , Array array, Object sortTypeOrClosure, String sortorder) throws PageException {
029                    return call(pc , array, sortTypeOrClosure, sortorder,false);
030            }
031            
032            public static boolean call(PageContext pc , Array array, Object sortTypeOrClosure, String sortorder, boolean localeSensitive) throws PageException {
033                    if(array.getDimension()>1)
034                            throw new ExpressionException("only 1 dimensional arrays can be sorted");
035    
036                    if(sortTypeOrClosure instanceof UDF){
037                            UDFComparator comp=new UDFComparator(pc, (UDF)sortTypeOrClosure);
038                            array.sort(comp);
039                    }
040                    else {
041                            array.sort(ArrayUtil.toComparator(pc,Caster.toString(sortTypeOrClosure), sortorder,localeSensitive));
042                    }
043                    return true;
044            }
045            
046            @Override
047            public Object invoke(PageContext pc, Object[] args) throws PageException {
048                    if(args.length==2)return call(pc,Caster.toArray(args[0]),args[1]);
049                    if(args.length==3)return call(pc,Caster.toArray(args[0]),args[1],Caster.toString(args[2]));
050                    return call(pc,Caster.toArray(args[0]),args[1],Caster.toString(args[2]),Caster.toBooleanValue(args[3]));
051            }
052    }
053    
054    class UDFComparator implements Comparator<Object> {
055    
056            private UDF udf;
057            private Object[] args=new Object[2];
058            private PageContext pc;
059            
060            public UDFComparator(PageContext pc,UDF udf){
061                    this.pc=pc;
062                    this.udf=udf;
063            }
064    
065            @Override
066            public int compare(Object oLeft, Object oRight) {
067                    try {
068                            args[0]=oLeft;
069                            args[1]=oRight;
070                            Object res = udf.call(pc, args, false);
071                            Integer i = Caster.toInteger(res,null);
072                            if(i==null) throw new FunctionException(pc,"ArraySort",2,"function","return value of the "+(udf instanceof Closure?"closure":"function ["+udf.getFunctionName()+"]")+" cannot be casted to a integer.",CasterException.createMessage(res, "integer"));
073                    return i.intValue();
074                    } 
075                    catch (PageException pe) {
076                            throw new PageRuntimeException(pe);
077                    }
078            }
079    
080    }