Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package asterix.parser.classad; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.TreeSet; import asterix.parser.classad.AMutableCharArrayString; import asterix.parser.classad.AttributeReference; import asterix.parser.classad.CaseInsensitiveString; import asterix.parser.classad.ClassAd; import asterix.parser.classad.ClassAdParser; import asterix.parser.classad.ClassAdUnParser; import asterix.parser.classad.Common; import asterix.parser.classad.EvalState; import asterix.parser.classad.ExprList; import asterix.parser.classad.ExprTree; import asterix.parser.classad.ExprTreeHolder; import asterix.parser.classad.FunctionCall; import asterix.parser.classad.Literal; import asterix.parser.classad.Operation; import asterix.parser.classad.PrettyPrint; import asterix.parser.classad.Value; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.asterix.om.base.AMutableDouble; import org.apache.asterix.om.base.AMutableInt32; import org.apache.asterix.om.base.AMutableInt64; import org.apache.asterix.om.base.AMutableString; import asterix.parser.classad.Value.NumberFactor; import asterix.parser.classad.object.pool.CaseInsensitiveStringPool; import org.apache.hyracks.api.exceptions.HyracksDataException; public class ClassAd extends ExprTree { /* * Static Variables */ public static final int ERR_OK = 0; public static final int ERR_MEM_ALLOC_FAILED = 1; public static final int ERR_BAD_VALUE = 255; public static final int ERR_FAILED_SET_VIEW_NAME = 256; public static final int ERR_NO_RANK_EXPR = 257; public static final int ERR_NO_REQUIREMENTS_EXPR = 258; public static final int ERR_BAD_PARTITION_EXPRS = 259; public static final int ERR_PARTITION_EXISTS = 260; public static final int ERR_MISSING_ATTRNAME = 261; public static final int ERR_BAD_EXPRESSION = 262; public static final int ERR_INVALID_IDENTIFIER = 263; public static final int ERR_MISSING_ATTRIBUTE = 264; public static final int ERR_NO_SUCH_VIEW = 265; public static final int ERR_VIEW_PRESENT = 266; public static final int ERR_TRANSACTION_EXISTS = 267; public static final int ERR_NO_SUCH_TRANSACTION = 268; public static final int ERR_NO_REPRESENTATIVE = 269; public static final int ERR_NO_PARENT_VIEW = 270; public static final int ERR_BAD_VIEW_INFO = 271; public static final int ERR_BAD_TRANSACTION_STATE = 272; public static final int ERR_NO_SUCH_CLASSAD = 273; public static final int ERR_BAD_CLASSAD = 275; public static final int ERR_NO_KEY = 276; public static final int ERR_LOG_OPEN_FAILED = 277; public static final int ERR_BAD_LOG_FILENAME = 278; public static final int ERR_NO_VIEW_NAME = 379; public static final int ERR_RENAME_FAILED = 280; public static final int ERR_NO_TRANSACTION_NAME = 281; public static final int ERR_PARSE_ERROR = 282; public static final int ERR_INTERNAL_CACHE_ERROR = 283; public static final int ERR_FILE_WRITE_FAILED = 284; public static final int ERR_FATAL_ERROR = 285; public static final int ERR_CANNOT_CHANGE_MODE = 286; public static final int ERR_CONNECT_FAILED = 287; public static final int ERR_CLIENT_NOT_CONNECTED = 288; public static final int ERR_COMMUNICATION_ERROR = 289; public static final int ERR_BAD_CONNECTION_TYPE = 290; public static final int ERR_BAD_SERVER_ACK = 291; public static final int ERR_CANNOT_REPLACE = 292; public static final int ERR_CACHE_SWITCH_ERROR = 293; public static final int ERR_CACHE_FILE_ERROR = 294; public static final int ERR_CACHE_CLASSAD_ERROR = 295; public static final int ERR_CANT_LOAD_DYNAMIC_LIBRARY = 296; public static final String ATTR_TOPLEVEL = "toplevel"; public static final String ATTR_ROOT = "root"; public static final String ATTR_SELF = "self"; public static final String ATTR_PARENT = "parent"; // The two names below are for compatibility public static final String ATTR_MY = "my"; public static final String ATTR_CURRENT_TIME = "CurrentTime"; // These versions are actually taken from an external file in the original cpp source code private static final int CLASSAD_VERSION_MAJOR = 8; private static final int CLASSAD_VERSION_MINOR = 0; private static final int CLASSAD_VERSION_PATCH = 0; private static final String CLASSAD_VERSION = "8.0.0"; public static final ArrayList<String> specialAttrNames = new ArrayList<String>(); private static final CaseInsensitiveStringPool StringPool = new CaseInsensitiveStringPool(); static { specialAttrNames.add(ATTR_TOPLEVEL); specialAttrNames.add(ATTR_ROOT); specialAttrNames.add(ATTR_SELF); specialAttrNames.add(ATTR_PARENT); } public static final FunctionCall curr_time_expr = FunctionCall.createFunctionCall("time", new ExprList()); private ClassAd alternateScope; //private boolean doDirtyTracking; private Map<CaseInsensitiveString, ExprTree> attrList = new HashMap<CaseInsensitiveString, ExprTree>(); private ClassAd chainedParentAd; private ClassAdParser parser = null; private ClassAd newAd = null; /* * Constructors */ public ClassAd() { chainedParentAd = null; alternateScope = null; newAd = new ClassAd(false, false); parser = new ClassAdParser(); } public ClassAd(boolean initializeParser, boolean initializeNewAd) { chainedParentAd = null; alternateScope = null; if (initializeNewAd) { newAd = new ClassAd(false, false); } if (initializeParser) { parser = new ClassAdParser(); } } public ClassAd(ClassAd ad) throws HyracksDataException { if (ad == null) { clear(); } else { copyFrom(ad); } } public void reset() { clear(); } public boolean isReset() { return false; } public ClassAd getAlternateScope() { return alternateScope; } public void setAlternateScope(ClassAd alternateScope) { this.alternateScope = alternateScope; } public Map<CaseInsensitiveString, ExprTree> getAttrList() { return attrList; } public void setAttrList(Map<CaseInsensitiveString, ExprTree> attrList) { this.attrList = attrList; } public void classAdLibraryVersion(AMutableInt32 major, AMutableInt32 minor, AMutableInt32 patch) { major.setValue(CLASSAD_VERSION_MAJOR); minor.setValue(CLASSAD_VERSION_MINOR); patch.setValue(CLASSAD_VERSION_PATCH); } public static void classAdLibraryVersion(AMutableString version_string) { version_string.setValue(CLASSAD_VERSION); } public static ArrayList<String> getSpecialAttrNames() { return specialAttrNames; } public static FunctionCall getCurrentTimeExpr() { return curr_time_expr; } //public TreeSet<CaseInsensitiveString> dirtyAttrList = new TreeSet<CaseInsensitiveString>(); /* Reference is an ordered set of Strings <The ordering uses less than ignore case>. Example below * TreeSet<String> references = new TreeSet<String>( * new Comparator<String>(){ * public int compare(String o1, String o2) { * return o1.compareToIgnoreCase(o2); * } * }); * // PortReferences is a Map<ClassAd,OrderedSet<Strings>> */ public boolean copyFrom(ClassAd ad) throws HyracksDataException { boolean succeeded = true; if (this == ad) { succeeded = false; } else { clear(); // copy scoping attributes super.copyFrom(ad); if (ad.chainedParentAd != null) { if (chainedParentAd == null) { chainedParentAd = new ClassAd(); } chainedParentAd.setValue(ad.chainedParentAd); } if (ad.alternateScope != null) { if (alternateScope == null) { alternateScope = new ClassAd(); } alternateScope.setValue(ad.alternateScope); } //this.doDirtyTracking = false; for (Entry<CaseInsensitiveString, ExprTree> attr : ad.attrList.entrySet()) { ExprTree tree = attr.getValue().copy(); attrList.put(attr.getKey(), tree); // if (ad.doDirtyTracking && ad.IsAttributeDirty(attr.getKey())) { // dirtyAttrList.add(attr.getKey()); //} } //doDirtyTracking = ad.doDirtyTracking; } return succeeded; } public boolean update(ClassAd ad) throws HyracksDataException { for (Entry<CaseInsensitiveString, ExprTree> attr : ad.attrList.entrySet()) { ExprTree tree = attr.getValue().copy(); attrList.put(attr.getKey(), tree); // if (ad.doDirtyTracking && ad.IsAttributeDirty(attr.getKey())) { // dirtyAttrList.add(attr.getKey()); //} } return true; } public boolean updateFromChain(ClassAd ad) throws HyracksDataException { ClassAd parent = ad.chainedParentAd; if (parent != null) { if (!updateFromChain(parent)) { return false; } } return update(ad); } public boolean copyFromChain(ClassAd ad) throws HyracksDataException { if (this == ad) { return false; } clear(); super.copyFrom(ad); return updateFromChain(ad); } public boolean sameAs(ExprTree tree) { boolean is_same; ExprTree pSelfTree = tree.self(); if (this == pSelfTree) { is_same = true; } else if (pSelfTree.getKind() != NodeKind.CLASSAD_NODE) { is_same = false; } else { ClassAd other_classad; other_classad = (ClassAd) pSelfTree; if (attrList.size() != other_classad.attrList.size()) { is_same = false; } else { is_same = true; for (Entry<CaseInsensitiveString, ExprTree> attr : attrList.entrySet()) { ExprTree this_tree = attr.getValue(); ExprTree other_tree = other_classad.lookup(attr.getKey()); if (other_tree == null) { is_same = false; break; } else if (!this_tree.sameAs(other_tree)) { is_same = false; break; } } } } return is_same; } public void clear() { unchain(); attrList.clear(); if (alternateScope != null) { alternateScope.clear(); } if (parser != null) { parser.reset(); } } public void unchain() { if (chainedParentAd != null) { chainedParentAd.clear(); } } public void getComponents(Map<CaseInsensitiveString, ExprTree> attrs) { attrs.clear(); for (Entry<CaseInsensitiveString, ExprTree> attr : this.attrList.entrySet()) { attrs.put(attr.getKey(), attr.getValue()); } } public ClassAd privateGetDeepScope(ExprTree tree) throws HyracksDataException { ClassAd scope = new ClassAd(); Value val = new Value(); if (tree == null) return (null); tree.setParentScope(this); if (!tree.publicEvaluate(val) || !val.isClassAdValue(scope)) { return (null); } return (scope); } // --- begin integer attribute insertion ---- public boolean insertAttr(String name, int value, NumberFactor f) throws HyracksDataException { ExprTree plit; Value val = new Value(); val.setIntegerValue(value); plit = Literal.createLiteral(val, f); return insert(name, plit); } public boolean insertAttr(String name, int value) throws HyracksDataException { return insertAttr(name, value, NumberFactor.NO_FACTOR); } public boolean insertAttr(String name, long value, NumberFactor f) throws HyracksDataException { ExprTree plit; Value val = new Value(); val.setIntegerValue(value); plit = Literal.createLiteral(val, f); return (insert(name, plit)); } public boolean insertAttr(String name, long value) throws HyracksDataException { return insertAttr(name, value, NumberFactor.NO_FACTOR); } public boolean deepInsertAttr(ExprTree scopeExpr, String name, int value, NumberFactor f) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); return (ad.insertAttr(name, value, f)); } public boolean deepInsertAttr(ExprTree scopeExpr, String name, long value, NumberFactor f) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); return (ad.insertAttr(name, value, f)); } // --- end integer attribute insertion --- // --- begin real attribute insertion --- public boolean insertAttr(String name, double value, NumberFactor f) throws HyracksDataException { ExprTree plit; Value val = new Value(); val.setRealValue(value); plit = Literal.createLiteral(val, f); return (insert(name, plit)); } public boolean deepInsertAttr(ExprTree scopeExpr, String name, double value, NumberFactor f) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); return (ad.insertAttr(name, value, f)); } // --- end real attribute insertion // --- begin boolean attribute insertion public boolean insertAttr(String name, boolean value) throws HyracksDataException { ExprTree plit; Value val = new Value(); val.setBooleanValue(value); plit = Literal.createLiteral(val); return (insert(name, plit)); } public boolean deepInsertAttr(ExprTree scopeExpr, String name, boolean value) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); return (ad.insertAttr(name, value)); } // --- end boolean attribute insertion // --- begin string attribute insertion public boolean insertAttr(String name, AMutableCharArrayString value) throws HyracksDataException { ExprTree plit; Value val = new Value(); val.setStringValue(value); plit = Literal.createLiteral(val); return (insert(name, plit)); } public boolean deepInsertAttr(ExprTree scopeExpr, String name, AMutableCharArrayString value) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); return (ad.insertAttr(name, value)); } public boolean insertAttr(String name, String value) throws HyracksDataException { ExprTree plit; Value val = new Value(); val.setStringValue(value); plit = Literal.createLiteral(val); return (insert(name, plit)); } public boolean deepInsertAttr(ExprTree scopeExpr, String name, String value) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); return (ad.insertAttr(name, value)); } // --- end string attribute insertion public boolean insert(String serialized_nvp) throws IOException { boolean bRet = false; String name, szValue; int pos, npos, vpos; int bpos = 0; // comes in as "name = value" "name= value" or "name =value" npos = pos = serialized_nvp.indexOf('='); // only try to process if the string is valid if (pos >= 0) { while (npos > 0 && serialized_nvp.charAt(npos - 1) == ' ') { npos--; } while (bpos < npos && serialized_nvp.charAt(bpos) == ' ') { bpos++; } name = serialized_nvp.substring(bpos, npos); vpos = pos + 1; while (serialized_nvp.charAt(vpos) == ' ') { vpos++; } szValue = serialized_nvp.substring(vpos); if (name.charAt(0) == '\'') { // We don't handle quoted attribute names for caching here. // Hand the name-value-pair off to the parser as a one-attribute // ad and merge the results into this ad. newAd.clear(); name = "[" + serialized_nvp.toString() + "]"; if (parser.parseClassAd(name, newAd, true)) { return update(newAd); } else { return false; } } ExprTree newTree; // we did not hit in the cache... parse the expression newTree = parser.ParseExpression(szValue); if (newTree != null) { // if caching is enabled, and we got to here then we know that the // cache doesn't already have an entry for this name:value, so add // it to the cache now. if (newTree.getKind() != NodeKind.LITERAL_NODE) { Literal lit = parser.getLiteral(); lit.getValue().setStringValue(szValue); bRet = insert(name, lit, false); } else { bRet = insert(name, newTree, false); } } } // end if pos >=0 return bRet; } public boolean insert(String attrName, ExprTree expr) throws HyracksDataException { return insert(attrName, expr.isTreeHolder() ? ((ExprTreeHolder) expr).getInnerTree() : expr, false); } public boolean insert(String attrName, ExprTree pRef, boolean cache) throws HyracksDataException { boolean bRet = false; ExprTree tree = pRef; // sanity checks if (attrName.isEmpty() || pRef == null) { throw new HyracksDataException(); } CaseInsensitiveString pstrAttr = StringPool.get(); pstrAttr.set(attrName); if (tree != null) { // parent of the expression is this classad tree.setParentScope(this); attrList.put(pstrAttr, tree); bRet = true; } return (bRet); } public boolean deepInsert(ExprTree scopeExpr, String name, ExprTree tree) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); return (ad.insert(name, tree)); } // --- end expression insertion // --- begin lookup methods public ExprTree lookup(String name) { CaseInsensitiveString aString = StringPool.get(); aString.set(name); ExprTree expr = lookup(aString); StringPool.put(aString); return expr; } public ExprTree lookup(CaseInsensitiveString name) { /*System.out.println("Lookup Printing all attributes with their values:"); for (Entry<String, ExprTree> entry : attrList.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue().getKind()); }*/ ExprTree attr = attrList.get(name); if (attr != null) { return attr; } else if (chainedParentAd != null) { return chainedParentAd.lookup(name); } else { return null; } } public ExprTree lookupInScope(AMutableCharArrayString name, ClassAd finalScope) { EvalState state = new EvalState(); ExprTreeHolder tree = new ExprTreeHolder(); int rval; state.setScopes(this); rval = lookupInScope(name.toString(), tree, state); if (rval == EvalResult.EVAL_OK.ordinal()) { finalScope.setValue(state.getCurAd()); return (tree); } finalScope.setValue(null); return null; } public int lookupInScope(String name, ExprTreeHolder expr, EvalState state) { ClassAd current = this; ClassAd superScope = new ClassAd(); expr.setInnerTree(null); while (expr.getInnerTree() == null && current != null) { // lookups/eval's being done in the 'current' ad state.getCurAd().setValue(current); // lookup in current scope expr.setInnerTree(current.lookup(name)); if ((expr.getInnerTree() != null)) { return EvalResult.EVAL_OK.ordinal(); } if (state.getRootAd().equals(current)) { superScope = null; } else { superScope = current.parentScope; } if (!getSpecialAttrNames().contains(name)) { // continue searching from the superScope ... current = superScope; if (current == this) { // NAC - simple loop checker return (EvalResult.EVAL_UNDEF.ordinal()); } } else if (name.equalsIgnoreCase(ATTR_TOPLEVEL) || name.equalsIgnoreCase(ATTR_ROOT)) { // if the "toplevel" attribute was requested ... expr.setInnerTree(state.getRootAd()); if (expr.getInnerTree() == null) { // NAC - circularity so no root return EvalResult.EVAL_FAIL.ordinal(); // NAC } // NAC return (expr.getInnerTree() != null ? EvalResult.EVAL_OK.ordinal() : EvalResult.EVAL_UNDEF.ordinal()); } else if (name.equalsIgnoreCase(ATTR_SELF) || name.equalsIgnoreCase(ATTR_MY)) { // if the "self" ad was requested expr.setInnerTree(state.getCurAd()); return (expr.getInnerTree() != null ? EvalResult.EVAL_OK.ordinal() : EvalResult.EVAL_UNDEF.ordinal()); } else if (name.equalsIgnoreCase(ATTR_PARENT)) { // the lexical parent expr.setInnerTree(superScope); return (expr.getInnerTree() != null ? EvalResult.EVAL_OK.ordinal() : EvalResult.EVAL_UNDEF.ordinal()); } else if (name.equalsIgnoreCase(ATTR_CURRENT_TIME)) { // an alias for time() from old ClassAds expr.setInnerTree(getCurrentTimeExpr()); return (expr.getInnerTree() != null ? EvalResult.EVAL_OK.ordinal() : EvalResult.EVAL_UNDEF.ordinal()); } } return (EvalResult.EVAL_UNDEF.ordinal()); } // --- end lookup methods // --- begin deletion methods public boolean delete(String name) throws HyracksDataException { CaseInsensitiveString aString = StringPool.get(); aString.set(name); boolean success = delete(aString); StringPool.put(aString); return success; } public boolean delete(CaseInsensitiveString name) throws HyracksDataException { boolean deleted_attribute; deleted_attribute = false; if (attrList.containsKey(name)) { attrList.remove(name); deleted_attribute = true; } // If the attribute is in the chained parent, we delete define it // here as undefined, whether or not it was defined here. This is // behavior copied from old ClassAds. It's also one reason you // probably don't want to use this feature in the future. if (chainedParentAd != null && chainedParentAd.lookup(name) != null) { Value undefined_value = new Value(); undefined_value.setUndefinedValue(); deleted_attribute = true; ExprTree plit = Literal.createLiteral(undefined_value); insert(name.get(), plit); } return deleted_attribute; } public boolean deepDelete(ExprTree scopeExpr, String name) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (false); CaseInsensitiveString aString = StringPool.get(); aString.set(name); ; boolean success = ad.delete(aString); StringPool.put(aString); return success; } // --- end deletion methods // --- begin removal methods public ExprTree remove(String name) throws HyracksDataException { ExprTree tree = null; if (attrList.containsKey(name)) { tree = attrList.remove(name); } // If the attribute is in the chained parent, we delete define it // here as undefined, whether or not it was defined here. This is // behavior copied from old ClassAds. It's also one reason you // probably don't want to use this feature in the future. if (chainedParentAd != null && chainedParentAd.lookup(name) != null) { if (tree == null) { tree = chainedParentAd.lookup(name); } Value undefined_value = new Value(); undefined_value.setUndefinedValue(); ExprTree plit = Literal.createLiteral(undefined_value); //why?? insert(name, plit); } return tree; } public ExprTree deepRemove(ExprTree scopeExpr, String name) throws HyracksDataException { ClassAd ad = privateGetDeepScope(scopeExpr); if (ad == null) return (null); return (ad.remove(name)); } // --- end removal methods public void privateSetParentScope(ClassAd ad) { // already set by base class for this node; we shouldn't propagate // the call to sub-expressions because this is a new scope } public void modify(ClassAd mod) throws HyracksDataException { ClassAd ctx; ExprTree expr; Value val = new Value(); // Step 0: Determine Context if ((expr = mod.lookup(Common.ATTR_CONTEXT)) != null) { if ((ctx = privateGetDeepScope(expr)) == null) { return; } } else { ctx = this; } // Step 1: Process Replace attribute if ((expr = mod.lookup(Common.ATTR_REPLACE)) != null) { ClassAd ad = new ClassAd(); if (expr.publicEvaluate(val) && val.isClassAdValue(ad)) { ctx.clear(); ctx.update(ad); } } // Step 2: Process Updates attribute if ((expr = mod.lookup(Common.ATTR_UPDATES)) != null) { ClassAd ad = new ClassAd(); if (expr.publicEvaluate(val) && val.isClassAdValue(ad)) { ctx.update(ad); } } // Step 3: Process Deletes attribute if ((expr = mod.lookup(Common.ATTR_DELETES)) != null) { ExprList list = new ExprList(); AMutableCharArrayString attrName = new AMutableCharArrayString(); // make a first pass to check that it is a list of strings ... if (!expr.publicEvaluate(val) || !val.isListValue(list)) { return; } for (ExprTree aExpr : list.getExprList()) { if (!aExpr.publicEvaluate(val) || !val.isStringValue(attrName)) { return; } } // now go through and delete all the named attributes ... for (ExprTree aExpr : list.getExprList()) { if (aExpr.publicEvaluate(val) && val.isStringValue(attrName)) { ctx.delete(attrName.toString()); } } } } public ExprTree copy() throws HyracksDataException { ClassAd newAd = new ClassAd(); newAd.parentScope = parentScope; newAd.chainedParentAd = chainedParentAd; for (Entry<CaseInsensitiveString, ExprTree> entry : attrList.entrySet()) { newAd.insert(entry.getKey().get(), entry.getValue().copy(), false); } return newAd; } public boolean publicEvaluate(EvalState state, Value val) { val.setClassAdValue(this); return (true); } public boolean privateEvaluate(EvalState state, Value val, ExprTreeHolder tree) throws HyracksDataException { val.setClassAdValue(this); tree.setInnerTree(copy()); return true; } public boolean privateFlatten(EvalState state, Value val, ExprTreeHolder tree, AMutableInt32 i) throws HyracksDataException { ClassAd newAd = new ClassAd(); Value eval = new Value(); ExprTreeHolder etree = new ExprTreeHolder(); ClassAd oldAd; tree.setInnerTree(null); // Just to be safe... wenger 2003-12-11. oldAd = state.getCurAd(); state.setCurAd(this); for (Entry<CaseInsensitiveString, ExprTree> entry : attrList.entrySet()) { // flatten expression if (!entry.getValue().publicFlatten(state, eval, etree)) { tree.setInnerTree(null); ; eval.clear(); state.setCurAd(oldAd); return false; } // if a value was obtained, convert it to a literal if (etree.getInnerTree() == null) { etree.setInnerTree(Literal.createLiteral(eval)); if (etree.getInnerTree() == null) { tree.setInnerTree(null); eval.clear(); state.setCurAd(oldAd); return false; } } newAd.attrList.put(entry.getKey(), etree); eval.clear(); } tree.setInnerTree(newAd); state.setCurAd(oldAd); return true; } public boolean evaluateAttr(String attr, Value val) throws HyracksDataException { EvalState state = new EvalState(); ExprTreeHolder tree = new ExprTreeHolder(); state.setScopes(this); switch (lookupInScope(attr, tree, state)) { case ExprTree.EVAL_FAIL_Int: return false; case ExprTree.EVAL_OK_Int: return (tree.publicEvaluate(state, val)); case ExprTree.EVAL_UNDEF_Int: val.setUndefinedValue(); return (true); case ExprTree.EVAL_ERROR_Int: val.setErrorValue(); return (true); default: return false; } } public boolean evaluateExpr(String buf, Value result) throws HyracksDataException { boolean successfully_evaluated; ExprTreeHolder tree = new ExprTreeHolder(); ClassAdParser parser = new ClassAdParser(); try { if (parser.parseExpression(buf, tree)) { successfully_evaluated = evaluateExpr(tree, result); } else { successfully_evaluated = false; } } catch (IOException e) { throw new HyracksDataException(e); } return successfully_evaluated; } public boolean evaluateExpr(ExprTreeHolder tree, Value val) throws HyracksDataException { EvalState state = new EvalState(); state.setScopes(this); return (tree.publicEvaluate(state, val)); } public boolean evaluateExpr(ExprTreeHolder tree, Value val, ExprTreeHolder sig) throws HyracksDataException { EvalState state = new EvalState(); state.setScopes(this); return (tree.publicEvaluate(state, val, sig)); } public boolean evaluateAttrInt(String attr, AMutableInt64 i) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isIntegerValue(i)); } public boolean evaluateAttrReal(String attr, AMutableDouble r) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isRealValue(r)); } public boolean evaluateAttrNumber(String attr, AMutableInt64 i) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isNumber(i)); } public boolean evaluateAttrNumber(String attr, AMutableDouble r) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isNumber(r)); } public boolean evaluateAttrString(String attr, AMutableCharArrayString buf, int len) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isStringValue(buf, len)); } public boolean evaluateAttrString(String attr, AMutableCharArrayString buf) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isStringValue(buf)); } public boolean evaluateAttrBool(String attr, MutableBoolean b) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isBooleanValue(b)); } public boolean evaluateAttrBoolEquiv(String attr, MutableBoolean b) throws HyracksDataException { Value val = new Value(); return (evaluateAttr(attr, val) && val.isBooleanValueEquiv(b)); } /* Reference is an ordered set of Strings <The ordering uses less than ignore case>. Example below * TreeSet<String> references = new TreeSet<String>( * new Comparator<String>(){ * public int compare(String o1, String o2) { * return o1.compareToIgnoreCase(o2); * } * }); * // PortReferences is a Map<ClassAd,OrderedSet<Strings>> */ public boolean getExternalReferences(ExprTree tree, TreeSet<String> refs, boolean fullNames) throws HyracksDataException { EvalState state = new EvalState(); // Treat this ad as the root of the tree for reference tracking. // If an attribute is only present in a parent scope of this ad, // then we want to treat it as an external reference. state.setRootAd(this); state.setCurAd(this); return (privateGetExternalReferences(tree, this, state, refs, fullNames)); } public boolean privateGetExternalReferences(ExprTree expr, ClassAd ad, EvalState state, TreeSet<String> refs, boolean fullNames) throws HyracksDataException { if (expr.isTreeHolder()) { expr = ((ExprTreeHolder) expr).getInnerTree(); } switch (expr.getKind()) { case LITERAL_NODE: // no external references here return (true); case ATTRREF_NODE: { ClassAd start = new ClassAd(); ExprTreeHolder tree = new ExprTreeHolder(); ExprTreeHolder result = new ExprTreeHolder(); AMutableCharArrayString attr = new AMutableCharArrayString(); Value val = new Value(); MutableBoolean abs = new MutableBoolean(); ((AttributeReference) expr).getComponents(tree, attr, abs); // establish starting point for attribute search if (tree.getInnerTree() == null) { start = abs.booleanValue() ? state.getRootAd() : state.getCurAd(); if (abs.booleanValue() && (start == null)) {// NAC - circularity so no root return false; // NAC } // NAC } else { if (!tree.publicEvaluate(state, val)) { return (false); } // if the tree evals to undefined, the external references // are in the tree part if (val.isUndefinedValue()) { if (fullNames) { AMutableCharArrayString fullName = new AMutableCharArrayString(); if (tree.getInnerTree() != null) { ClassAdUnParser unparser = new PrettyPrint(); unparser.unparse(fullName, tree); fullName.appendChar('.'); } fullName.appendString(attr); refs.add(fullName.toString()); return true; } else { if (state.getDepthRemaining() <= 0) { return false; } state.decrementDepth(); boolean ret = privateGetExternalReferences(tree, ad, state, refs, fullNames); state.incrementDepth(); return ret; } } // otherwise, if the tree didn't evaluate to a classad, // we have a problem if (!val.isClassAdValue(start)) { return (false); } } // lookup for attribute ClassAd curAd = state.getCurAd(); switch (start.lookupInScope(attr.toString(), result, state)) { case EVAL_ERROR_Int: // some error return (false); case EVAL_UNDEF_Int: // attr is external refs.add(attr.toString()); state.setCurAd(curAd); return (true); case EVAL_OK_Int: { // attr is internal; find external refs in result if (state.getDepthRemaining() <= 0) { state.setCurAd(curAd); return false; } state.decrementDepth(); boolean rval = privateGetExternalReferences(result, ad, state, refs, fullNames); state.incrementDepth(); state.setCurAd(curAd); return (rval); } case EVAL_FAIL_Int: default: // enh?? return (false); } } case OP_NODE: { // recurse on subtrees AMutableInt32 opKind = new AMutableInt32(0); ExprTreeHolder t1 = new ExprTreeHolder(); ExprTreeHolder t2 = new ExprTreeHolder(); ExprTreeHolder t3 = new ExprTreeHolder(); ((Operation) expr).getComponents(opKind, t1, t2, t3); if (t1.getInnerTree() != null && !privateGetExternalReferences(t1, ad, state, refs, fullNames)) { return (false); } if (t2.getInnerTree() != null && !privateGetExternalReferences(t2, ad, state, refs, fullNames)) { return (false); } if (t3.getInnerTree() != null && !privateGetExternalReferences(t3, ad, state, refs, fullNames)) { return (false); } return (true); } case FN_CALL_NODE: { // recurse on subtrees AMutableCharArrayString fnName = new AMutableCharArrayString(); ExprList args = new ExprList(); ((FunctionCall) expr).getComponents(fnName, args); for (ExprTree tree : args.getExprList()) { if (!privateGetExternalReferences(tree, ad, state, refs, fullNames)) { return (false); } } return (true); } case CLASSAD_NODE: { // recurse on subtrees Map<CaseInsensitiveString, ExprTree> attrs = new HashMap<CaseInsensitiveString, ExprTree>(); ((ClassAd) expr).getComponents(attrs); for (Entry<CaseInsensitiveString, ExprTree> entry : attrs.entrySet()) { if (state.getDepthRemaining() <= 0) { return false; } state.decrementDepth(); boolean ret = privateGetExternalReferences(entry.getValue(), ad, state, refs, fullNames); state.incrementDepth(); if (!ret) { return (false); } } return (true); } case EXPR_LIST_NODE: { // recurse on subtrees ExprList exprs = new ExprList(); ((ExprList) expr).getComponents(exprs); for (ExprTree exprTree : exprs.getExprList()) { if (state.getDepthRemaining() <= 0) { return false; } state.decrementDepth(); boolean ret = privateGetExternalReferences(exprTree, ad, state, refs, fullNames); state.incrementDepth(); if (!ret) { return (false); } } return (true); } default: return false; } } // PortReferences is a Map<ClassAd,TreeSet<Strings>> public boolean getExternalReferences(ExprTree tree, Map<ClassAd, TreeSet<String>> refs) throws HyracksDataException { EvalState state = new EvalState(); // Treat this ad as the root of the tree for reference tracking. // If an attribute is only present in a parent scope of this ad, // then we want to treat it as an external reference. state.setRootAd(this); state.setCurAd(this); return (privateGetExternalReferences(tree, this, state, refs)); } public boolean privateGetExternalReferences(ExprTree expr, ClassAd ad, EvalState state, Map<ClassAd, TreeSet<String>> refs) throws HyracksDataException { switch (expr.getKind()) { case LITERAL_NODE: // no external references here return (true); case ATTRREF_NODE: { ClassAd start = new ClassAd(); ExprTreeHolder tree = new ExprTreeHolder(); ExprTreeHolder result = new ExprTreeHolder(); AMutableCharArrayString attr = new AMutableCharArrayString(); Value val = new Value(); MutableBoolean abs = new MutableBoolean(); ((AttributeReference) expr).getComponents(tree, attr, abs); // establish starting point for attribute search if (tree.getInnerTree() == null) { start = abs.booleanValue() ? state.getRootAd() : state.getCurAd(); if (abs.booleanValue() && (start == null)) {// NAC - circularity so no root return false; // NAC } // NAC } else { if (!tree.publicEvaluate(state, val)) return (false); // if the tree evals to undefined, the external references // are in the tree part if (val.isUndefinedValue()) { return (privateGetExternalReferences(tree, ad, state, refs)); } // otherwise, if the tree didn't evaluate to a classad, // we have a problem if (!val.isClassAdValue(start)) return (false); // make sure that we are starting from a "valid" scope if (!refs.containsKey(start) && start != this) { return (false); } } // lookup for attribute ClassAd curAd = state.getCurAd(); TreeSet<String> pitr = refs.get(start); if (pitr == null) { pitr = new TreeSet<String>(); refs.put(start, pitr); } switch (start.lookupInScope(attr.toString(), result, state)) { case EVAL_ERROR_Int: // some error return (false); case EVAL_UNDEF_Int: // attr is external pitr.add(attr.toString()); state.setCurAd(curAd); return (true); case EVAL_OK_Int: { // attr is internal; find external refs in result boolean rval = privateGetExternalReferences(result, ad, state, refs); state.setCurAd(curAd); return (rval); } case EVAL_FAIL_Int: default: // enh?? return (false); } } case OP_NODE: { // recurse on subtrees AMutableInt32 opKind = new AMutableInt32(0); ExprTreeHolder t1 = new ExprTreeHolder(); ExprTreeHolder t2 = new ExprTreeHolder(); ExprTreeHolder t3 = new ExprTreeHolder(); ((Operation) expr).getComponents(opKind, t1, t2, t3); if (t1.getInnerTree() != null && !privateGetExternalReferences(t1, ad, state, refs)) { return (false); } if (t2.getInnerTree() != null && !privateGetExternalReferences(t2, ad, state, refs)) { return (false); } if (t3.getInnerTree() != null && !privateGetExternalReferences(t3, ad, state, refs)) { return (false); } return (true); } case FN_CALL_NODE: { // recurse on subtrees AMutableCharArrayString fnName = new AMutableCharArrayString(); ExprList args = new ExprList(); ((FunctionCall) expr).getComponents(fnName, args); for (ExprTree exprTree : args.getExprList()) { if (!privateGetExternalReferences(exprTree, ad, state, refs)) { return (false); } } return (true); } case CLASSAD_NODE: { // recurse on subtrees HashMap<CaseInsensitiveString, ExprTree> attrs = new HashMap<CaseInsensitiveString, ExprTree>(); ((ClassAd) expr).getComponents(attrs); for (Entry<CaseInsensitiveString, ExprTree> entry : attrs.entrySet()) { if (!privateGetExternalReferences(entry.getValue(), ad, state, refs)) { return (false); } } return (true); } case EXPR_LIST_NODE: { // recurse on subtrees ExprList exprs = new ExprList(); ((ExprList) expr).getComponents(exprs); for (ExprTree exprTree : exprs.getExprList()) { if (!privateGetExternalReferences(exprTree, ad, state, refs)) { return (false); } } return (true); } default: return false; } } /* Reference is an ordered set of Strings <The ordering uses less than ignore case>. Example below * TreeSet<String> references = new TreeSet<String>( * new Comparator<String>(){ * public int compare(String o1, String o2) { * return o1.compareToIgnoreCase(o2); * } * }); * // PortReferences is a Map<ClassAd,OrderedSet<Strings>> */ public boolean getInternalReferences(ExprTree tree, TreeSet<String> refs, boolean fullNames) throws HyracksDataException { EvalState state = new EvalState(); // Treat this ad as the root of the tree for reference tracking. // If an attribute is only present in a parent scope of this ad, // then we want to treat it as an external reference. state.setRootAd(this); state.setCurAd(this); return (privateGetInternalReferences(tree, this, state, refs, fullNames)); } //this is closely modelled off of _GetExternalReferences in the new_classads. public boolean privateGetInternalReferences(ExprTree expr, ClassAd ad, EvalState state, TreeSet<String> refs, boolean fullNames) throws HyracksDataException { switch (expr.getKind()) { //nothing to be found here! case LITERAL_NODE: { return true; } case ATTRREF_NODE: { ClassAd start = new ClassAd(); ExprTreeHolder tree = new ExprTreeHolder(); ExprTreeHolder result = new ExprTreeHolder(); AMutableCharArrayString attr = new AMutableCharArrayString(); Value val = new Value(); MutableBoolean abs = new MutableBoolean(); ((AttributeReference) expr).getComponents(tree, attr, abs); //figuring out which state to base this off of if (tree.getInnerTree() == null) { start = abs.booleanValue() ? state.getRootAd() : state.getCurAd(); //remove circularity if (abs.booleanValue() && (start == null)) { return false; } } else { boolean orig_inAttrRefScope = state.isInAttrRefScope(); state.setInAttrRefScope(true); boolean rv = privateGetInternalReferences(tree, ad, state, refs, fullNames); state.setInAttrRefScope(orig_inAttrRefScope); if (!rv) { return false; } if (!tree.publicEvaluate(state, val)) { return false; } // TODO Do we need extra handling for list values? // Should types other than undefined, error, or list // cause a failure? if (val.isUndefinedValue()) { return true; } //otherwise, if the tree didn't evaluate to a classad, //we have a problemo, mon. //TODO: but why? if (!val.isClassAdValue(start)) { return false; } } ClassAd curAd = state.getCurAd(); switch (start.lookupInScope(attr.toString(), result, state)) { case EVAL_ERROR_Int: return false; //attr is external, so let's find the internals in that //result //JUST KIDDING case EVAL_UNDEF_Int: { //boolean rval = _GetInternalReferences(result, ad, state, refs, fullNames); //state.getCurAd() = curAd; return true; } case EVAL_OK_Int: { //whoo, it's internal. // Check whether the attribute was found in the root // ad for this evaluation and that the attribute isn't // one of our special ones (self, parent, my, etc.). // If the ad actually has an attribute with the same // name as one of our special attributes, then count // that as an internal reference. // TODO LookupInScope() knows whether it's returning // the expression of one of the special attributes // or that of an attribute that actually appears in // the ad. If it told us which one, then we could // avoid the Lookup() call below. if (state.getCurAd() == state.getRootAd() && state.getCurAd().lookup(attr.toString()) != null) { refs.add(attr.toString()); } if (state.getDepthRemaining() <= 0) { state.setCurAd(curAd); return false; } state.decrementDepth(); boolean rval = privateGetInternalReferences(result, ad, state, refs, fullNames); state.incrementDepth(); //TODO: Does this actually matter? state.setCurAd(curAd); return rval; } case EVAL_FAIL_Int: default: // "enh??" return false; } } case OP_NODE: { //recurse on subtrees AMutableInt32 op = new AMutableInt32(0); ExprTreeHolder t1 = new ExprTreeHolder(); ExprTreeHolder t2 = new ExprTreeHolder(); ExprTreeHolder t3 = new ExprTreeHolder(); ((Operation) expr).getComponents(op, t1, t2, t3); if (t1.getInnerTree() != null && !privateGetInternalReferences(t1, ad, state, refs, fullNames)) { return false; } if (t2.getInnerTree() != null && !privateGetInternalReferences(t2, ad, state, refs, fullNames)) { return false; } if (t3.getInnerTree() != null && !privateGetInternalReferences(t3, ad, state, refs, fullNames)) { return false; } return true; } case FN_CALL_NODE: { //recurse on the subtrees! AMutableCharArrayString fnName = new AMutableCharArrayString(); ExprList args = new ExprList(); ((FunctionCall) expr).getComponents(fnName, args); for (ExprTree exprTree : args.getExprList()) { if (!privateGetInternalReferences(exprTree, ad, state, refs, fullNames)) { return false; } } return true; } case CLASSAD_NODE: { //also recurse on subtrees... HashMap<CaseInsensitiveString, ExprTree> attrs = new HashMap<CaseInsensitiveString, ExprTree>(); // If this ClassAd is only being used here as the scoping // for an attribute reference, don't recurse into all of // its attributes. if (state.isInAttrRefScope()) { return true; } ((ClassAd) expr).getComponents(attrs); for (Entry<CaseInsensitiveString, ExprTree> entry : attrs.entrySet()) { if (state.getDepthRemaining() <= 0) { return false; } state.decrementDepth(); boolean ret = privateGetInternalReferences(entry.getValue(), ad, state, refs, fullNames); state.incrementDepth(); if (!ret) { return false; } } return true; } case EXPR_LIST_NODE: { ExprList exprs = new ExprList(); ((ExprList) expr).getComponents(exprs); for (ExprTree exprTree : exprs.getExprList()) { if (state.getDepthRemaining() <= 0) { return false; } state.decrementDepth(); boolean ret = privateGetInternalReferences(exprTree, ad, state, refs, fullNames); state.incrementDepth(); if (!ret) { return false; } } return true; } default: return false; } } public boolean publicFlatten(ExprTree tree, Value val, ExprTreeHolder fexpr) throws HyracksDataException { EvalState state = new EvalState(); state.setScopes(this); return (tree.publicFlatten(state, val, fexpr)); } public boolean flattenAndInline(ExprTree tree, Value val, ExprTreeHolder fexpr) throws HyracksDataException { EvalState state = new EvalState(); state.setScopes(this); state.setFlattenAndInline(true); return (tree.publicFlatten(state, val, fexpr)); } public void chainToAd(ClassAd new_chain_parent_ad) { if (new_chain_parent_ad != null) { chainedParentAd = new_chain_parent_ad; } } public int pruneChildAd() { int iRet = 0; if (chainedParentAd != null) { // loop through cleaning all expressions which are the same. Iterator<Entry<CaseInsensitiveString, ExprTree>> it = attrList.entrySet().iterator(); while (it.hasNext()) { Entry<CaseInsensitiveString, ExprTree> entry = it.next(); ExprTree tree = chainedParentAd.lookup(entry.getKey()); if (tree != null && tree.sameAs(entry.getValue())) { // 1st remove from dirty list it.remove(); iRet++; } } } return iRet; } public ClassAd getChainedParentAd() { return chainedParentAd; } public void setValue(ClassAd value) { this.attrList = value.attrList; this.alternateScope = value.alternateScope; this.chainedParentAd = value.chainedParentAd; this.parentScope = value.parentScope; this.size = value.size; } public int size() { return attrList.size(); } public static void valStr(AMutableCharArrayString szUnparsedValue, ExprTree pTree) { szUnparsedValue.appendString(pTree.toString()); } public static void valStr(AMutableCharArrayString szOut, boolean tValue) { szOut.appendString(tValue ? "true" : "false"); } @Override public NodeKind getKind() { return NodeKind.CLASSAD_NODE; } @Override public boolean privateEvaluate(EvalState state, Value val) throws HyracksDataException { val.setClassAdValue(this); return (true); } public void insertAttr(String name, double value) throws HyracksDataException { insertAttr(name, value, NumberFactor.NO_FACTOR); } public void createParser() { parser = new ClassAdParser(); } }