/* * Copyright 1999-2006 University of Chicago * * Licensed 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 org.globus.rsl; import java.util.*; /** * This class represents an abstract RSL parse tree. It is composed of variable definitions * (bindings), relations, and sub-specifications (sub nodes). */ public class ListRslNode extends AbstractRslNode { protected List _relations = null; protected List _bindings = null; public ListRslNode() { super(); } public ListRslNode(int operator) { super(operator); } public boolean add(Bindings bindings) { if (_bindings == null) { _bindings = new LinkedList(); } return _bindings.add(bindings); } public boolean add(NameOpValue relation) { if (_relations == null) { _relations = new LinkedList(); } return _relations.add(relation); } /** * Returns the relation associated with the given attribute. * * @param attribute the attribute of the relation. * @return the relation for the attribute. Null, if not found. */ public NameOpValue getParam(String attribute) { if (_relations == null || attribute == null) return null; Iterator iter = _relations.iterator(); NameOpValue nv; String canonAttrib = canonicalize(attribute); String tmpCanonAttrib = null; while(iter.hasNext()) { nv = (NameOpValue)iter.next(); tmpCanonAttrib = canonicalize(nv.getAttribute()); if (tmpCanonAttrib.equalsIgnoreCase(canonAttrib)) { return nv; } } return null; } /** * Returns the variable definitions associated wit the given * attribute. * * @param attribute the attribute of the variable deinitions. * @return the variable deinitions for the attribute. * Null, if not found. */ public Bindings getBindings(String attribute) { if (_bindings == null || attribute == null) return null; Iterator iter = _bindings.iterator(); Bindings bind; String canonAttrib = canonicalize(attribute); String tmpCanonAttrib = null; while(iter.hasNext()) { bind = (Bindings)iter.next(); tmpCanonAttrib = canonicalize(bind.getAttribute()); if (tmpCanonAttrib.equalsIgnoreCase(canonAttrib)) { return bind; } } return null; } /** * Removes a bindings list for the specified attribute. * * @param attribute the attribute name for the * bindings. * @return the bindings that were removed. */ public Bindings removeBindings(String attribute) { if (_bindings == null || attribute == null) return null; Iterator iter = _bindings.iterator(); Bindings bind; String canonAttrib = canonicalize(attribute); String tmpCanonAttrib = null; while(iter.hasNext()) { bind = (Bindings)iter.next(); tmpCanonAttrib = canonicalize(bind.getAttribute()); if (tmpCanonAttrib.equalsIgnoreCase(canonAttrib)) { iter.remove(); return bind; } } return null; } /** * Removes a relation for the specified attribute. * * @param attribute the attribute name for the * relation to remove. * @return the relation that was removed. */ public NameOpValue removeParam(String attribute) { if (_relations == null || attribute == null) return null; Iterator iter = _relations.iterator(); NameOpValue nv; String canonAttrib = canonicalize(attribute); String tmpCanonAttrib = null; while(iter.hasNext()) { nv = (NameOpValue)iter.next(); tmpCanonAttrib = canonicalize(nv.getAttribute()); if (tmpCanonAttrib.equalsIgnoreCase(canonAttrib)) { iter.remove(); return nv; } } return null; } public void mergeTo(AbstractRslNode dstNode) { Iterator iter = null; super.mergeTo(dstNode); if (_relations != null) { iter = _relations.iterator(); NameOpValue nov, tmpNov; while(iter.hasNext()) { tmpNov = (NameOpValue)iter.next(); nov = dstNode.getParam(tmpNov.getAttribute()); if (nov == null) { dstNode.add(tmpNov); } else { nov.merge(tmpNov); } } } if (_bindings != null) { iter = _bindings.iterator(); Bindings bind, tmpBind; while(iter.hasNext()) { tmpBind = (Bindings)iter.next(); bind = dstNode.getBindings(tmpBind.getAttribute()); if (bind == null) { dstNode.add(tmpBind); } else { bind.merge(tmpBind); } } } } /** * Returns the relations. * * @return the list of relations. */ public List getRelations() { return _relations; } /** * Returns the variable definitions. * * @return the map of variable definitions. */ public List getBindings() { return _bindings; } /** * Evalutes the rsl tree against the specified symbol table. * All the variable definitions are first evaluated because * they might update the symbol table. Then all the relations * followed by the sub-specifications are evaluated. * * @param symbolTable the symbol table to evalute variables against. * @return the evaluated rsl tree. * @exception RslEvaluationException If an error occured during * rsl evaluation. */ public AbstractRslNode evaluate(Map symbolTable) throws RslEvaluationException { if (symbolTable == null) symbolTable = new HashMap(); Map localSymbolTable = null; Iterator iter = null; ListRslNode finalRsl = new ListRslNode(getOperator()); if (_bindings != null && _bindings.size() > 0) { iter = _bindings.iterator(); localSymbolTable = new HashMap(symbolTable); Bindings binds; while( iter.hasNext() ) { binds = (Bindings)iter.next(); finalRsl.add( binds.evaluate( localSymbolTable ) ); } } else { localSymbolTable = symbolTable; } if (_relations != null && _relations.size() > 0) { iter = _relations.iterator(); NameOpValue nov; while(iter.hasNext()) { nov = (NameOpValue)iter.next(); finalRsl.add( nov.evaluate(localSymbolTable) ); } } if (_specifications != null && _specifications.size() > 0) { iter = _specifications.iterator(); AbstractRslNode node; while(iter.hasNext()) { node = (AbstractRslNode)iter.next(); finalRsl.add( node.evaluate(localSymbolTable) ); } } return finalRsl; } /** * Produces a RSL representation of node. * * @param buf buffer to add the RSL representation to. * @param explicitConcat if true explicit concatination will * be used in RSL strings. */ public void toRSL(StringBuffer buf, boolean explicitConcat) { Iterator iter; buf.append( getOperatorAsString() ); if (_bindings != null && _bindings.size() > 0) { iter = _bindings.iterator(); Bindings binds; while( iter.hasNext() ) { binds = (Bindings)iter.next(); binds.toRSL(buf, explicitConcat); } } if (_relations != null && _relations.size() > 0) { iter = _relations.iterator(); NameOpValue nov; while(iter.hasNext()) { nov = (NameOpValue)iter.next(); nov.toRSL(buf, explicitConcat); } } if (_specifications != null && _specifications.size() > 0) { iter = _specifications.iterator(); AbstractRslNode node; while(iter.hasNext()) { node = (AbstractRslNode)iter.next(); buf.append(" ("); node.toRSL(buf, explicitConcat); buf.append(" )"); } } } }