public override void ReportError(RecognitionException e) { StringTemplateGroup group = self.Group; if (group == StringTemplate.defaultGroup) { self.Error("action parse error; template context is " + self.GetEnclosingInstanceStackString(), e); } else { self.Error("action parse error in group " + self.Group.Name + " line " + self.GroupFileLine + "; template context is " + self.GetEnclosingInstanceStackString(), e); } }
public virtual StringTemplate LookupTemplate( StringTemplate enclosingInstance, string name ) { //Console.Out.WriteLine( "look up " + Name + "::" + name ); if ( name.StartsWith( "super." ) ) { if ( _superGroup != null ) { int dot = name.IndexOf( '.' ); name = name.Substring( dot + 1 ); StringTemplate superScopeST = _superGroup.LookupTemplate( enclosingInstance, name ); //Console.Out.WriteLine( "superScopeST is " + // superScopeST.Group.Name + "::" + name + // " with native group " + superScopeST.NativeGroup.Name ); return superScopeST; } throw new ArgumentException( Name + " has no super group; invalid template: " + name ); } CheckRefreshInterval(); StringTemplate st; lock (_templates) { if (!_templates.TryGetValue(name, out st) || st == null) { // not there? Attempt to load if (!_templatesDefinedInGroupFile) { // only check the disk for individual template st = LoadTemplateFromBeneathRootDirOrCLASSPATH(GetFileNameFromTemplateName(name)); } if (st == null && _superGroup != null) { // try to resolve in super group st = _superGroup.GetInstanceOf(name); // make sure that when we inherit a template, that it's // group is reset; it's nativeGroup will remain where it was if (st != null) { st.Group = this; } } if (st != null) { // found in superGroup // insert into this group; refresh will allow super // to change it's def later or this group to add // an override. _templates[name] = st; } else { // not found; remember that this sucker doesn't exist _templates[name] = NOT_FOUND_ST; string context = ""; if (enclosingInstance != null) { context = "; context is " + enclosingInstance.GetEnclosingInstanceStackString(); } string hier = GetGroupHierarchyStackString(); context += "; group hierarchy is " + hier; throw new ArgumentException("Can't find template " + GetFileNameFromTemplateName(name) + context); } } else if (st == NOT_FOUND_ST) { return null; } //Console.Out.WriteLine( "lookup found " + st.Group.Name + "::" + st.Name ); } return st; }
protected object RawGetObjectProperty(StringTemplate self, object o, string propertyName) { Type c = o.GetType(); object val = null; // Special case: our automatically created Aggregates via // attribute name: "{obj.{prop1,prop2}}" if (c == typeof(StringTemplate.Aggregate)) { val = ((StringTemplate.Aggregate) o).Get(propertyName); return val; } // Special case: if it's a template, pull property from // it's attribute table. // TODO: TJP just asked himself why we can't do inherited attr here? else if (c == typeof(StringTemplate)) { IDictionary attributes = ((StringTemplate) o).Attributes; if (attributes != null) { val = attributes[propertyName]; return val; } } // Special case: if it's an IDictionary then pull using // key not the property method. // // Original intent was to DISALLOW general IDictionary interface // as people could pass in their database masquerading as a IDictionary. // Pragmatism won out ;-) if (typeof(IDictionary).IsAssignableFrom(c)) { IDictionary map = (IDictionary) o; if (propertyName.Equals("keys")) { val = map.Keys; } else if (propertyName.Equals("values")) { val = map.Values; } else if (map.Contains(propertyName)) { val = map[propertyName]; } else { if ( map.Contains(DEFAULT_MAP_VALUE_NAME) ) val = map[DEFAULT_MAP_VALUE_NAME]; } if (val == MAP_KEY_VALUE) { // no property defined; if a map in this group // then there may be a default value val = propertyName; } return val; } // try getXXX and isXXX properties // check cache PropertyLookupParams paramBag; //MemberInfo cachedMember = self.Group.GetCachedClassProperty(c, propertyName); //if ( cachedMember != null ) //{ // try // { // paramBag = new PropertyLookupParams(self, c, o, propertyName, null); // if ( cachedMember is PropertyInfo ) // { // // non-indexed property (since we don't cache indexers) // PropertyInfo pi = (PropertyInfo)cachedMember; // GetPropertyValue(pi, paramBag, ref val); // } // else if ( cachedMember is MethodInfo ) // { // MethodInfo mi = (MethodInfo)cachedMember; // GetMethodValue(mi, paramBag, ref val); // } // else if ( cachedMember is FieldInfo ) // { // // must be a field // FieldInfo fi = (FieldInfo)cachedMember; // GetFieldValue(fi, paramBag, ref val); // } // } // catch (Exception e) // { // self.Error("Can't get property '" + propertyName + // "' from '" + c.FullName + "' instance", e); // } // return val; //} // must look up using reflection // Search for propertyName as: // Property (non-indexed), Method(get_XXX, GetXXX, IsXXX, getXXX, isXXX), Field, this[string] string methodSuffix = Char.ToUpper(propertyName[0]) + propertyName.Substring(1); paramBag = new PropertyLookupParams(self, c, o, propertyName, methodSuffix); totalReflectionLookups++; if (!GetPropertyValueByName(paramBag, ref val)) { bool found = false; foreach (string prefix in new string[] { "get_", "Get", "Is", "get", "is" }) { paramBag.lookupName = prefix + methodSuffix; totalReflectionLookups++; if (found = GetMethodValueByName(paramBag, ref val)) break; } if (!found) { paramBag.lookupName = methodSuffix; totalReflectionLookups++; if (!GetFieldValueByName(paramBag, ref val)) { totalReflectionLookups++; PropertyInfo pi = c.GetProperty("Item", new Type[] { typeof(string) }); if (pi != null) { // TODO: we don't cache indexer PropertyInfo objects (yet?) // it would have complicated getting values from cached property objects try { val = pi.GetValue(o, new object[] { propertyName }); } catch(Exception ex) { self.Error("Can't get property " + propertyName + " via C# string indexer from " + c.FullName + " instance", ex); } } else { self.Error("Class " + c.FullName + " has no such attribute: " + propertyName + " in template context " + self.GetEnclosingInstanceStackString()); } } } } return val; }
// 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 StringTemplate.STAttributeList(); // convert all attributes to iterators even if just one value for (int a = 0; a < attributes.Count; a++) { object o = (object) attributes[a]; if (o != null) { o = ConvertAnythingToIterator(o); attributes[a] = o; // alter the list in place } } int numAttributes = attributes.Count; // ensure arguments line up HashList formalArguments = (HashList) templateToApply.FormalArguments; if (formalArguments == null || formalArguments.Count == 0) { self.Error("missing arguments in anonymous" + " template in context " + self.GetEnclosingInstanceStackString()); return null; } object[] formalArgumentNames = new object[formalArguments.Count]; formalArguments.Keys.CopyTo(formalArgumentNames, 0); if (formalArgumentNames.Length != numAttributes) { self.Error("number of arguments " + formalArguments.Keys.ToString() + " 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]; Array.Copy(formalArgumentNames, 0, newFormalArgumentNames, 0, shorterSize); formalArgumentNames = newFormalArgumentNames; } // keep walking while at least one attribute has values int i = 0; // iteration number from 0 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 != null) && it.MoveNext()) { string argName = (string) formalArgumentNames[a]; object iteratedValue = it.Current; argumentContext[argName] = iteratedValue; } else { numEmpty++; } } if (numEmpty == numAttributes) { break; } argumentContext[DEFAULT_INDEX_VARIABLE_NAME] = i+1; argumentContext[DEFAULT_INDEX0_VARIABLE_NAME] = i; StringTemplate embedded = templateToApply.GetInstanceOf(); embedded.EnclosingInstance = self; embedded.ArgumentContext = argumentContext; results.Add(embedded); i++; } return results; }
/// <summary> /// Get the template called 'name' from the group. If not found, /// attempt to load. If not found on disk, then try the superGroup /// if any. If not even there, then record that it's /// NOT_FOUND so we don't waste time looking again later. If we've gone /// past refresh interval, flush and look again. /// /// If I find a template in a super group, copy an instance down here /// </summary> public virtual StringTemplate LookupTemplate(StringTemplate enclosingInstance, string name) { lock (this) { if (name.StartsWith("super.")) { if (superGroup != null) { int dot = name.IndexOf('.'); name = name.Substring(dot + 1, (name.Length) - (dot + 1)); StringTemplate superScopeST = superGroup.LookupTemplate(enclosingInstance, name); return superScopeST; } throw new StringTemplateException(Name + " has no super group; invalid template: " + name); } StringTemplate st = (StringTemplate)templates[name]; if (st != null) { // Discard cached template? if (st.NativeGroup.TemplateHasChanged(name)) { templates.Remove(name); st = null; } } if (st == null) { // not there? Attempt to load if (!templatesDefinedInGroupFile) { // only check the disk for individual template st = LoadTemplate(name); } if (st == null && superGroup != null) { // try to resolve in super group //st = superGroup.GetInstanceOf(name); st = superGroup.GetInstanceOf(enclosingInstance, name); // make sure that when we inherit a template, that it's // group is reset; it's nativeGroup will remain where it was if (st != null) { st.Group = this; } } if (st != null) { // found in superGroup // insert into this group; refresh will allow super // to change it's def later or this group to add // an override. templates[name] = st; } else { // not found; remember that this sucker doesn't exist templates[name] = NOT_FOUND_ST; string context = ""; if (enclosingInstance != null) { context = "; context is " + enclosingInstance.GetEnclosingInstanceStackString(); } throw new TemplateLoadException(this, "Can't load template '" + GetLocationFromTemplateName(name) + "'" + context); } } else if (st == NOT_FOUND_ST) { return null; } return st; } }
/** <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 } Dictionary<string, object> argumentContext = null; // indicate it's an ST-created list var results = new StringTemplate.STAttributeList(); // convert all attributes to iterators even if just one value for ( int a = 0; a < attributes.Count; a++ ) { object o = attributes[a]; if ( o != null ) { o = ConvertAnythingToIterator( o ); attributes[a] = o; // alter the list in place } } int numAttributes = attributes.Count; // ensure arguments line up var formalArguments = templateToApply.FormalArguments; if ( formalArguments == null || formalArguments.Count == 0 ) { self.Error( "missing arguments in anonymous" + " template in context " + self.GetEnclosingInstanceStackString() ); return null; } string[] formalArgumentNames = formalArguments.Select( fa => fa.name ).ToArray(); if ( formalArgumentNames.Length != numAttributes ) { string formalArgumentsText = formalArguments.Select( fa => fa.name ).ToList().ToElementString(); self.Error( "number of arguments " + formalArgumentsText + " 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; string[] newFormalArgumentNames = new string[shorterSize]; Array.Copy( formalArgumentNames, 0, newFormalArgumentNames, 0, shorterSize ); formalArgumentNames = newFormalArgumentNames; } // keep walking while at least one attribute has values int i = 0; // iteration number from 0 for ( ; ; ) { argumentContext = new Dictionary<string, object>(); // 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++ ) { Iterator it = attributes[a] as Iterator; if ( it != null && it.hasNext() ) { string argName = formalArgumentNames[a]; object iteratedValue = it.next(); argumentContext[argName] = iteratedValue; } else { numEmpty++; } } if ( numEmpty == numAttributes ) { break; } argumentContext[DefaultIndexVariableName] = i + 1; argumentContext[DefaultIndex0VariableName] = i; StringTemplate embedded = templateToApply.GetInstanceOf(); embedded.EnclosingInstance = self; embedded.ArgumentContext = argumentContext; results.Add( embedded ); i++; } return results; }
protected virtual object RawGetObjectProperty( StringTemplate self, object o, object property ) { Type c = o.GetType(); object value = null; // Special case: our automatically created Aggregates via // attribute name: "{obj.{prop1,prop2}}" if ( c == typeof( StringTemplate.Aggregate ) ) { string propertyName2 = (string)property; value = ( (StringTemplate.Aggregate)o ).Get( (string)propertyName2 ); return value; } else if ( c == typeof( StringTemplate ) ) { // Special case: if it's a template, pull property from // it's attribute table. // TODO: TJP just asked himself why we can't do inherited attr here? var attributes = ( (StringTemplate)o ).Attributes; if ( attributes != null ) { string propertyName2 = (string)property; value = attributes.get( propertyName2 ); return value; } } // Special case: if it's a Map then pull using // key not the property method. IDictionary map = o as IDictionary; if ( map != null ) { if ( property.Equals( "keys" ) ) { value = map.Keys; } else if ( property.Equals( "values" ) ) { value = map.Values; } else if ( map.Contains( property ) ) { value = map[property]; } else if ( map.Contains( property.ToString() ) ) { // if we can't find the key, toString it value = map[property.ToString()]; } else { if ( map.Contains( DefaultMapValueName ) ) { value = map[DefaultMapValueName]; } } if ( value == MapKeyValue ) { value = property; } return value; } string propertyName = (string)property; var accessor = FindMember( c, propertyName ); if ( accessor != null ) { try { value = accessor( o ); } catch ( Exception e ) { self.Error( "Can't access property " + propertyName + " using method get/is" + propertyName + " or direct field access from " + c.Name + " instance", e ); } } else { self.Error( "Class " + c.Name + " has no such attribute: " + propertyName + " in template context " + self.GetEnclosingInstanceStackString(), null ); } return value; }