public Element getElement ( Path path , boolean errorIfNotFound ) throws EvaluationException { // Set the initial node to use. Element node = null ; // The initial element to use depends on the type of path. Define the // correct root element. switch ( path . getType ( ) ) { case ABSOLUTE : // Typical, very easy case. All absolute paths refer to this object. node = root ; break ; case RELATIVE : // Check to see if we are within a structure template by checking if // relativeRoot is set. If set, then proceed with lookup, otherwise // fail. if ( relativeRoot != null ) { node = relativeRoot ; } else { throw new EvaluationException ( "relative path ('" + path + "') cannot be used to retrieve element in configuration" ) ; } break ; case EXTERNAL : // This is an external path. Check the authority. String myObject = objectTemplate . name ; String externalObject = path . getAuthority ( ) ; if ( myObject . equals ( externalObject ) ) { // Easy case, this references itself. Just set the initial node // to the root of this object. node = root ; } else { // FIXME: Review this code. Much can probably be deleted. // Harder case, we must lookup the other object template, // compiling and building it as necessary. // Try loading the template. This may throw an // EvaluationException if something goes wrong in the load. Template externalTemplate = localAndGlobalLoad ( externalObject , ! errorIfNotFound ) ; // Check to see if the template was found. if ( externalTemplate != null && ! errorIfNotFound ) { // If we asked for only a lookup of the template, then we // need to ensure that the referenced template is added to // the dependencies. dependencies . put ( externalObject , externalTemplate ) ; objectDependencies . add ( externalObject ) ; } else if ( externalTemplate == null ) { // Throw an error or return null as appropriate. if ( errorIfNotFound ) { throw new EvaluationException ( "object template " + externalObject + " could not be found" , null ) ; } else { return null ; } } // Verify that the retrieved template is actually an object // template. if ( externalTemplate . type != TemplateType . OBJECT ) { throw new EvaluationException ( externalObject + " does not refer to an object template" ) ; } // Retrieve the build cache. BuildCache bcache = compiler . getBuildCache ( ) ; // Only check the object dependencies if this object is // currently in the "build" phase. If this is being validated, // then circular dependencies will be handled without problems. // If dependencies are checked, check BEFORE waiting for the // external object, otherwise the compilation may deadlock. if ( checkObjectDependencies ) { bcache . setDependency ( myObject , externalObject ) ; } // Wait for the result and set the node to the external object's // root element. BuildResult result = ( BuildResult ) bcache . waitForResult ( externalObject ) ; node = result . getRoot ( ) ; } break ; } // Now that the root node is defined, recursively descend through the // given terms to retrieve the desired element. assert ( node != null ) ; try { node = node . rget ( path . getTerms ( ) , 0 , node . isProtected ( ) , ! errorIfNotFound ) ; } catch ( InvalidTermException ite ) { throw new EvaluationException ( ite . formatMessage ( path ) ) ; } if ( ! errorIfNotFound || node != null ) { return node ; } else { throw new EvaluationException ( MessageUtils . format ( MSG_NO_VALUE_FOR_PATH , path . toString ( ) ) ) ; } }
Pull the value of an element from a configuration tree . This can either be an absolute relative or external path .