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 }