Holon.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. package classes;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.UUID;
  7. import classes.holonControlUnit.HolonControlUnit;
  8. import ui.controller.Control;
  9. import ui.model.DecoratedNetwork;
  10. import ui.model.IntermediateCableWithState;
  11. import ui.model.MinimumModel;
  12. import ui.model.Model;
  13. public class Holon {
  14. public String name = new String();
  15. private Holon parent = null;
  16. public ArrayList<Holon> childHolons = new ArrayList<Holon>();
  17. private List<HolonElement> elements = new ArrayList<HolonElement>();
  18. //HolonObject is the lowest representation of a holon.
  19. private final HolonObject holonObject;
  20. public final boolean isPhysical;
  21. public HolonControlUnit holonControlUnit;
  22. private String uniqueID;
  23. public Model model;
  24. private MinimumModel minModel;
  25. /** stores whether the part between this holon and the child is occupied by the superholon */
  26. private boolean canRunIndependentFromParent;
  27. public Holon(String name, Model model) {
  28. this.name = name;
  29. this.parent = parent;
  30. this.holonObject = null;
  31. isPhysical = false;
  32. this.uniqueID = UUID.randomUUID().toString();
  33. this.model = model;
  34. this.holonControlUnit = new HolonControlUnit(this);
  35. this.minModel = new MinimumModel(new ArrayList<AbstractCanvasObject>(), new ArrayList<Edge>());
  36. this.canRunIndependentFromParent = true;
  37. }
  38. public Holon(HolonObject object, Model model) {
  39. holonObject = object;
  40. object.holon = this;
  41. this.parent = parent;
  42. name = object.getName();
  43. elements.addAll(object.getElements());
  44. for(HolonElement ele : elements) {
  45. ele.holon = this;
  46. }
  47. isPhysical = true;
  48. this.uniqueID = UUID.randomUUID().toString();
  49. this.model = model;
  50. this.holonControlUnit = new HolonControlUnit(this);
  51. ArrayList<AbstractCanvasObject> list = new ArrayList<AbstractCanvasObject>();
  52. list.add(object);
  53. this.minModel = new MinimumModel(list, new ArrayList<Edge>());
  54. this.canRunIndependentFromParent = true;
  55. }
  56. public void addElement(HolonElement element) {
  57. element.holon = this;
  58. elements.add(element);
  59. }
  60. public void removeElement(HolonElement element) {
  61. element.holon = null;
  62. elements.remove(element);
  63. }
  64. public int elementsCount() {
  65. return elements.size();
  66. }
  67. public void addChild(Holon child) {
  68. if(!this.childHolons.contains(child)) {
  69. child.parent = this;
  70. this.childHolons.add(child);
  71. }
  72. this.holonControlUnit.addSubHolon(child);
  73. }
  74. public void addChildHolon(Holon child, int index) {
  75. if(!this.childHolons.contains(child)) {
  76. child.parent = this;
  77. childHolons.add(index, child);
  78. }
  79. this.holonControlUnit.addSubHolon(child);
  80. }
  81. public void removeChildHolon(Holon child) {
  82. child.parent = null;
  83. childHolons.remove(child);
  84. this.holonControlUnit.getHierarchyController().removeSubHolon(child.getUniqueID());
  85. revalidateMinModel();
  86. }
  87. public void removeFromParent() {
  88. if(parent != null) {
  89. parent.removeChildHolon(this);
  90. }
  91. parent = model.getStateHolon();
  92. }
  93. public int getChildCount() {
  94. return childHolons.size();
  95. }
  96. public Holon getParent() {
  97. return parent;
  98. }
  99. public void setParent(Holon parent) {
  100. this.parent = parent;
  101. this.holonControlUnit.getHierarchyController().setSuperHolon(parent.getUniqueID());
  102. }
  103. public HolonObject getHolonObject() {
  104. return holonObject;
  105. }
  106. public List<Holon> getChildView(){
  107. return Collections.unmodifiableList(childHolons);
  108. }
  109. public List<HolonElement> getElementView(){
  110. return Collections.unmodifiableList(elements);
  111. }
  112. @Override
  113. public String toString() {
  114. return name;
  115. }
  116. public void reassignAllChildren(Holon other) {
  117. for(Holon child: this.childHolons) {
  118. other.merge(child);
  119. }
  120. childHolons.clear();
  121. }
  122. public void removeAllRefrences() {
  123. parent = null;
  124. this.childHolons.clear();
  125. this.elements.clear();
  126. }
  127. public int getLayer() {
  128. return parent != null ? parent.getLayer() + 1 : 0;
  129. }
  130. public Holon cloneWithoutParent() {
  131. Holon cloned = new Holon(this.name, this.model);
  132. model.getHolonsByID().put(cloned.getUniqueID(), cloned);
  133. cloned.childHolons = this.childHolons;
  134. cloned.elements = this.elements;
  135. return cloned;
  136. }
  137. public boolean checkHolonArePhysicalConnected(Holon other, Control control) {
  138. HashMap<HolonObject, DecoratedNetwork> table = control.getSimManager().getActualDecorState().getHolonObjectNetworkTable();
  139. HolonObject a = tryGetAPhysicalHolon();
  140. HolonObject b = other.tryGetAPhysicalHolon();
  141. boolean aHolonIsPureAbstract = a == null || b == null;
  142. return aHolonIsPureAbstract || table.get(a) == table.get(b);
  143. }
  144. private HolonObject tryGetAPhysicalHolon() {
  145. if(holonObject != null) {
  146. return holonObject;
  147. }
  148. for(Holon holon : childHolons) {
  149. HolonObject object = holon.tryGetAPhysicalHolon();
  150. if(object != null) {
  151. return object;
  152. }
  153. }
  154. return null;
  155. }
  156. public void checkRepairHolarchy(HashMap<HolonObject, DecoratedNetwork> table, Holon stateHolon) {
  157. if(childHolons.isEmpty()) {
  158. return;
  159. }
  160. //To establish the invariant that all child holons are repaired
  161. for(Holon other : childHolons) {
  162. other.checkRepairHolarchy(table, stateHolon);
  163. }
  164. //Repair this Holon
  165. HolonObject first = tryGetAPhysicalHolon();
  166. if(first == null) {
  167. return;
  168. }
  169. List<Holon> removeList = new ArrayList<Holon>();
  170. for(Holon other : childHolons) {
  171. HolonObject otherHolonObject = other.tryGetAPhysicalHolon();
  172. boolean isPureAbstract = otherHolonObject == null;
  173. if(isPureAbstract) {
  174. continue;
  175. }
  176. boolean isPhysicalConnected = model.checkHolonObjectsAreConnected(this, other);
  177. if(!isPhysicalConnected) {
  178. removeList.add(other);
  179. }
  180. }
  181. //Remove holons
  182. for(Holon holon : removeList) {
  183. holon.split(stateHolon);
  184. }
  185. }
  186. public void addNewVirtualNeighbor(String virtualNeighbor) {
  187. if(!this.uniqueID.equals(virtualNeighbor)) {
  188. this.holonControlUnit.addNewVirtualNeighbor(virtualNeighbor);
  189. }
  190. }
  191. public String getUniqueID() {
  192. return uniqueID;
  193. }
  194. public ArrayList<HolonObject> getAllHolonObjects() {
  195. ArrayList<HolonObject> list = new ArrayList<HolonObject>();
  196. for(Holon h : this.childHolons) {
  197. list.addAll(h.getAllHolonObjects());
  198. }
  199. if(this.holonObject != null) {
  200. list.add(this.holonObject);
  201. }
  202. return list;
  203. }
  204. public MinimumModel getMinimumModel() {
  205. return this.minModel;
  206. }
  207. public void merge(Holon child) {
  208. if(!this.model.getHolonsByID().containsKey(child.getUniqueID())) {
  209. System.err.println("could not find: "+child.getHolonObject());
  210. return;
  211. }
  212. if(this.childHolons.contains(child)) {
  213. return;
  214. }
  215. if(this.getLayer() == 0) {
  216. this.addChild(child);
  217. return;
  218. }
  219. //check if path between this holon and child holon is already occupied
  220. ArrayList<HolonObject> holarchy = getAllHolonObjects();
  221. holarchy.addAll(child.getAllHolonObjects());
  222. HashMap<Float, ArrayList<Edge>> paths = this.model.getShortestPathToHolarchy(this.minModel, child.getMinimumModel(), holarchy);
  223. HashMap<Float, ArrayList<Edge>> free_paths = new HashMap<Float, ArrayList<Edge>>();
  224. HashMap<Float, ArrayList<Edge>> occ_paths = new HashMap<Float, ArrayList<Edge>>();
  225. HashMap<ArrayList<Edge>, Holon> occ_by = new HashMap<ArrayList<Edge>, Holon>();
  226. for(Float f : paths.keySet()) {
  227. ArrayList<Edge> path = paths.get(f);
  228. Holon holder = isPathOccupied(path);
  229. if(holder == null || holder.getLayer() == 0 || holder.equals(this.parent)) {
  230. free_paths.put(f, path);
  231. } else {
  232. occ_paths.put(f, path);
  233. occ_by.put(path, holder);
  234. }
  235. }
  236. if(free_paths.size() > 0) {
  237. //there is a free path, take it and add child directly
  238. this.addChild(child);
  239. this.addChildToMinModel(child, free_paths.get(getShortestPath(free_paths)));
  240. if(this.getLayer() > 1) {
  241. this.parent.recalculateMinModel();
  242. }
  243. return;
  244. }
  245. if(occ_paths.size() < 1) {
  246. System.err.println("something went wrong when looking for shortest path while merging "+this.uniqueID+" and "+child.getUniqueID());
  247. }
  248. ArrayList<ArrayList<Edge>> shortestPaths = sortPaths(occ_paths);
  249. for(int i=0; i< shortestPaths.size(); i++) {
  250. //check if holon should merge with holder of this path
  251. ArrayList<Edge> path = shortestPaths.get(i);
  252. Holon holder = occ_by.get(path);
  253. //if true try to merge with holon which is using the path
  254. if(holder != null && holder.getLayer() > 0) {
  255. this.split(holder);
  256. this.addChild(child);
  257. this.addChildToMinModel(child, path);
  258. if(this.parent != null && this.getLayer() > 1) {
  259. this.parent.recalculateMinModel();
  260. }
  261. this.canRunIndependentFromParent = false;
  262. }
  263. break;
  264. }
  265. }
  266. /**
  267. * checks whether a path is occupied
  268. * if true returns the holon in which the path is located
  269. * @param path
  270. * @return
  271. */
  272. private Holon isPathOccupied(ArrayList<Edge> path) {
  273. Holon h = this.parent;
  274. Holon r = this;
  275. Holon holder = null;
  276. while(h != null) {
  277. holder = h.containsPath(path, r);
  278. if(holder != null) {
  279. //found a holon which contains the path
  280. return holder;
  281. }
  282. r = h;
  283. h = h.parent;
  284. }
  285. return null;
  286. }
  287. private ArrayList<ArrayList<Edge>> sortPaths(HashMap<Float, ArrayList<Edge>> paths) {
  288. ArrayList<ArrayList<Edge>> shortestPaths = new ArrayList<ArrayList<Edge>>();
  289. while(paths.size() > 0) {
  290. shortestPaths.add(paths.remove(getShortestPath(paths)));
  291. }
  292. return shortestPaths;
  293. }
  294. private Float getShortestPath(HashMap<Float, ArrayList<Edge>> paths){
  295. float min = Float.MAX_VALUE;
  296. for(Float f : paths.keySet()) {
  297. if(f < min) {
  298. min = f;
  299. }
  300. }
  301. return min;
  302. }
  303. /**
  304. * removes this holon from current superholon and merge with new superholon
  305. */
  306. public void split(Holon newParent) {
  307. if(newParent == null) {
  308. System.err.println("can not split without new super holon");
  309. return;
  310. }
  311. //ensure that this holarchy can run independent(path is not occupied by superholon) from the superholon
  312. if(!this.canRunIndependentFromParent) {
  313. return;
  314. }
  315. if(this.parent != null) {
  316. this.parent.removeChildHolon(this);
  317. }
  318. newParent.merge(this);
  319. }
  320. /**
  321. * recalculates the min model after a holon was added to a subholon
  322. * does NOT recalculate the shortest paths between its subholons
  323. */
  324. public void recalculateMinModel() {
  325. ArrayList<AbstractCanvasObject> objects = new ArrayList<AbstractCanvasObject>();
  326. ArrayList<Edge> edges = new ArrayList<Edge>();
  327. for(Holon child : this.childHolons) {
  328. MinimumModel cmm = child.getMinimumModel();
  329. objects.addAll(cmm.getHolonObjectList());
  330. objects.addAll(cmm.getNodeList());
  331. objects.addAll(cmm.getSwitchList());
  332. for(IntermediateCableWithState icws : cmm.getEdgeList()) {
  333. edges.add(icws.getModel());
  334. }
  335. }
  336. //go through the edge list and add all edges connecting the subholons
  337. for(IntermediateCableWithState icws : this.minModel.getEdgeList()) {
  338. if(!edges.contains(icws.getModel())) {
  339. edges.add(icws.getModel());
  340. }
  341. }
  342. this.minModel = new MinimumModel(objects, edges);
  343. //notify superholon to recalculate its minModel
  344. if(this.parent != null && this.getLayer() > 0) {
  345. this.parent.recalculateMinModel();
  346. }
  347. }
  348. /**
  349. * adds a child and its min model (incl. all its subholons) to this min model
  350. * @param child
  351. */
  352. private void addChildToMinModel(Holon child, ArrayList<Edge> path) {
  353. if(this.minModel.getHolonObjectList().contains(child.getHolonObject()) || getLayer() == 0)
  354. return;
  355. ArrayList<Edge> edgeList = new ArrayList<Edge>();
  356. //add all holon objects that are part of this holarchy
  357. ArrayList<HolonObject> holarchy = getAllHolonObjects();
  358. holarchy.addAll(child.getAllHolonObjects());
  359. edgeList.addAll(path);
  360. for(IntermediateCableWithState icws : this.minModel.getEdgeList()) {
  361. edgeList.add(icws.getModel());
  362. }
  363. for(IntermediateCableWithState icws : child.minModel.getEdgeList()) {
  364. edgeList.add(icws.getModel());
  365. }
  366. //aggregate all objects
  367. ArrayList<AbstractCanvasObject> objects = new ArrayList<AbstractCanvasObject>();
  368. for(Edge e : edgeList) {
  369. AbstractCanvasObject a = e.getA();
  370. AbstractCanvasObject b = e.getB();
  371. if(!objects.contains(a)) {
  372. objects.add(a);
  373. }
  374. if(!objects.contains(b)) {
  375. objects.add(b);
  376. }
  377. }
  378. this.minModel = new MinimumModel(objects, edgeList);
  379. }
  380. /**
  381. * revalidate this min model after a subholon was removed
  382. */
  383. public void revalidateMinModel() {
  384. if(getLayer() == 0)
  385. return;
  386. this.canRunIndependentFromParent = true;
  387. ArrayList<AbstractCanvasObject> list = new ArrayList<AbstractCanvasObject>();
  388. list.add(this.holonObject);
  389. this.minModel = new MinimumModel(list, new ArrayList<Edge>());
  390. for(int i=0; i< this.childHolons.size(); i++) {
  391. Holon child = this.childHolons.remove(0);
  392. this.merge(child);
  393. }
  394. if(this.parent != null) {
  395. this.parent.revalidateMinModel();
  396. }
  397. }
  398. /**
  399. * returns the holon which uses the specified path if it is included in min model, otherwise null
  400. */
  401. public Holon containsPath(ArrayList<Edge> path, Holon requester) {
  402. if(this.minModel.containsPath(path) || this.getLayer() == 0) {
  403. for(Holon child : this.childHolons) {
  404. if(child.equals(requester))
  405. continue;
  406. Holon h = child.containsPath(path, this);
  407. if(h != null) {
  408. return h;
  409. }
  410. }
  411. return this;
  412. }
  413. return null;
  414. }
  415. }