PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/code/KinTermMatrix.java

http://silkin.googlecode.com/
Java | 911 lines | 569 code | 48 blank | 294 comment | 129 complexity | 729f21add28e7efd9b6fca85a4b1f233 MD5 | raw file
  1. import java.util.*;
  2. import java.io.*;
  3. import javax.swing.JOptionPane;
  4. /**
  5. A KinTermMatrix has one row and one column for each person in a culture; each cell contains null or a
  6. {@link Node} containing the kinTerms <code>Row</code> (Ego) could use to refer to <code>Column</code> (Alter).
  7. This sparse matrix is currently implemented as a nested TreeMap. That may change in the future.
  8. <p>
  9. A KinTermMatrix grows by adding a new person (indexed by their serialNmbr) to the rows (list of Egos)
  10. and columns (list of Alters) of the matrix. Each Node holds lists of terms that Ego calls Alter,
  11. plus data about the most recent diagram that has been drawn.
  12. </p> <p>
  13. The matrix is normally built one person at a time as a Field Worker gathers data about people in the
  14. local culture. It is imperative that the retrieval of kinTerms by (row, col) address be fast and
  15. scalable.
  16. </p> <p>
  17. A special problem arises when the User alters a chart to correct a kinTerm. A "retraction" dyad must be
  18. created whenever that happens. The retraction will contain all the info in the original (erroneous) node
  19. so it can be removed from the indexRef or indexAddr.
  20. </p> <p>
  21. A KinTermMatrix has 2 associated indexes of kinTerms, for Reference terms and terms of Address.
  22. For every kinTerm that has been recorded in a matrix, its index entry has a list of all the Egos
  23. who have a kin of that type, and for each one has a list of Alters whom Ego calls by that kinTerm.
  24. @author Gary Morris, Northern Virginia Community College garymorris2245@verizon.net
  25. */
  26. public class KinTermMatrix implements Serializable {
  27. TreeMap matrix;
  28. TreeMap indexRef, indexAddr;
  29. /** This constructor creates an empty matrix. */
  30. public KinTermMatrix() {
  31. matrix = new TreeMap();
  32. indexRef = new TreeMap();
  33. indexAddr = new TreeMap();
  34. } // end of constructor
  35. /** This method removes the row and column associated
  36. * with an Individual. This method is used to clean up
  37. * any possible by-products of the accidental creation
  38. * of this person being removed from the system.
  39. *
  40. * @param ind the person being deleted.
  41. */
  42. public void deletePerson(Individual ind) {
  43. Integer ndx = new Integer(ind.serialNmbr);
  44. TreeMap herRow = (TreeMap)matrix.get(ndx);
  45. for (Object o : herRow.values()) {
  46. Node nod = (Node)o;
  47. Context.current.deleteDyads(nod, ndx);
  48. }
  49. matrix.remove(ndx);
  50. Iterator rowIter = matrix.entrySet().iterator();
  51. while (rowIter.hasNext()) {
  52. Map.Entry entry = (Map.Entry)rowIter.next();
  53. Integer altSerial = (Integer)entry.getKey();
  54. TreeMap row = (TreeMap)entry.getValue();
  55. Node nod = (Node)row.get(ndx);
  56. Context.current.deleteDyads(nod, altSerial);
  57. row.remove(ndx);
  58. }
  59. }
  60. public void deleteKinTerm(int ego, int alter, String kinTerm, boolean adr) {
  61. TreeMap egoRow = (TreeMap)matrix.get(ego);
  62. Node nod = (Node)egoRow.get(alter);
  63. ArrayList<Object> lst = (adr ? nod.kinTermsAddr : nod.kinTermsAddr);
  64. lst.remove(kinTerm);
  65. }
  66. public void correctKinTerm(int ego, int alter, String oldTerm, String newTerm, boolean adr) {
  67. TreeMap egoRow = (TreeMap)matrix.get(ego);
  68. Node nod = (Node)egoRow.get(alter);
  69. ArrayList<Object> lst = (adr ? nod.kinTermsAddr : nod.kinTermsRef);
  70. lst.remove(oldTerm);
  71. if (!lst.contains(newTerm)) {
  72. lst.add(newTerm);
  73. }
  74. }
  75. public int numberOfKinTerms() {
  76. int s = 0, ego, alter;
  77. Iterator egoIter = matrix.entrySet().iterator(), altIter, ktIter;
  78. Map.Entry egoEntry, altEntry;
  79. Node cell;
  80. while (egoIter.hasNext()) {
  81. egoEntry = (Map.Entry) egoIter.next();
  82. ego = ((Integer) egoEntry.getKey()).intValue();
  83. altIter = ((TreeMap) egoEntry.getValue()).entrySet().iterator();
  84. while (altIter.hasNext()) {
  85. altEntry = (Map.Entry) altIter.next();
  86. alter = ((Integer) altEntry.getKey()).intValue();
  87. cell = (Node) altEntry.getValue();
  88. s += cell.nmbrOfKinTerms();
  89. } // end of loop thru cells in the row
  90. } // end of loop thru the rows
  91. return s;
  92. }
  93. public int numberOfCells() {
  94. return DomainTheory.countLeaves(matrix);
  95. }
  96. /** For every Node in the matrix, make terms of address that mimic the
  97. * terms of reference.
  98. */
  99. public void addAdrCloneTerms() {
  100. Iterator rowIter = matrix.values().iterator();
  101. while (rowIter.hasNext()) {
  102. TreeMap rowMap = (TreeMap)rowIter.next();
  103. Iterator nodeIter = rowMap.values().iterator();
  104. while (nodeIter.hasNext()) {
  105. Node nod = (Node)nodeIter.next();
  106. nod.kinTermsAddr = union(nod.kinTermsRef, nod.kinTermsAddr);
  107. nod.extKinTermsAddr = union(nod.extKinTermsRef, nod.extKinTermsAddr);
  108. }
  109. }
  110. }
  111. /** Used when deleting a domain theory for Terms of Address.
  112. * Visit every node of every row and nullify the Address terms.
  113. * */
  114. public void cleanAdrTerms() {
  115. Iterator rowIter = matrix.values().iterator(), altIter;
  116. while (rowIter.hasNext()) {
  117. TreeMap egoRow = (TreeMap)rowIter.next();
  118. altIter = egoRow.values().iterator();
  119. while (altIter.hasNext()) {
  120. Node nod = (Node)altIter.next();
  121. nod.kinTermsAddr.clear();
  122. nod.extKinTermsAddr.clear();
  123. }
  124. }
  125. }
  126. public ArrayList union(ArrayList lst1, ArrayList lst2) {
  127. ArrayList merge = new ArrayList(lst1);
  128. for (Object o : lst2) {
  129. if (! merge.contains(o)) {
  130. merge.add(o);
  131. }
  132. }
  133. return merge;
  134. }
  135. /** This method builds a string that represents a KinTermMatrix in a SILKin data (_.silk) file. */
  136. public String toSILKString() {
  137. String image = "";
  138. int ego, alter;
  139. Iterator egoIter = matrix.entrySet().iterator(), altIter, ktIter;
  140. Map.Entry egoEntry, altEntry;
  141. Node cell;
  142. while (egoIter.hasNext()) {
  143. egoEntry = (Map.Entry) egoIter.next();
  144. ego = ((Integer) egoEntry.getKey()).intValue();
  145. image += "<row ego=\"" + ego + "\">";
  146. altIter = ((TreeMap) egoEntry.getValue()).entrySet().iterator();
  147. while (altIter.hasNext()) {
  148. altEntry = (Map.Entry) altIter.next();
  149. alter = ((Integer) altEntry.getKey()).intValue();
  150. cell = (Node) altEntry.getValue();
  151. image += "\n\t<cell alter=\"" + alter + "\">" + cell.toSILKString() + "</cell>";
  152. } // end of loop thru cells in the row
  153. image += "\n</row>";
  154. } // end of loop thru the rows
  155. return image;
  156. } // end of method toSILKString
  157. /** Return a printable String displaying the complete contents of this Matrix and Indices */
  158. public String toString() {
  159. String st = "";
  160. if (indexRef.size() > 0) {
  161. st += printIndexRef() + "\n\n";
  162. }
  163. if ((indexAddr != null) && (indexAddr.size() > 0)) {
  164. st += printIndexAddr() + "\n\n";
  165. }
  166. st += printMatrix();
  167. return st;
  168. } // end of over-riding method
  169. /** Return a printable String displaying the selected contents of this Matrix.
  170. @param type String containing one or more of: 'address' = Index of Terms of Address,
  171. 'reference' = Index of Terms of Reference, and 'matrix' = KinTerm Matrix.
  172. @return printable String.
  173. */
  174. public String toString(String type) {
  175. String image = "";
  176. if (type.indexOf("address") > -1) {
  177. image += printIndexAddr() + "\n\n";
  178. }
  179. if (type.indexOf("reference") > -1) {
  180. image += printIndexRef() + "\n\n";
  181. }
  182. if (type.indexOf("matrix") > -1) {
  183. image += printMatrix() + "\n\n";
  184. }
  185. if (image.length() < 10) {
  186. image += "Type specifier of '" + type + "' not recognized";
  187. }
  188. return image;
  189. }
  190. /** Return a printable String displaying the Index of Kinship Terms of Reference. */
  191. public String printIndexRef() {
  192. // This method is temporarily bypassed. If a use for this index appears
  193. // it can be reinstated
  194. return "";
  195. // String image = "\nIndex of Kinship Terms of Reference in " + DomainTheory.current.languageName, term;
  196. // image += ".\nKin Term\n Ego (All_Known_Alters)\n";
  197. // Iterator termIter = indexRef.entrySet().iterator(), egoIter;
  198. // Map.Entry termEntry, egoEntry;
  199. // ArrayList<Object> altLst;
  200. // Integer ego, alter;
  201. // while (termIter.hasNext()) {
  202. // termEntry = (Map.Entry) termIter.next();
  203. // image += "\n" + (String) termEntry.getKey() + "\n";
  204. // egoIter = ((TreeMap) termEntry.getValue()).entrySet().iterator();
  205. // while (egoIter.hasNext()) {
  206. // egoEntry = (Map.Entry) egoIter.next();
  207. // image += " " + egoEntry.getKey() + " (";
  208. // altLst = (ArrayList<Object>) egoEntry.getValue();
  209. // for (int i = 0; i < altLst.numberOfKinTerms(); i++) {
  210. // image += altLst.get(i) + " ";
  211. // }
  212. // image += ")\n";
  213. // }
  214. // }
  215. // return image;
  216. } // end of method for printing indexRef of kinTerms
  217. /** Return a printable String displaying the Index of Kinship Terms of Address. */
  218. public String printIndexAddr() {
  219. if ((indexAddr == null) || (indexAddr.isEmpty())) {
  220. return " ";
  221. }
  222. String image = "\nIndex of Kinship Terms of Address in " + DomainTheory.current.languageName, term;
  223. image += ".\nKin Term\n Ego (All_Known_Alters)\n";
  224. Iterator termIter = indexAddr.entrySet().iterator(), egoIter;
  225. Map.Entry termEntry, egoEntry;
  226. ArrayList<Object> altLst;
  227. Integer ego, alter;
  228. while (termIter.hasNext()) {
  229. termEntry = (Map.Entry) termIter.next();
  230. image += "\n" + (String) termEntry.getKey() + "\n";
  231. egoIter = ((TreeMap) termEntry.getValue()).entrySet().iterator();
  232. while (egoIter.hasNext()) {
  233. egoEntry = (Map.Entry) egoIter.next();
  234. image += " " + egoEntry.getKey() + " (";
  235. altLst = (ArrayList<Object>) egoEntry.getValue();
  236. for (int i = 0; i < altLst.size(); i++) {
  237. image += altLst.get(i) + " ";
  238. }
  239. image += ")\n";
  240. }
  241. }
  242. return image;
  243. } // end of method for printing indexAddr of kinTerms
  244. /** Return a printable String displaying the contents of this Matrix */
  245. public String printMatrix() {
  246. String image = "\nMatrix of Relationships in " + DomainTheory.current.languageName, term;
  247. image += ".\nEgo\n Alter (Primaries) [Extended] {Exceptions} * = Terms of Address\n";
  248. Iterator egoIter = matrix.entrySet().iterator(), altIter, ktIter;
  249. Map.Entry egoEntry, altEntry;
  250. Node cell;
  251. while (egoIter.hasNext()) {
  252. egoEntry = (Map.Entry) egoIter.next();
  253. image += "\n" + egoEntry.getKey().toString() + "\n";
  254. altIter = ((TreeMap) egoEntry.getValue()).entrySet().iterator();
  255. while (altIter.hasNext()) {
  256. altEntry = (Map.Entry) altIter.next();
  257. image += " " + altEntry.getKey().toString();
  258. cell = (Node) altEntry.getValue();
  259. image += cell.toString() + "\n";
  260. }
  261. }
  262. return image;
  263. } // end of method for printing matrix of relationship terms
  264. /** Write a *.ktm file storing all the contents of this Matrix.
  265. @param pathName String with the pathname for this output file.
  266. @param langName String = the name of the language in the enclosing context.
  267. */
  268. public void writeKtmFile(String pathName, String langName) throws JavaSystemException {
  269. Iterator egoIter = matrix.entrySet().iterator(), altIter, ktIter;
  270. Map.Entry egoEntry, altEntry;
  271. Node cell;
  272. int ego, alter;
  273. try {
  274. PrintWriter file = new PrintWriter(new BufferedWriter(new FileWriter(pathName)));
  275. file.println("<matrix> ");
  276. while (egoIter.hasNext()) {
  277. egoEntry = (Map.Entry) egoIter.next();
  278. ego = ((Integer) egoEntry.getKey()).intValue();
  279. file.println("<row> " + ego);
  280. altIter = ((TreeMap) egoEntry.getValue()).entrySet().iterator();
  281. while (altIter.hasNext()) {
  282. altEntry = (Map.Entry) altIter.next();
  283. alter = ((Integer) altEntry.getKey()).intValue();
  284. cell = (Node) altEntry.getValue();
  285. file.println(alter + " " + cell.writeKinTerms());
  286. }
  287. file.println("</row> ");
  288. }
  289. file.println("</matrix> ");
  290. if (indexRef != null) {
  291. writeIndexToKtmFile(file, "ref");
  292. }
  293. if (indexAddr != null) {
  294. writeIndexToKtmFile(file, "addr");
  295. }
  296. file.flush();
  297. file.close();
  298. } catch (IOException e) {
  299. throw new JavaSystemException(langName + ".ktm File Creation failed:\n" + e);
  300. } // end of catch block
  301. } // end of method writeKtmFile
  302. public void writeIndexToKtmFile(PrintWriter file, String type) {
  303. String tag;
  304. TreeMap index;
  305. if (type.equals("ref")) {
  306. tag = "indexRef";
  307. index = indexRef;
  308. } else {
  309. tag = "indexAddr";
  310. index = indexAddr;
  311. }
  312. file.println("<" + tag + "> ");
  313. Iterator termIter = index.entrySet().iterator(), egoIter;
  314. Map.Entry termEntry, egoEntry;
  315. ArrayList<Object> altLst;
  316. Integer ego, alter;
  317. while (termIter.hasNext()) {
  318. termEntry = (Map.Entry) termIter.next();
  319. file.println("<row> " + (String) termEntry.getKey());
  320. egoIter = ((TreeMap) termEntry.getValue()).entrySet().iterator();
  321. while (egoIter.hasNext()) {
  322. egoEntry = (Map.Entry) egoIter.next();
  323. file.print(egoEntry.getKey() + " (");
  324. altLst = (ArrayList<Object>) egoEntry.getValue();
  325. file.print(altLst.get(0));
  326. for (int i = 1; i < altLst.size(); i++) {
  327. file.print(", " + altLst.get(i));
  328. }
  329. file.println(")");
  330. } // end of while-egoIter.hasNext
  331. file.println("</row> ");
  332. } // end of while-termIter.hasNext
  333. file.println("</" + tag + "> ");
  334. } // end of method writeIndexToKtmFile
  335. private void addToIndex(Integer egoNum, Integer altNum, String kinTerm, boolean addr) {
  336. // This method is temporarily bypassed. If a use for this index appears
  337. // it can be reinstated
  338. return;
  339. // TreeMap index;
  340. // if (!addr) {
  341. // index = indexRef;
  342. // } else {
  343. // if (indexAddr == null) {
  344. // indexAddr = new TreeMap();
  345. // }
  346. // index = indexAddr;
  347. // }
  348. // if (index.get(kinTerm) == null) {
  349. // index.put(kinTerm, new TreeMap());
  350. // }
  351. // TreeMap egoTree = (TreeMap) index.get(kinTerm);
  352. // if (egoTree.get(egoNum) == null) {
  353. // egoTree.put(egoNum, new ArrayList<Object>());
  354. // }
  355. // ((ArrayList<Object>) egoTree.get(egoNum)).add(altNum);
  356. } // end of method addToIndex
  357. /**
  358. Find all the (serial numbers of) people (alters) who are called <code>kinTerm</code> by ego.
  359. @param ego (serial number of) speaker of this kinTerm: the focus person.
  360. @param kinTerm the term to be found
  361. @param addr true = searching Terms of Address, false = searching Terms of Reference
  362. @return array of ints - the serial numbers of all people ego calls by this term
  363. (primary, extended, or exception), or null if there are none.
  364. */
  365. public int[] findKinFor(int ego, String kinTerm, boolean addr) {
  366. TreeMap index;
  367. if (!addr) {
  368. index = indexRef;
  369. } else {
  370. if (indexAddr == null) {
  371. return null;
  372. } else {
  373. index = indexAddr;
  374. }
  375. }
  376. Integer egoInt = new Integer(ego);
  377. TreeMap termMap = (TreeMap) index.get(kinTerm);
  378. if ((termMap == null) || (termMap.get(egoInt) == null)) {
  379. return null;
  380. }
  381. ArrayList<Object> egoKin = (ArrayList<Object>) termMap.get(egoInt);
  382. int[] answer = new int[egoKin.size()];
  383. Iterator egoIter = egoKin.iterator();
  384. int i = 0;
  385. while (egoIter.hasNext()) {
  386. answer[i++] = ((Integer) egoIter.next()).intValue();
  387. }
  388. return answer;
  389. } // end of method findKinFor with int
  390. /**
  391. Find all the (serial numbers of) people (alters) who are called <code>kinTerm</code> by ego.
  392. @param ego speaker of this kinTerm: the focus person.
  393. @param kinTerm the term to be found
  394. @param addr true = searching Terms of Address, false = searching Terms of Reference
  395. @return array of ints - the serial numbers of all people ego calls by this term (primary, extended, or exception).
  396. */
  397. public int[] findKinFor(Individual ego, String kinTerm, boolean addr) {
  398. return findKinFor(ego.serialNmbr, kinTerm, addr);
  399. }
  400. /**
  401. Find all instances of <code>kinTerm</code>, for any ego, in this KinTermMatrix.
  402. @param kinTerm the term to be found
  403. @param addr true = searching Terms of Address, false = searching Terms of Reference
  404. @return TreeMap with keys = ego serial numbers (Integers) and values = ALists of serial numbers (Integers)
  405. of all people that ego calls by this term (primary, extended, or exception).
  406. Return null if there are no entries for <code>kinTerm</code>.
  407. */
  408. public TreeMap exampleMapOf(String kinTerm, boolean addr) {
  409. TreeMap index;
  410. if (!addr) {
  411. index = indexRef;
  412. } else {
  413. if (indexAddr == null) {
  414. return null;
  415. } else {
  416. index = indexAddr;
  417. }
  418. }
  419. return (TreeMap) index.get(kinTerm);
  420. } // end of method exampleMapOf
  421. /**
  422. Find all instances of <code>kinTerm</code>, for any ego, in this KinTermMatrix.
  423. @param kinTerm the term to be found
  424. @param addr true = searching Terms of Address, false = searching Terms of Reference
  425. @return ArrayList<Object> (possibly empty) of {@link KinTermExample} objects.
  426. For each example, ego calls alter by this term (primary, extended, or exception).
  427. */
  428. public ArrayList<Object> exampleListOf(String kinTerm, boolean addr) {
  429. TreeMap index;
  430. if (!addr) {
  431. index = indexRef;
  432. } else {
  433. if (indexAddr == null) {
  434. return new ArrayList<Object>();
  435. } else {
  436. index = indexAddr;
  437. }
  438. }
  439. ArrayList<Object> examples = new ArrayList<Object>();
  440. Map.Entry entry;
  441. Integer ego;
  442. ArrayList<Object> alters;
  443. TreeMap termMap = (TreeMap) index.get(kinTerm);
  444. if (termMap == null) {
  445. return examples;
  446. }
  447. Iterator entryIter = termMap.entrySet().iterator();
  448. Iterator alterIter;
  449. while (entryIter.hasNext()) {
  450. entry = (Map.Entry) entryIter.next();
  451. ego = (Integer) entry.getKey();
  452. alters = (ArrayList<Object>) entry.getValue();
  453. alterIter = alters.iterator();
  454. while (alterIter.hasNext()) {
  455. examples.add(new KinTermExample(ego.intValue(), ((Integer) alterIter.next()).intValue(), kinTerm));
  456. }
  457. } // end of outer loop thru ego's for this kinTerm
  458. return examples;
  459. } // end of method exampleListOf
  460. /**
  461. Enter into this KinTermMatrix the kinship term that <code>ego</code> calls <code>alter</code>.
  462. For example: addKinTerm(DonaldDuckSerial#, ScroogeMcDuckSerial#, "uncle", "primary", false).
  463. @param egoInt (serial number of) speaker of this kinTerm: the focus person.
  464. @param alterInt (serial number of) person ego would call this kinTerm
  465. @param kinTerm the term to be found
  466. @param type 'primary' or 'extended' or 'exception'
  467. @param addr true = searching Terms of Address, false = searching Terms of Reference
  468. */
  469. public void addTerm(int egoInt, int alterInt, String kinTerm, String type, boolean addr)
  470. throws KSInternalErrorException {
  471. if ((!type.equals("primary")) && (!type.equals("extended")) && (!type.equals("exception"))) {
  472. throw new KSInternalErrorException("Invalid 'type' given to method KinTermMatrix.addTerm.");
  473. }
  474. Integer ego = new Integer(egoInt), alter = new Integer(alterInt);
  475. String clas = (addr ? "address" : "reference");
  476. if (matrix.get(ego) == null) {
  477. matrix.put(ego, new TreeMap());
  478. }
  479. if (((TreeMap) matrix.get(ego)).get(alter) == null) {
  480. ((TreeMap) matrix.get(ego)).put(alter, new Node());
  481. }
  482. addToIndex(ego, alter, kinTerm, addr);
  483. ((Node) ((TreeMap) matrix.get(ego)).get(alter)).addTerm(kinTerm, type, clas);
  484. } // end of method replaceTerms with ints
  485. /**
  486. Enter into this KinTermMatrix the kinship term that <code>ego</code> calls <code>alter</code>.
  487. For example: addKinTerm(DonaldDuckSerial#, ScroogeMcDuckSerial#, "uncle", "primary", false).
  488. @param egoInd {@link Individual} who uses this kinTerm: the focus person.
  489. @param alterInd Individual ego would call this kinTerm
  490. @param kinTerm the term used
  491. @param type 'primary' or 'extended' or 'exception'
  492. @param addr true = searching Terms of Address, false = searching Terms of Reference
  493. */
  494. public void addTerm(Individual egoInd, Individual alterInd, String kinTerm, String type, boolean addr)
  495. throws KSInternalErrorException {
  496. addTerm(egoInd.serialNmbr, alterInd.serialNmbr, kinTerm, type, addr);
  497. } // end of method replaceTerms with Individuals
  498. public void addNode(int egoInt, int alterInt, Node node) {
  499. Integer ego = new Integer(egoInt), alter = new Integer(alterInt);
  500. Node oldNode = null;
  501. if (matrix.get(ego) == null) {
  502. matrix.put(ego, new TreeMap());
  503. } else {
  504. oldNode = (Node) ((TreeMap) matrix.get(ego)).get(alter);
  505. }
  506. ((TreeMap) matrix.get(ego)).put(alter, node);
  507. if (oldNode != null) {
  508. try {
  509. ArrayList<String> deletedTerms = oldNode.getKinTerms(false);
  510. deletedTerms.removeAll(node.getKinTerms(false));
  511. DomainTheory dt = Context.current.domTheoryRef();
  512. deleteDyads(deletedTerms, egoInt, alterInt, node, dt);
  513. String oldPC = oldNode.pcString,
  514. newPC = node.pcString;
  515. if (! oldPC.equals(newPC)) {
  516. KinTypeIndex kti = Context.current.kti;
  517. Integer[] pair = {egoInt, alterInt};
  518. kti.removePair(oldPC, pair);
  519. }
  520. if (SIL_Edit.editWindow.chart.distinctAdrTerms) {
  521. dt = Context.current.domTheoryAdr();
  522. deletedTerms = oldNode.getKinTerms(true);
  523. deletedTerms.removeAll(node.getKinTerms(true));
  524. deleteDyads(deletedTerms, egoInt, alterInt, node, dt);
  525. }
  526. } catch (Exception ex) {
  527. String msg = "Error while loading domain theories: " + ex;
  528. MainPane.displayError(msg, "Internal Error", JOptionPane.WARNING_MESSAGE);
  529. }
  530. }
  531. }
  532. void deleteDyads(ArrayList<String> deletedTerms, int egoInt, int alterInt,
  533. Node node, DomainTheory dt) {
  534. DyadTMap dyadsDef = dt.dyadsDefined;
  535. DyadTMap dyadsUndef = dt.dyadsUndefined;
  536. for (String kinTerm : deletedTerms) {
  537. if (dyadsDef.containsKey(kinTerm)) {
  538. dyadsDef.removeDyad(dt, egoInt, alterInt, kinTerm, node.pcString);
  539. } else {
  540. dyadsUndef.removeDyad(dt, egoInt, alterInt, kinTerm, node.pcString);
  541. }
  542. }
  543. }
  544. /**
  545. Return a {@link Node} of KinTerms that <code>ego</code> may call <code>alter</code>.
  546. @param egoInt (serial number of) speaker of this kinTerm: the focus person.
  547. @param alterInt (serial number of) person ego would call this kinTerm
  548. @return the Node of KinTerms, or null if no terms are defined for this pair.
  549. */
  550. public Node getCell(int egoInt, int alterInt) {
  551. Integer ego = new Integer(egoInt), alter = new Integer(alterInt);
  552. if (matrix.get(ego) == null) {
  553. return null;
  554. }
  555. return (Node) ((TreeMap) matrix.get(ego)).get(alter);
  556. } // end of method getCell
  557. /**
  558. Return a {@link Node} of KinTerms that <code>ego</code> may call <code>alter</code>.
  559. @param egoInd {@link Individual} who uses this kinTerm: the focus person.
  560. @param alterInd <code>Individual</code> ego would call this kinTerm
  561. @return the Node of KinTerms
  562. */
  563. public Node getCell(Individual egoInd, Individual alterInd) {
  564. Integer ego = new Integer(egoInd.serialNmbr), alter = new Integer(alterInd.serialNmbr);
  565. if (matrix.get(ego) == null) {
  566. return null;
  567. }
  568. return (Node) ((TreeMap) matrix.get(ego)).get(alter);
  569. } // end of method getCell
  570. /** Remove this cell (node) if it exists.
  571. *
  572. * @param egoInt serial number of ego
  573. * @param alterInt serial number of alter
  574. */
  575. public void removeCell(int egoInt, int alterInt) {
  576. Integer ego = new Integer(egoInt), alter = new Integer(alterInt);
  577. if (matrix.get(ego) == null) return;
  578. ((TreeMap) matrix.get(ego)).remove(alter);
  579. } // end of method getCell
  580. /**
  581. Return an ArrayList<Object> of Nodes containing the kinTerms ego would use for each
  582. person in the list of individuals. The returned list is exactly the same length as the
  583. input list, or <code>null</code> if there are no kinTerms for this Ego.
  584. @param ego a focal person.
  585. @param individuals list of <code>Individual</code>s
  586. @return an ArrayList<Object> of Nodes holding appropriate kinTerms (Strings) for the
  587. Individual in the corresponding position of the input ArrayList<Object> <code>individuals</code>.
  588. @throws a KSInternalErrorException if the input ArrayList<Object> <code>individuals</code> contains anything
  589. other than <code>Individual</code>s.
  590. */
  591. public ArrayList<Object> getEgoTermList(Individual ego, ArrayList<Object> individuals)
  592. throws KSInternalErrorException {
  593. int[] indArray = new int[individuals.size()];
  594. Iterator indIter = individuals.iterator();
  595. int i = 0;
  596. try {
  597. while (indIter.hasNext()) {
  598. indArray[i++] = ((Individual) indIter.next()).serialNmbr;
  599. }
  600. } catch (ClassCastException e) {
  601. throw new KSInternalErrorException("List passed to KinTermMatrix.getEgoTermList "
  602. + "has an element that is NOT an Individual.\n" + e);
  603. }
  604. return getEgoTermList(ego.serialNmbr, indArray);
  605. } // end of method getEgoTermList
  606. /**
  607. Return an ArrayList<Object> of Nodes containing the kinTerms ego would use for each
  608. person in the list of individuals. The returned list is exactly the same length as the
  609. input list, or <code>null</code> if there are no kinTerms for this Ego.
  610. @param ego serial number of a focal person.
  611. @param individuals array of serial numbers
  612. @return a list of Nodes; each (possibly empty) holds appropriate kinTerms (Strings),
  613. for the Individual (who has a serial number) in the corresponding position of the
  614. input ArrayList<Object> <code>individuals</code>.
  615. */
  616. public ArrayList<Object> getEgoTermList(int ego, int[] individuals) {
  617. ArrayList<Object> reply = new ArrayList<Object>();
  618. TreeMap tree = (TreeMap) matrix.get(new Integer(ego));
  619. if (tree == null) {
  620. return null;
  621. }
  622. Integer serial;
  623. for (int j = 0; j < individuals.length; j++) {
  624. serial = new Integer(individuals[j]);
  625. if (tree.get(serial) == null) {
  626. reply.add(new Node());
  627. } else {
  628. reply.add(tree.get(serial));
  629. }
  630. } // end of loop thru individuals
  631. return reply;
  632. } // end of method getEgoTermList
  633. /**
  634. Return a TreeMap which represents <code>ego</code>'s row in this KinTermMatrix, or <code>null</code> if no row exists yet.
  635. The returned TreeMap has one Node associated with each Alter that has any kinTerms defined.
  636. @param egoInd a focal person.
  637. @return a TreeMap of Nodes associated with Alter Serial Numbers.
  638. */
  639. public TreeMap getRow(Individual egoInd) {
  640. Integer ego = new Integer(egoInd.serialNmbr);
  641. return (TreeMap) matrix.get(ego);
  642. } // end of method getRow
  643. /**
  644. Return a TreeMap which represents <code>ego</code>'s row in this KinTermMatrix, or <code>null</code> if no row exists yet.
  645. The returned TreeMap has one Node associated with each Alter that has any kinTerms defined.
  646. @param egoInt serial number of a focal person.
  647. @return a TreeMap of Nodes associated with Alter Serial Numbers.
  648. */
  649. public TreeMap getRow(int egoInt) {
  650. Integer ego = new Integer(egoInt);
  651. if (matrix.get(ego) == null) {
  652. return null;
  653. } else {
  654. return (TreeMap) matrix.get(ego);
  655. }
  656. } // end of method getRow
  657. /** Build an array of ints = the linking kinsmen between ego and alter.
  658. * A "miniPred" looks like: "Fa(#3,#8)"
  659. *
  660. * @param egoNum ego's serial number
  661. * @param alterNum alter's serial number
  662. * @return the array
  663. */
  664. public ArrayList<Integer> getPath(int egoNum, int alterNum) {
  665. ArrayList<Integer> path = new ArrayList<Integer>();
  666. Node n = getCell(egoNum, alterNum);
  667. if (n == null || n.miniPreds == null) return path;
  668. for (Object o : n.miniPreds) {
  669. String pred = (String)o;
  670. int start, comma, close, p1, p2;
  671. start = pred.indexOf("#");
  672. comma = pred.indexOf(",");
  673. close = pred.indexOf(")");
  674. p1 = Integer.parseInt(pred.substring(start +1, comma));
  675. start = pred.indexOf("#", comma);
  676. p2 = Integer.parseInt(pred.substring(start +1, close));
  677. if (p1 != egoNum && p1 != alterNum && !path.contains(p1)) {
  678. path.add(p1);
  679. }
  680. if (p2 != egoNum && p2 != alterNum && !path.contains(p2)) {
  681. path.add(p2);
  682. }
  683. }
  684. return path;
  685. }
  686. /**
  687. Update <code>ego</code>'s row in this KinTermMatrix. For each person in the ArrayList<Individual>
  688. <code>people</code>, let its current node become the new <code>Node</code> for that person in ego's row.
  689. * This method is used in Data Gathering *
  690. @param egoSerial serial# of the Ego for this row.
  691. @param people an ArrayList<Individual> of {@link Individual}s who are on Ego's chart
  692. */
  693. public void updateRow(int egoSerial, ArrayList<Individual> people) {
  694. Integer ego = new Integer(egoSerial), alter;
  695. TreeMap newRow = new TreeMap();
  696. for (Individual ind : people) {
  697. alter = new Integer(ind.serialNmbr);
  698. newRow.put(alter, ind.node);
  699. }
  700. matrix.put(ego, newRow);
  701. // TODO If we keep the 2 extra indexes, I should update them here
  702. // or else rebuild them at end of a Data Gathering session.
  703. }
  704. /**
  705. Update <code>ego</code>'s row in this KinTermMatrix. For each person in the ArrayList<Object>
  706. <code>individuals</code>, let its current node become the new <code>Node</code> for that person in ego's row.
  707. The Index of kinTerms associated with this KinTermMatrix is also updated.
  708. * This method is used primarily in Example Generation *
  709. @param egoInd a focal person.
  710. @param individuals an ArrayList<Object> of {@link Individual}s
  711. */
  712. public void updateRow(Individual egoInd, ArrayList<Individual> individuals) throws NumberFormatException {
  713. // Every individual who has a node appears on Ego's chart. So store his node in Ego's row.
  714. // CAUTION: watch out for substitute egos.
  715. Integer ego = new Integer(egoInd.serialNmbr), alter;
  716. if (matrix.get(ego) == null) {
  717. matrix.put(ego, new TreeMap());
  718. }
  719. Individual person;
  720. TreeMap tree = (TreeMap) matrix.get(ego), altTree;
  721. Iterator indIter = individuals.iterator();
  722. while (indIter.hasNext()) {
  723. person = (Individual) indIter.next();
  724. alter = new Integer(person.serialNmbr);
  725. if (person.node != null && person.node.ktSuffix.length() > 0) {
  726. Integer altEgo = new Integer(pullSerial(person.node.ktSuffix));
  727. if (altEgo.intValue() == egoInd.serialNmbr) { // regular ego
  728. tree.put(alter, person.node);
  729. updateIndices(ego, alter, person.node);
  730. } else { // substitute ego
  731. if (matrix.get(altEgo) == null) {
  732. matrix.put(altEgo, new TreeMap());
  733. }
  734. altTree = (TreeMap) matrix.get(altEgo);
  735. altTree.put(alter, person.node);
  736. updateIndices(altEgo, alter, person.node);
  737. }
  738. } else {
  739. tree.remove(alter);
  740. }
  741. } // end of loop thru serial numbers and cells
  742. } // end of method updateRow
  743. public int pullSerial(String suffix) throws NumberFormatException {
  744. int end = suffix.indexOf(")");
  745. return Integer.parseInt(suffix.substring(1, end));
  746. } // end of method pullSerial
  747. private void updateIndices(Integer ego, Integer alter, Node cell) {
  748. return;
  749. /* Iterator termIter;
  750. // SEE HEADER NOTES ON THIS CLASS FOR HOW TO RECORD DELETED KIN TERMS
  751. if (cell.kinTermsRef() != null) {
  752. termIter = cell.kinTermsRef().iterator();
  753. while (termIter.hasNext()) addToIndex(ego, alter, (String)termIter.next(), false);
  754. }
  755. if (cell.exceptionsRef() != null) {
  756. termIter = cell.exceptionsRef().iterator();
  757. while (termIter.hasNext()) addToIndex(ego, alter, (String)termIter.next(), false);
  758. }
  759. if (cell.extKinTermsRef() != null) {
  760. termIter = cell.extKinTermsRef().iterator();
  761. while (termIter.hasNext()) addToIndex(ego, alter, (String)termIter.next(), false);
  762. }
  763. if (cell.kinTermsAddr() != null) {
  764. termIter = cell.kinTermsAddr().iterator();
  765. while (termIter.hasNext()) addToIndex(ego, alter, (String)termIter.next(), true);
  766. }
  767. if (cell.exceptionsAddr() != null) {
  768. termIter = cell.exceptionsAddr().iterator();
  769. while (termIter.hasNext()) addToIndex(ego, alter, (String)termIter.next(), true);
  770. }
  771. if (cell.extKinTermsAddr() != null) {
  772. termIter = cell.extKinTermsAddr().iterator();
  773. while (termIter.hasNext()) addToIndex(ego, alter, (String)termIter.next(), true);
  774. }
  775. */ } // end of method updateIndices
  776. /**
  777. Replace <code>ego</code>'s row in this KinTermMatrix with this TreeMap. All terms in the old row are erased.
  778. Update the Indices of kinTerms associated with this KinTermMatrix.
  779. @param egoInd a focal person.
  780. @param newRow new TreeMap of serial numbers associated with <code>Node</code>s for <code>ego</code>'s row.
  781. @throws a KSInternalErrorException if the values in the TreeMap <code>newRow</code>
  782. are not <code>Node</code>s and the keys are not Integers.
  783. */
  784. public void replaceRow(Individual egoInd, TreeMap newRow) throws KSInternalErrorException {
  785. replaceRow(egoInd.serialNmbr, newRow);
  786. } // end of alternate-format call to method replaceRow.
  787. /**
  788. Replace <code>ego</code>'s row in this KinTermMatrix with this TreeMap. All terms in the old row are erased.
  789. Update the Indices of kinTerms associated with this KinTermMatrix.
  790. @param egoInt serial number of a focal person.
  791. @param newRow new TreeMap of serial numbers associated with <code>Node</code>s for <code>ego</code>'s row.
  792. @throws a KSInternalErrorException if the values in the TreeMap <code>newRow</code>
  793. are not <code>Node</code>s and the keys are not Integers.
  794. */
  795. public void replaceRow(int egoInt, TreeMap newRow) throws KSInternalErrorException {
  796. Integer ego = new Integer(egoInt), alter;
  797. Iterator entries = newRow.entrySet().iterator();
  798. Map.Entry entry;
  799. Integer person;
  800. Node cell;
  801. try {
  802. while (entries.hasNext()) {
  803. entry = (Map.Entry) entries.next();
  804. person = (Integer) entry.getKey();
  805. cell = (Node) entry.getValue();
  806. } // end of validity-test loop thru newRow's contents
  807. } catch (ClassCastException e) {
  808. throw new KSInternalErrorException("In KinTermMatrix.replaceRow: newRow not composed of Integers and Nodes" + e);
  809. }
  810. // If we made it this far, all data is valid.
  811. matrix.put(ego, newRow);
  812. // Now remove from Index all entries for this Ego
  813. Iterator indexIter = indexRef.values().iterator();
  814. while (indexIter.hasNext()) {
  815. ((TreeMap) indexIter.next()).remove(ego);
  816. }
  817. indexIter = indexAddr.values().iterator();
  818. while (indexIter.hasNext()) {
  819. ((TreeMap) indexIter.next()).remove(ego);
  820. }
  821. entries = newRow.entrySet().iterator();
  822. while (entries.hasNext()) {
  823. entry = (Map.Entry) entries.next();
  824. alter = (Integer) entry.getKey();
  825. cell = (Node) entry.getValue();
  826. updateIndices(ego, alter, cell);
  827. } // end of loop thru newRow's contents
  828. } // end of method replaceRow
  829. } // end of class KinTermMatrix