/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt ******************************************************************************/ package com.opendoorlogistics.core.formulae; import java.util.ArrayList; import java.util.List; import com.opendoorlogistics.core.formulae.Functions.FmAnd; import com.opendoorlogistics.core.formulae.Functions.FmConst; import com.opendoorlogistics.core.formulae.definitions.FunctionDefinitionLibrary; import com.opendoorlogistics.core.scripts.elements.UserFormula; import com.opendoorlogistics.core.scripts.formulae.FmLocalElement; import com.opendoorlogistics.core.utils.Numbers; public final class FunctionUtils { /** * Extract the constant string from the formula. The method will return null * if the formula does not contain a constant string. * * @param formula * @return */ public static String getConstantString(Function formula) { String ret = null; if (formula != null) { if (FmConst.class.isInstance(formula)) { FmConst cnst = (FmConst) formula; // allow a non-string object to be treated as a const string (e.g. '1') if (cnst.value() != null) { ret = cnst.value().toString(); } } else if (FmLocalElement.class.isInstance(formula)) { // We can have a local variable with the same name as remote one... just grab the name ret = ((FmLocalElement) formula).getName(); } } return ret; } public static Function [] toSingleArray(Function a, Function ...arr){ Function [] ret = new Function[arr.length+1]; ret[0] = a; for(int i =0 ; i < arr.length ; i++){ ret[i+1] = arr[i]; } return ret; } /** * Convert the function to an equivalent array of the form a[0] && a[1] && ... && a[n]. * The function can then be processed by testing each element is true consecutively * and returning false when the first non-true is found. * @param f * @return */ public static Function [] toEquivalentSplitAndArray(Function f){ final ArrayList<Function> andArrayList = new ArrayList<Function>(); class Helper{ void process(Function func){ if(func!=null){ if(FmAnd.class.isInstance(func)){ process(func.child(0)); process(func.child(1)); }else{ andArrayList.add(func); } } } } new Helper().process(f); return andArrayList.toArray(new Function[andArrayList.size()]); } public static void main(String[] args) throws Exception { FunctionDefinitionLibrary lib = new FunctionDefinitionLibrary(); lib.buildStd(); FormulaParser loader = new FormulaParser(null, lib, null); String function = "(2 && 5 && 7 && 2) + 1"; Function formula = loader.parse(function); for(Function split : toEquivalentSplitAndArray(formula)){ System.out.println("\t" + split + " -> " + split.execute(null)); } // System.out.println(formula.execute(null)); } public interface FunctionVisitor{ /** * Visit the function and return false if no more visits should be done * @param f * @return */ boolean visit(Function f); } public static boolean visit(Function f, FunctionVisitor visitor){ if(!visitor.visit(f)){ return false; } int n = f.nbChildren(); for(int i =0 ; i < n ; i++){ if(!visit(f.child(i), visitor)){ return false; } } return true; } public static boolean containsFunctionType(Function f, Class<? extends Function> functionType){ return visit(f, new FunctionVisitor() { @Override public boolean visit(Function f) { if(f!=null && functionType.isInstance(f)){ // stop the search... return false; } return true; } })==false; } public static boolean isTrue(Object exec){ if (exec != null) { Long val = Numbers.toLong(exec); if(val!=null && val.intValue()==1){ return true; } } return false; } }