// HELP ROUTINES CALLED BY EVALUATOR TREE WALKER /// <summary> /// For names,phones:{n,p | ...} treat the names, phones as lists /// to be walked in lock step as n=names[i], p=phones[i]. /// </summary> public virtual Object applyTemplateToListOfAttributes(StringTemplate self, IList attributes, StringTemplate templateToApply) { if ( attributes==null || templateToApply==null || attributes.Count==0 ) { return null; // do not apply if missing templates or empty values } IDictionary argumentContext = null; IList results = new ArrayList(); // convert all attributes to iterators even if just one value for (int a = 0; a < attributes.Count; a++) { Object o = attributes[a]; o = convertAnythingToIterator(o); attributes[a] = o; } int numAttributes = attributes.Count; // ensure arguments line up IDictionary formalArguments = templateToApply.getFormalArguments(); if ( formalArguments==null || formalArguments.Count==0 ) { self.error("missing arguments in anonymous"+ " template in context "+self.getEnclosingInstanceStackString()); return null; } ICollection keys = formalArguments.Keys; Object[] formalArgumentNames = new object[keys.Count]; keys.CopyTo(formalArgumentNames,0); if ( formalArgumentNames.Length!=numAttributes ) { self.error("number of arguments "+SupportClass.CollectionToString(formalArguments.Keys)+ " mismatch between attribute list and anonymous"+ " template in context "+self.getEnclosingInstanceStackString()); // truncate arg list to match smaller size int shorterSize = Math.Min(formalArgumentNames.Length, numAttributes); numAttributes = shorterSize; Object[] newFormalArgumentNames = new Object[shorterSize]; System.Array.Copy(formalArgumentNames, 0, newFormalArgumentNames, 0, shorterSize); formalArgumentNames = newFormalArgumentNames; } // keep walking while at least one attribute has values while ( true ) { argumentContext = new Hashtable(); // get a value for each attribute in list; put into arg context // to simulate template invocation of anonymous template int numEmpty = 0; for (int a = 0; a < numAttributes; a++) { IEnumerator it = (IEnumerator)attributes[a]; if ( it.MoveNext() ) { String argName = (String)formalArgumentNames[a]; Object iteratedValue = it.Current; argumentContext[argName] = iteratedValue; } else { numEmpty++; } } if ( numEmpty==numAttributes ) { break; } StringTemplate embedded = templateToApply.getInstanceOf(); embedded.setEnclosingInstance(self); embedded.setArgumentContext(argumentContext); results.Add(embedded); } return results; }