001 /*
002 @license.text@
003 */
004 package biz.hammurapi.config;
005
006 import java.util.ArrayList;
007 import java.util.Collections;
008 import java.util.Comparator;
009 import java.util.HashMap;
010 import java.util.HashSet;
011 import java.util.Iterator;
012 import java.util.List;
013 import java.util.Map;
014 import java.util.Set;
015
016 import biz.hammurapi.eval.CircularReferenceException;
017
018 /**
019 * Manages dependencies between objects.
020 * @author Pavel Vlasov
021 * @revision $Revision$
022 */
023 public class DependencyManager {
024 private Map dependencyMap=new HashMap();
025
026 /**
027 * Adds dependency. Master can be null for independent objects.
028 * @param slave
029 * @param master
030 */
031 public void addDependency(Object slave, Object master) {
032 Set masters=(Set) dependencyMap.get(slave);
033 if (masters==null) {
034 masters=new HashSet();
035 dependencyMap.put(slave, masters);
036 }
037 if (master!=null) {
038 masters.add(master);
039 }
040 }
041
042 /**
043 * Finds out whether slave depends on master directly or indirectly
044 * @param slave
045 * @param master
046 * @return
047 */
048 public boolean isDependent(Object slave, Object master) {
049 return isDependent(slave, master, slave);
050 }
051
052 private boolean isDependent(Object slave, Object master, Object originalSlave) {
053 if (master==originalSlave) {
054 throw new CircularReferenceException("Circular reference : "+originalSlave);
055 }
056
057 Set masters=(Set) dependencyMap.get(slave);
058 if (masters!=null && masters.contains(master)) {
059 return true;
060 }
061
062 Iterator it=masters.iterator();
063 while (it.hasNext()) {
064 if (isDependent(it.next(), master, originalSlave)) {
065 return true;
066 }
067 }
068
069 return false;
070 }
071
072 /**
073 * @return List of items ordered by dependency - independent items first.
074 */
075 public List getOrdered() {
076 ArrayList ret=new ArrayList(dependencyMap.keySet());
077 Collections.sort(
078 ret,
079 new Comparator() {
080
081 public int compare(Object o1, Object o2) {
082 if (o1==o2) {
083 return 0;
084 }
085
086 if (isDependent(o1, o2)) {
087 return 1;
088 }
089
090 if (isDependent(o2,o1)) {
091 return -1;
092 }
093
094 return o1.hashCode()-o2.hashCode();
095 }
096
097 });
098 return ret;
099 }
100
101 }