    001    package escjava.tc;
    002
    003    import java.util.Iterator;
    004    import java.util.List;
    005    import java.util.LinkedList;
    006    import java.util.HashMap;
    007    import java.util.Map;
    008    import javafe.ast.FieldDecl;
    009    import javafe.ast.TypeDecl;
    010    import javafe.ast.FieldAccess;
    011    import javafe.ast.ASTDecoration;
    012    import javafe.ast.Expr;
    013    import javafe.ast.TypeNameVec;
    014    import javafe.ast.TypeName;
    015
    016    public class Datagroups {
    017
    018        /* Each TypeDecl has a decoration associated with it that contains a
    019           Map; this map has key type FieldDecl and value type List.  The
    020           FieldDecl is the model variable that has a datagroup and the List is
    021           the set of Expr instances in the datagroup.
    022
    023           The reason that the same fd has different datagroups depending on the
    024           TypeDecl is that the members of a datagroup are those fields mapped into
    025           it in a TypeDecl and its supertypes, but not those in other branches of
    026           the inheritance tree.
    027         */
    028
    029        //@ non_null
    030        static private final ASTDecoration datagroups =
    031                                              new ASTDecoration("datagroups");
    032
    033        //@ non_null
    034        static final private List empty = new LinkedList();
    035
    036        /** Get the items that are in the datagroup for fd */
    037        //@ requires fd != null;
    038        static public List get(TypeDecl td, FieldDecl fd) {
    039            Map map = (Map)datagroups.get(td);
    040            if (map == null) map = initMap(td);
    041            List list = (List)map.get(fd);
    042            if (list == null) list = empty;
    043    /*
    044            System.out.println("DG GET: " + td.id + " " + fd.id + ":");
    045            Iterator i = list.iterator();
    046            while (i.hasNext()) System.out.println(">>> " + i.next());
    047    */
    048            return list;
    049        }
    050
    051        /** Add Expr fa to the datagroup for declaration fd in the
    052            context of type td; the declaration fd may be in a superclass.
    053            When we fetch a contents of a datagroup, we only fetch the fields that
    054            are in td or its superclasses and super interfaces. */
    055        //@ requires fd != null;
    056        //@ requires td != null;
    057        static public void add(TypeDecl td, FieldDecl fd, Expr fa) {
    058            Map map = (Map) datagroups.get(td);
    059            if (map == null) map = initMap(td);
    060            List list = (List)map.get(fd);
    061            if (list == null) {
    062                list = new LinkedList();
    063                map.put(fd,list);
    064            }
    065            list.add(fa);
    066    //        System.out.println("ADDING TO " + td.id + " " + fd.id + " : " + fa);
    067        }
    068
    069        static public Map initMap(TypeDecl td) {
    070                //System.out.println("INITIALIZING MAP FOR " + td.id);
    071                // If the TypeDecl does not yet have a datagroup map, we create
    072                // one and initialize it with all the mappings contained in its
    073                // super types, since the TypeDecl will see both the datagroup and
    074                // the field mapped into the datagroup.  (This ignores access
    075                // visibility).  The supertypes have already been typechecked, so
    076                // their maps will be complete.
    077                Map map = new HashMap();
    078                javafe.tc.TypeSig ts = TypeSig.getSig(td).superClass();
    079                if (ts != null) {
    080                  //System.out.println("ADD FROM " + ts);
    081                  addToMap(map, getMap(ts.getTypeDecl()));
    082                }
    083                TypeNameVec tv = td.superInterfaces;
    084                for (int i=0; i<tv.size(); ++i) {
    085                    TypeName si = tv.elementAt(i);
    086                    TypeDecl itd = TypeSig.getSig(si).getTypeDecl();
    087                    //System.out.println("ADD FROM " + itd.id);
    088                    addToMap(map, getMap(itd) );
    089                }
    090                datagroups.set(td,map);
    091                return map;
    092        }
    093
    094        //@ ensures \result != null;
    095        static public Map getMap(TypeDecl td) {
    096            Map m = (Map)datagroups.get(td);
    097            if (m == null) m = initMap(td);
    098            return m;
    099        }
    100
    101        //@ requires map != null;
    102        static public void addToMap(Map map, Map m) {
    103            Iterator i = m.entrySet().iterator();
    104            while (i.hasNext()) {
    105                Map.Entry e = (Map.Entry)i.next();
    106                List list = (List) map.get( e.getKey() );
    107                if (list == null) {
    108                    list = new LinkedList();
    109                    map.put( e.getKey(), list);
    110                }
    111                list.addAll( (List) e.getValue() );
    112            //System.out.println("ATM: " + ((FieldDecl)e.getKey()).id);
    113            //Iterator ii = list.iterator();
    114            //while (ii.hasNext()) System.out.println(">>> " + ii.next());
    115            }
    116        }
    117
    118    }