001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.config;
024:
025: import java.util.ArrayList;
026: import java.util.Collections;
027: import java.util.Comparator;
028: import java.util.HashMap;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.List;
032: import java.util.Map;
033: import java.util.Set;
034:
035: import biz.hammurapi.eval.CircularReferenceException;
036:
037: /**
038: * Manages dependencies between objects.
039: * @author Pavel Vlasov
040: * @revision $Revision$
041: */
042: public class DependencyManager {
043: private Map dependencyMap = new HashMap();
044:
045: /**
046: * Adds dependency. Master can be null for independent objects.
047: * @param slave
048: * @param master
049: */
050: public void addDependency(Object slave, Object master) {
051: Set masters = (Set) dependencyMap.get(slave);
052: if (masters == null) {
053: masters = new HashSet();
054: dependencyMap.put(slave, masters);
055: }
056: if (master != null) {
057: masters.add(master);
058: }
059: }
060:
061: /**
062: * Finds out whether slave depends on master directly or indirectly
063: * @param slave
064: * @param master
065: * @return
066: */
067: public boolean isDependent(Object slave, Object master) {
068: return isDependent(slave, master, slave);
069: }
070:
071: private boolean isDependent(Object slave, Object master,
072: Object originalSlave) {
073: if (master == originalSlave) {
074: throw new CircularReferenceException(
075: "Circular reference : " + originalSlave);
076: }
077:
078: Set masters = (Set) dependencyMap.get(slave);
079: if (masters != null && masters.contains(master)) {
080: return true;
081: }
082:
083: Iterator it = masters.iterator();
084: while (it.hasNext()) {
085: if (isDependent(it.next(), master, originalSlave)) {
086: return true;
087: }
088: }
089:
090: return false;
091: }
092:
093: /**
094: * @return List of items ordered by dependency - independent items first.
095: */
096: public List getOrdered() {
097: ArrayList ret = new ArrayList(dependencyMap.keySet());
098: Collections.sort(ret, new Comparator() {
099:
100: public int compare(Object o1, Object o2) {
101: if (o1 == o2) {
102: return 0;
103: }
104:
105: if (isDependent(o1, o2)) {
106: return 1;
107: }
108:
109: if (isDependent(o2, o1)) {
110: return -1;
111: }
112:
113: return o1.hashCode() - o2.hashCode();
114: }
115:
116: });
117: return ret;
118: }
119:
120: }
|