using System; using genlib = System.Collections.Generic; using edu.neu.ccs.demeterf.control; using edu.neu.ccs.demeterf.lib; using edu.neu.ccs.demeterf.util; using System.Reflection; namespace edu.neu.ccs.demeterf{ public abstract class AbstTraversal{ public static string BuilderMethod = "combine"; public static string AugmentorMethod = "update"; protected Control control; /** Create a Traversal that goes Everywhere */ public AbstTraversal() : this(Control.everywhere()) { } /** Create a Traversal with Selective edge/field Bypassing */ public AbstTraversal(Control eb){ control = eb; } /** Do the Traversal... No arguments */ public virtual Ret traverse(Object o){ return (Ret)traverse(o, Option.none()); } /** Do the Traversal... With an argument */ public virtual Ret traverse(Object o, Object a){ return (Ret)traverse(o, Option.some(a)); } static int indentAmt = 0; static String indent(){ return indent(indentAmt); } static String indent(int i){ if(i==0)return ""; return " "+indent(i-1); } // Do the Traversal... With an ML like Option argument (Some/None) protected virtual Ret traverse(Object o, Option arg){ indentAmt++; Type t = o.GetType(); bool hasArg = arg.some(); Object result = null; List fs = Util.getFuncFields(t); if(control.isBuiltIn(t)){ result = applyBuilder(Util.addArg(new Object[]{o},arg),true); }else{ if(t.IsArray){ Option narg = (hasArg)?applyAugment(new Object[]{o, arg.get()},null):arg; result = traverseArray((Object[])o, narg); }else{ genlib.List ret = new genlib.List(); ret.Add(o); foreach(FieldInfo f in fs){ Object tret = f.GetValue(o); if(tret == null){ // Throw an error if(!Util.allowNull)Util.nullFieldError(f); return default(Ret); }else{ Option farg = (hasArg)?applyAugment(new Object[]{o, arg.get()},f):arg; if(!control.skip(t, f.Name)) tret = traverse(tret, farg); } ret.Add(tret); } if(hasArg)ret.Add(arg.get()); result = applyBuilder(ret.ToArray(),false); } } indentAmt--; return (Ret)result; } /** Traverses each element of an Array, and Combines the results into * an Array with an element type of the 'closest' common supertype * of all returned valuse */ protected virtual Object traverseArray(Object[] o, Option arg){ genlib.List ret = new genlib.List(); Type t = Util.objectType; for(int i = 0; i < o.Length; i++){ Object el = traverse(o[i], arg); Type tel = el.GetType(); ret.Add(el); if(i == 1)t = tel; else while(!t.IsAssignableFrom(tel)) t = t.BaseType; } Object[] retArr = ret.ToArray(); Object[] typedArr = (Object[])(Array.CreateInstance(t, 0)); for(int i = 0; i < retArr.Length; i++) typedArr[i] = retArr[i]; return typedArr; } // Apply the Augmentor the the Argument at this Object protected Option applyAugment(Object[] o, FieldInfo f){ return Option.some(applyAugment(o, f.DeclaringType, f.Name)); } /** Apply the Builder to this list of 'Fields' */ protected abstract Object applyBuilder(Object[] o, bool leaf); /** Apply the Augmentor the the Argument at this Object */ protected abstract Object applyAugment(Object[] o, Type pc, String fn); } }