/* This file is part of Green. * * Copyright (C) 2005 The Research Foundation of State University of New York * All Rights Under Copyright Reserved, The Research Foundation of S.U.N.Y. * * Green is free software, licensed under the terms of the Eclipse * Public License, version 1.0. The license is available at * http://www.eclipse.org/legal/epl-v10.html */ package edu.buffalo.cse.green.relationships; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.IType; import edu.buffalo.cse.green.editor.model.RelationshipModel; /** * Provides a convenient way to store information about which relationships are * displayed in the editor, which ones should be added/removed, and cardinality * * @author bcmartin */ public class RelationshipCache { private Map<IType, Map<IType, Map<String, RelationshipModel>>> _models; private Set<RelationshipModel> _changes; public RelationshipCache() { _models = new HashMap<IType, Map<IType, Map<String, RelationshipModel>>>(); _changes = new HashSet<RelationshipModel>(); } /** * Removes a model from the cache. * * @param rModel - The model. */ public void removeRelationshipModel(RelationshipModel rModel) { _models.get(rModel.getSourceType()).get(rModel.getTargetType()).remove(rModel.getPartClass().getName()); } /** * Gets the relationship model representing the given relationship * * @param source - The source <code>IType</code> of the relationship * @param target - The target <code>IType</code> of the relationship * @param name - The name of the part class of the kind of relationship * @return The unique <code>RelationshipModel</code> representing the given * kind of relationship between the given <code>IType</code>s, or null if * it doesn't exist */ public RelationshipModel getRelationshipModel(IType source, IType target, String name) { Map<IType, Map<String, RelationshipModel>> targetMap = _models.get(source); if (targetMap == null) { return null; } // find the class map Map<String, RelationshipModel> classMap = targetMap.get(target); if (classMap == null) { return null; } // find the model return classMap.get(name); } /** * Gets the relationship model representing the given relationship or * creates the model if it doesn't exist * * @param source - The source <code>IType</code> of the relationship * @param target - The target <code>IType</code> of the relationship * @param klass - The part class of the kind of relationship * @return The unique <code>RelationshipModel</code> representing the given * kind of relationship between the given <code>IType</code>s */ private RelationshipModel getRelationshipModel(IType source, IType target, Class klass) { // find the target map (create it if it doesn't exist) Map<IType, Map<String, RelationshipModel>> targetMap = _models.get(source); if (targetMap == null) { targetMap = new HashMap<IType, Map<String, RelationshipModel>>(); _models.put(source, targetMap); } // find the class map (create it if it doesn't exist) Map<String, RelationshipModel> classMap = targetMap.get(target); if (classMap == null) { classMap = new HashMap<String, RelationshipModel>(); targetMap.put(target, classMap); } // find the model (create it if it doesn't exist) RelationshipModel rModel = classMap.get(klass.getName()); if (rModel == null) { rModel = new RelationshipModel(source, target, klass); classMap.put(klass.getName(), rModel); } return rModel; } /** * Adds a relationship to the cache of relationships. * * @param source - The source type of the relationship * @param target - The target type of the relationship * @param klass - The class representing the controller part * @param relationship - The identifying features of the relationship */ public void add(IType source, IType target, Class klass, Relationship relationship) { RelationshipModel rModel = getRelationshipModel(source, target, klass); // get the relationship, if it already exists in the model Relationship eRelationship = rModel.contains(relationship); /* check whether or not the relationship already exists in the model; * if it does, mark it as retained (so that it doesn't get removed from * the cache); if it doesn't, add it to the list of changed * relationships and mark it as retained */ if (eRelationship == null) { // new relationship rModel.addRelationship(relationship); relationship.setRetained(true); _changes.add(rModel); } else { // existing relationship eRelationship.setRetained(true); } } /** * Looks through the cache for relationships that have not been marked as * retained; those relationships were not found on this pass through the * relationship recognizers and should be removed from the editor; all * models that have relationships removed are added to the list of changes * * @return The list of models that have been altered */ public Set<RelationshipModel> processChanges() { for (Map<IType, Map<String, RelationshipModel>> map1 : _models.values()) { for (Map<String, RelationshipModel> map2: map1.values()) { for (RelationshipModel rModel : map2.values()) { for (Iterator iter = rModel.getRelationships().iterator(); iter.hasNext();) { Relationship relationship = (Relationship) iter.next(); if (!relationship.isRetained()) { iter.remove(); _changes.add(rModel); } else { relationship.setRetained(false); } } } } } return _changes; } /** * @param klass - The part <code>Class</code> that represents the kind of * relationship * @return All relationships of the given kind */ public List<RelationshipModel> getRelationships(Class klass) { List<RelationshipModel> relationships = new ArrayList<RelationshipModel>(); for (Map<IType, Map<String, RelationshipModel>> map : _models.values()) { for (Map<String, RelationshipModel> map2 : map.values()) { if (map2.get(klass.getName()) != null) { relationships.add(map2.get(klass.getName())); } } } return relationships; } /** * @param type - The source type to find relationships for * @return All relationships that have the given type as their source */ public Set<RelationshipModel> getRelationships(IType type) { Set<RelationshipModel> models = new HashSet<RelationshipModel>(); Map<IType, Map<String, RelationshipModel>> map = _models.get(type); if (map == null) { return models; } for (Map<String, RelationshipModel> map2 : map.values()) { models.addAll(map2.values()); } return models; } }