/code/Context.java
Java | 1408 lines | 1100 code | 54 blank | 254 comment | 365 complexity | 3b892b901b56e04fe51c564f72e84121 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- import java.util.*;
- import java.text.*;
- import java.io.*;
- import java.awt.*;
- import javax.swing.JOptionPane;
- /**
- Each instance of Context is a 'workspace' in which a particular culture's Kinship System
- is under construction or examination. Each contains its own population of
- {@link Family} and {@link Individual} objects, domain theories, etc.
- Class-level (static) fields act as global variables.
- @author Gary Morris, Northern Virginia Community College garymorris2245@verizon.net
- */
- public class Context implements Serializable {
- static Context current; // for Library Browser purposes only. User's current Context = Library.contextUnderConstruction
- static boolean simulation = false;
- static float spellingNoise, classNoise;
- // --- Debug tools ---
- static Individual watchInd;
- static int breakCount1 = 0;
- static int breakCount2 = 0;
- static boolean breakFlag = false;
- // --- Instance Variables ---
- /** Comments hold special comment from (or about) the author of the data about this culture. */
- public String comments = "",
- /** Date this context was initialized. */
- createDate;
- public String dateOfLastSuggestion, dateOfLastDataChange;
- ArrayList<String> dataAuthors = new ArrayList<String>();
- int indSerNumGen = 0, famSerNumGen = 0, maxBaseDefMisFits = 4;
- /** Name of the language spoken in this culture. It is limited administratively to 28 characters. */
- public String languageName;
- ArrayList<Object> selectedKinTerms;
- /** List of all persons in this culture, in serialNmbr order (beginning with 0). */
- public ArrayList<Individual> individualCensus = new ArrayList<Individual>();
- /** List of all families in this culture, in serialNmbr order (beginning with 0). */
- public ArrayList<Family> familyCensus = new ArrayList<Family>();
- ArrayList<Object> bagOfEgos = new ArrayList<Object>();
- private DomainTheory domTheoryRef, domTheoryAdr;
- /** Two-dimensional matrix of all kin terms known for pairs of persons. Row# = Ego's serialNmbr.
- Column = Alter's serialNmbr. Each cell contains null or a {@link Node} with the kinTerms
- <code>Row</code> (Ego) could use to refer to <code>Column</code> (Alter). */
- public KinTermMatrix ktm = new KinTermMatrix();
- /** Index of all {@link Node}str according to their kin type. Used to create
- * named-data-requests.*/
- public KinTypeIndex kti = new KinTypeIndex();
- Individual currentEgo;
- String editDirectory;
- /** True if polygamy is accepted in this culture (regardless of whether it has ever happened). */
- public boolean polygamyPermit, featuresHaveChanged = false; // flag -> true when definition added
- // These 2 parameters (plus maxNoiseP and ignorableP) control the Learning Algorithm
- public boolean doBaseCBs = false, doInduction = false;
- /** Optional extra fields, defined by user. Stored as a TreeMap of pairs:
- property-name (must begin with '*') -> UserDefinedProperty-object. */
- public TreeMap userDefinedProperties;
- /** The <code>saveState</code> boolean flag determines whether this instance of Context has its complete state
- saved to disk at shut-down. The context in which Data_Gathering is done (the 'target culture') MUST be
- saved between sessions. Other contexts can be saved by the User's explicit menu choice. */
- public boolean saveState = false, simDataGen = false;
- /** The learningHistory (Ref or Adr) is a TreeMap from kinTerm -> ArrayList<HistoryItem>.
- * Each history item records a User decision on a Suggestion. */
- public TreeMap<String, ArrayList<HistoryItem>> learningHistoryRef = new TreeMap<String, ArrayList<HistoryItem>>();
- public TreeMap<String, ArrayList<HistoryItem>> learningHistoryAdr;
- /** The autoDef (Ref or Adr) is a TreeMap from kinType -> ArrayList<kinTerm>.
- * This indexes by kin type each accepted definition that could apply to that kin type.
- * It is used to determine if we should attempt to pre-fill the kinTerm field for a new Alter. */
- public TreeMap<String, ArrayList<CB_Ptr>> autoDefRef = new TreeMap<String, ArrayList<CB_Ptr>>();
- public TreeMap<String, ArrayList<CB_Ptr>> autoDefAdr;
- /* The following fields were added to allow a Context to carry the parameters
- * needed by KAES back to the loadFile method. */
- public Point origin;
- public Dimension area;
- public int infoPerson, infoMarriage, labelChoice, ktLabelChoice, maxNoiseP = 25, ignorableP = 5;
- public boolean editable, distinctAdrTerms;
- /** This zero-arg constructor is for use by Serialization ONLY. */
- public Context() {
- createDate = UDate.today();
- Context.current = this;
- }
- // end of zero-arg constructor
- /**
- Constructor with only a {@link DomainTheory} as argument.
-
- @param dt a (possibly empty) domain theory for a Kinship System
- */
- public Context(DomainTheory dt) {
- createDate = UDate.today();
- Context.current = this;
- dt.ctxt = this;
- if (dt.addressTerms) {
- domTheoryAdr = dt;
- } else {
- domTheoryRef = dt;
- }
- languageName = dt.languageName;
- int end = languageName.indexOf("(");
- if (end > -1) {
- languageName = languageName.substring(0, end);
- }
- polygamyPermit = dt.polygamyOK;
- userDefinedProperties = dt.userDefinedProperties;
- Library.activeContexts.put(languageName, this);
- } // end of theory-only constructor
- /**
- Constructor with a {@link DomainTheory} and comments-string.
-
- @param dt a (possibly empty) domain theory for a Kinship System
- @param cmts string to begin the Comments field of this instance.
- */
- public Context(DomainTheory dt, String cmts) {
- createDate = UDate.today();
- Context.current = this;
- dt.ctxt = this;
- comments = cmts;
- if (dt.addressTerms) {
- domTheoryAdr = dt;
- } else {
- domTheoryRef = dt;
- }
- languageName = dt.languageName;
- int end = languageName.indexOf("(");
- if (end > -1) {
- languageName = languageName.substring(0, end);
- }
- polygamyPermit = dt.polygamyOK;
- userDefinedProperties = dt.userDefinedProperties;
- Library.activeContexts.put(languageName, this);
- } // end of 2-arg constructor
- public static void breakpoint() {
- return;
- } // end of breakpoint
- public static String convertDoubleQuotes(String s) {
- return FamilyPanel.convertBannedCharacters(s);
- } // end of method convertDoubleQuotes
- /** Add a Domain Theory to this context.
-
- @param theory new theory to be added, covering kinship terms of Reference or Address.
-
- @throws KSInternalErrorException if the new theory will over-write an existing one
- */
- public void addDomainTheory(DomainTheory theory) throws KSInternalErrorException {
- theory.ctxt = this;
- if (theory.addressTerms) {
- if (domTheoryAdr == null || domTheoryAdr.isEmpty()) {
- domTheoryAdr = theory;
- } else {
- String st = "Attempt to over-write existing Domain Theory (Address) "
- + "for language " + theory.languageName;
- throw new KSInternalErrorException(st);
- }
- } else {
- if (domTheoryRef == null || domTheoryRef.isEmpty()) {
- domTheoryRef = theory;
- } else {
- String st = "Attempt to over-write existing Domain Theory (Reference) "
- + "for language " + theory.languageName;
- throw new KSInternalErrorException(st);
- }
- }
- if (userDefinedProperties == null) {
- userDefinedProperties = theory.userDefinedProperties;
- } else if (theory.userDefinedProperties != null) {
- // Aha! Both theories have non-null TreeMaps of userDefinedProperties
- // We must merge them. IF THERE ARE CONFLICTS, the newly-added theory's version will overwrite.
- Iterator udpIter = theory.userDefinedProperties.entrySet().iterator();
- Map.Entry entry;
- while (udpIter.hasNext()) {
- entry = (Map.Entry) udpIter.next();
- userDefinedProperties.put(entry.getKey(), entry.getValue());
- } // end iteration over all entries in new theory's TMap
- } // end of 2 non-null TreeMaps of userDefinedProperties
- } // end of method addDomainTheory
- /** Returns the Domain Theory for Terms of Reference in this context. */
- public DomainTheory domTheoryRef() throws KSParsingErrorException, JavaSystemException, KSBadHornClauseException,
- KSInternalErrorException, KSConstraintInconsistency {
- if (domTheoryRef != null) {
- return domTheoryRef;
- }
- String fileName = Library.thyDirectory + languageName + ".thy";
- domTheoryRef = Library.readThyFile(fileName);
- return domTheoryRef;
- } // end of accessor method domTheoryRef
- /** Returns the Domain Theory for Terms of Address in this context. */
- public DomainTheory domTheoryAdr() throws KSParsingErrorException, JavaSystemException, KSBadHornClauseException,
- KSInternalErrorException, KSConstraintInconsistency {
- if (domTheoryAdr != null) {
- return domTheoryAdr;
- }
- String fileName = Library.thyDirectory + languageName + "(Adr).thy";
- domTheoryAdr = Library.readThyFile(fileName);
- return domTheoryAdr;
- } // end of accessor method domTheoryAdr
- public boolean hasIssues() {
- if (domTheoryRef != null && !domTheoryRef.issuesForUser.isEmpty()) {
- return true;
- }
- if (domTheoryAdr != null && !domTheoryAdr.issuesForUser.isEmpty()) {
- return true;
- }
- return false;
- }
-
- public boolean domTheoryAdrLoaded() {
- return domTheoryAdr != null;
- }
- public boolean domTheoryRefLoaded() {
- return domTheoryRef != null;
- }
- /** Returns true if a domain theory for Terms of Address exists. It may not be loaded into memory yet. */
- public boolean domTheoryAdrExists() {
- if (domTheoryAdr != null) {
- return true;
- }
- Library.ContextStub cStub = Library.retrieveOrCreateStub(languageName);
- return cStub.adrThyExists;
- }
- /** Returns true if a domain theory for Terms of Reference exists. It may not be loaded into memory yet. */
- public boolean domTheoryRefExists() {
- if (domTheoryRef != null) {
- return true;
- }
- Library.ContextStub cStub = Library.retrieveOrCreateStub(languageName);
- return cStub.refThyExists;
- }
- void domTheoryRefNullify() {
- domTheoryRef = null;
- }
- void domTheoryAdrNullify() {
- domTheoryAdr = null;
- }
- /** Remove this domain theory from this context.
- @param dt theory to be removed. */
- public void removeDomainTheory(DomainTheory dt) {
- // They should all be this simple.
- if (dt.addressTerms) {
- domTheoryAdr = null;
- } else {
- domTheoryRef = null;
- }
- dt.ctxt = null;
- } // end of method removeDomainTheory
- /**Delete all dyads associated with node from the dyadsDefined
- * and dyadsUndefined of the 2 DomainTheories for this context.
- *
- * @param node The source of any dyads.
- */
- void deleteDyads(Node node, int egoSerial) {
- if (node == null) {
- return;
- }
- int alterSerial = node.indiv.serialNmbr;
- String kinType = node.pcString;
- if (domTheoryRef != null) {
- for (Object o : node.kinTermsRef) {
- String kinTerm = (String) o;
- deleteDyad(domTheoryRef, kinTerm, kinType, egoSerial, alterSerial);
- }
- for (Object o : node.extKinTermsRef) {
- deleteDyad(domTheoryRef, (String) o, kinType, egoSerial, alterSerial);
- }
- }
- if (domTheoryAdr != null) {
- for (Object o : node.kinTermsAddr) {
- deleteDyad(domTheoryAdr, (String) o, kinType, egoSerial, alterSerial);
- }
- for (Object o : node.extKinTermsAddr) {
- deleteDyad(domTheoryAdr, (String) o, kinType, egoSerial, alterSerial);
- }
- }
- }
- void addDyad(DomainTheory dt, Dyad d) {
- DyadTMap tm;
- if (dt.theory.containsKey(d.kinTerm)) {
- tm = dt.dyadsDefined;
- } else {
- tm = dt.dyadsUndefined;
- }
- tm.dyAdd(d);
- }
- void confirmDyad(DomainTheory dt, Dyad dy1) {
- DyadTMap tm;
- if (dt.theory.containsKey(dy1.kinTerm)) {
- tm = dt.dyadsDefined;
- } else {
- tm = dt.dyadsUndefined;
- }
- ArrayList<Dyad> lst = tm.findDyadList(dy1);
- for (Dyad dy2 : lst) {
- if (dy1.equals(dy2)) {
- dy2.confirmed = true;
- dy2.challenged = false;
- break;
- }
- } // if we get here, did not find a match
- String msg = "Did not find match for dyad: " + dy1;
- MainPane.displayError(msg, "Internal Error", JOptionPane.ERROR_MESSAGE);
- }
- void deleteDyad(DomainTheory dt, String kinTerm, String kinType,
- int egoSerial, int alterSerial) {
- TreeMap kinTypeTree, dyadTMap = dt.dyadsDefined;
- if (dyadTMap.containsKey(kinTerm)) {
- kinTypeTree = (TreeMap) dyadTMap.get(kinTerm);
- } else {
- dyadTMap = dt.dyadsUndefined;
- kinTypeTree = (TreeMap) dyadTMap.get(kinTerm);
- }
- if (kinTypeTree != null && kinTypeTree.containsKey(kinType)) {
- ArrayList<Object> dyads = (ArrayList<Object>) kinTypeTree.get(kinType);
- Iterator dyIter = dyads.iterator();
- while (dyIter.hasNext()) {
- Dyad dy = (Dyad) dyIter.next();
- if (dy.ego.serialNmbr == egoSerial
- && dy.alter.serialNmbr == alterSerial) {
- dyIter.remove();
- break;
- }
- } // if we deleted a singleton, clean up.
- if (dyads.isEmpty()) {
- kinTypeTree.remove(kinType);
- }
- if (kinTypeTree.isEmpty()) {
- dyadTMap.remove(kinTerm);
- }
- }
- }
- public ArrayList<Object> getPair() throws KSInternalErrorException {
- // return 1 male and 1 female person from IndividualCensus
- ArrayList<Object> pair = new ArrayList<Object>();
- Individual first = individualCensus.get(0), second;
- String nextSex = (first.gender.equals("M") ? "F" : "M");
- pair.add(first);
- Iterator iter = individualCensus.iterator();
- while (iter.hasNext()) {
- second = (Individual) iter.next();
- if (second.gender.equals(nextSex)) {
- pair.add(second);
- return pair;
- } // end of BINGO
- } // end of loop thru individualCensus
- throw new KSInternalErrorException("Context.getPair couldn't find 1 male & 1 female.");
- // return pair;
- } // end of method getPair
- /**
- Add an individual (stored by serial number) to this context.
- @param indiv person to be added */
- public void addIndividual(Individual indiv) { // just for type-checking
- individualCensus.add(indiv.serialNmbr, indiv);
- } // end of method addIndividual
- /**
- Add a family (stored by serial number) to this context.
-
- @param fam family to be added */
- public void addFamily(Family fam) { // just for type-checking
- familyCensus.add(fam.serialNmbr, fam);
- } // end of method addFamily
- int litCounter() {
- int total = 0;
- if (domTheoryRef != null && domTheoryRef.theory != null) {
- Iterator iter = domTheoryRef.theory.values().iterator();
- while (iter.hasNext()) {
- KinTermDef ktd = (KinTermDef) iter.next();
- for (int i = 0; i < ktd.definitions.size(); i++) {
- ClauseBody cb = (ClauseBody) ktd.definitions.get(i);
- total += cb.body.size();
- } // end of loop thru definitions
- for (int i = 0; i < ktd.expandedDefs.size(); i++) {
- ClauseBody cb = (ClauseBody) ktd.expandedDefs.get(i);
- total += cb.body.size();
- } // end of loop thru expandedDefs
- } // end of loop thru theory
- } // end of loop thru domThRef
- if (domTheoryAdr != null && domTheoryAdr.theory != null) {
- Iterator iter = domTheoryAdr.theory.values().iterator();
- while (iter.hasNext()) {
- KinTermDef ktd = (KinTermDef) iter.next();
- for (int i = 0; i < ktd.definitions.size(); i++) {
- ClauseBody cb = (ClauseBody) ktd.definitions.get(i);
- total += cb.body.size();
- } // end of loop thru definitions
- for (int i = 0; i < ktd.expandedDefs.size(); i++) {
- ClauseBody cb = (ClauseBody) ktd.expandedDefs.get(i);
- total += cb.body.size();
- } // end of loop thru expandedDefs
- } // end of loop thru theory
- } // end of loop thru domTheoryAdr
- return total;
- } // end of method litCounter
- /**
- Build a string with a brief summary of this context.
-
- @return a string containing:
- <ul>
- <li> Lanuguage name
- <li> Field worker's comments (if any)
- <li> A count of the individuals and families in this context
- </ul>
- */
- public String toString() {
- String image = createDate + "\nContext for " + languageName + " language";
- if (comments == null || comments.length() == 0) {
- image += " is:\n";
- } else {
- image += " (" + comments + ") is:\n";
- }
- image += indSerNumGen + " individuals and " + famSerNumGen + " families registered.\n";
- return image;
- } // end of description method -- short (default)
- /**
- Build a string with a brief summary of this context.
-
- @param style a string containing 'theory' or 'census' or both terms
-
- @return a string containing:
- <ul>
- <li> Lanuguage name
- <li> Field worker's comments (if any)
- <li> A count of the individuals and families in this context
- <li> (if theory) all known definitions of kinTerms
- <li> (if census) List of each individual (short display)
- <li> (if census) List of each family (short display)
- </ul>
- */
- public String toString(String style) {
- String image = createDate + "\nContext for " + languageName + " language";
- if (comments == null || comments.length() == 0) {
- image += " is:\n";
- } else {
- image += " (" + comments + ") is:\n";
- }
- image += indSerNumGen + " individuals and " + famSerNumGen + " families registered.\n\n";
- if (style.indexOf("theory") >= 0) {
- if (domTheoryRef != null) {
- image += "Terms of Reference:\n";
- image += domTheoryRef.toString()
- + "\n==================================================\n\n";
- }
- if (domTheoryAdr != null) {
- image += "Terms of Address:\n";
- image += domTheoryAdr.toString()
- + "\n==================================================\n\n";
- }
- } // end of if-theory-is-requested
- if (style.indexOf("census") >= 0) {
- image += "Individuals:\n";
- for (int i = 0; i < individualCensus.size(); i++) {
- image += individualCensus.get(i);
- }
- image += "\nFamilies:\n";
- for (int j = 0; j < familyCensus.size(); j++) {
- image += familyCensus.get(j);
- }
- image += "-------End------\n";
- } // end of if-census-requested
- return image;
- } // end of description method -- long, with optional details
- /** Write out a domain theory to a file.
-
- @param file name of file to hold a complete theory.
- @param type if type = 'address' the Terms of Address are written. Else Terms of Reference.
-
- @throws an internal error if the chosen domain theory does not exist or can't be written. */
- public void printTheory(PrintWriter file, String type) throws KSInternalErrorException {
- if (type.equals("address")) {
- domTheoryAdr.toThyFile(file);
- } else {
- domTheoryRef.toThyFile(file);
- }
- } // end of method printTheory
- /** Write out a domain theory for Terms of Reference to a file.
-
- @param file name of file to hold a complete theory.
-
- @throws an internal error if the chosen domain theory does not exist or can't be written. */
- public void printTheory(PrintWriter file)
- throws KSInternalErrorException {
- domTheoryRef.toThyFile(file);
- } // end of method printTheory
- /** Write to a file a complete census of Families and Individuals for this context.
-
- @param file name of file to hold the census. */
- public void printCensus(PrintWriter file) {
- file.print(createDate + "\nContext for " + languageName + " language");
- if (comments == null || comments.length() == 0) {
- file.println(" is:");
- } else {
- file.println(" (" + comments + ") is:");
- }
- file.println(indSerNumGen + " individuals and " + famSerNumGen + " families registered.\n");
- file.println("Individuals:");
- for (int i = 0; i < individualCensus.size(); i++) {
- file.println(individualCensus.get(i));
- }
- file.println("\nFamilies:");
- for (int j = 0; j < familyCensus.size(); j++) {
- file.println(familyCensus.get(j));
- }
- file.println("\n-------End------\n");
- file.flush();
- file.close();
- } // end of method printCensus
- void diagnosticPrint(ClauseBody cb, TreeMap bindings) {
- System.out.println("\n\n##############################################################");
- System.out.println("Generating Examples for: " + cb);
- System.out.println("Bindings: ");
- Iterator bindIter = bindings.entrySet().iterator();
- Map.Entry boundPair;
- while (bindIter.hasNext()) {
- boundPair = (Map.Entry) bindIter.next();
- System.out.println(boundPair.getKey() + " bound to: I-"
- + ((Individual) boundPair.getValue()).serialNmbr);
- } // end of iteration thru bindings
- System.out.println("Individuals:\n");
- for (int i = 0; i < individualCensus.size(); i++) {
- System.out.println(individualCensus.get(i));
- }
- System.out.println("\nFamilies:\n");
- for (int j = 0; j < familyCensus.size(); j++) {
- System.out.println(familyCensus.get(j));
- }
- System.out.println("-------End------\n");
- } // end of diagnosticPrint()
- /**
- <p>Write output file in GEDCOM (v 5.5) format, containing all individuals and
- families in this context.
- </p>
- File will contain:
- <ul>
- <li> Header: Source program & version, </li>
- <li> Destination program & version, </li>
- <li> Date, Filename, GEDCOM version </li>
- <li> Individuals: 1 GEDCOM record each </li>
- <li> Families: 1 GEDCOM record each </li>
- <li> Trailer. </li>
- </ul>
-
- @param outFile a {@link PrintWriter} to write to.
- @param fileName direct filename; required extension is '.ged'
- */
- public void exportGEDCOM(PrintWriter outFile, String fileName, String choice) {
- // Write out the header, all individual and family records, & then trailer.
- outFile.println("0 HEAD");
- outFile.println("1 SOUR SILKin");
- outFile.println("2 VERS 1.0");
- outFile.println("2 NAME SIL Kinship Analysis Tools");
- outFile.println("1 DEST Reunion");
- String today = UDate.today();
- outFile.println("1 DATE " + today);
- outFile.println("1 FILE " + fileName);
- outFile.println("1 GEDC");
- outFile.println("2 VERS 5.5");
- outFile.println("2 FORM LINEAGE-LINKED");
- outFile.println("1 CHAR ASCII");
- Individual ind;
- Family fam;
- Iterator iter1 = individualCensus.iterator();
- while (iter1.hasNext()) {
- ind = (Individual) iter1.next();
- ind.exportGEDCOM(outFile, today, choice, DomainTheory.current.nonTerms);
- } // end of loop through Individuals
- Iterator iter2 = familyCensus.iterator();
- while (iter2.hasNext()) {
- fam = (Family) iter2.next();
- fam.exportGEDCOM(outFile, today);
- } // end of loop through Families
- outFile.println("0 TRLR");
- return;
- } // end of method exportGEDCOM
- private String editorParameters = "";
- public void writeSILKFile(File f, String params) throws FileNotFoundException,
- KSInternalErrorException, KSDateParseException {
- editorParameters = params;
- writeSILKFile(f);
- }
- /**
- Write output file in _.silk format, containing all parameters, dyads,
- individuals and families in this context. This is an XML-style file, with
- blocks defined as follows:
- <p>
- File will contain:
- <ul>
- <li> a <parameters> block. </li>
- <li> an <IndividualCensus> block containing zero or more <individual> blocks. </li>
- <li> a <FamilyCensus> block containing zero or more <family> blocks </li>
- <li> a <matrix> block containing zero or more <row> blocks (specified below).
- This block represents the contents of the KinTermMatrix. </li>
- <li> a <dyadsUndefinedRef> block containing zero or more <dyad> blocks
- for terms of reference. </li>
- <li> a <dyadsDefinedRef> block containing zero or more <dyad> blocks
- for terms of reference. </li>
- <li> (optionally) a <dyadsUndefinedAddr> block containing zero or more <dyad> blocks
- for terms of address. </li>
- <li> (optionally) a <dyadsDefinedAddr> block containing zero or more <dyad> blocks
- for terms of address. </li>
- </ul> </p>
-
- @param f a file to write to.
- */
- public void writeSILKFile(File f) throws FileNotFoundException, KSInternalErrorException,
- KSDateParseException {
- String directory = f.getParent(), path, lang;
- PrintWriter silk = null;
- try {
- silk = new PrintWriter(f, "UTF-8");
- } catch (Exception ex) {
- System.err.println("Encoding 'UTF-8' rejected.");
- System.exit(9);
- }
- silk.println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
- silk.println("<?xml-stylesheet type=\"text/xsl\" href=\"Silk-status.xsl\"?>");
- silk.println("<!DOCTYPE SIL_KinData>");
- silk.println("<SIL_KinData>");
- writeSILKGuts(silk, directory);
- if (domTheoryRef != null && domTheoryRef.issuesForUser != null
- && !domTheoryRef.issuesForUser.isEmpty()) {
- DomainTheory.current = domTheoryRef;
- printSuggestions(silk, domTheoryRef, "Reference");
- }
- if (domTheoryAdr != null && domTheoryAdr.issuesForUser != null
- && !domTheoryAdr.issuesForUser.isEmpty()) {
- DomainTheory.current = domTheoryAdr;
- printSuggestions(silk, domTheoryAdr, "Address");
- }
- silk.println("</SIL_KinData>");
- silk.flush();
- silk.close();
- saveState = false;
- } // end of method writeSILKFile
- /** This method writes the entire saved state of the SIL_Edit session in XML-like format.
- * It is used by writeSILKFile for xxx.silk files, and by writeSuggsFile for xxx.sugg files.
- *
- * @param silk the file to be written
- * @param directory the directory containing 'silk', or null
- * @param sug true = writing a Suggestion file. false = a SILK file
- *
- * @throws FileNotFoundException if there's a file system error
- * @throws KSInternalErrorException if SILKin code crashes
- */
- void writeSILKGuts(PrintWriter silk, String directory)
- throws FileNotFoundException, KSInternalErrorException, KSDateParseException {
- String path, lang;
- silk.println("<parameters>");
- silk.println(" <language name=\"" + languageName + "\"/>");
- if (comments != null && comments.length() > 1) {
- silk.print(" <comments txt=\"");
- comments = convertDoubleQuotes(comments); // replace doubles with singles, etc.
- silk.print(comments);
- silk.println("\"/>");
- } // end of optional comments
- if (createDate != null) {
- if (!UDate.validXSD(createDate)) {
- createDate = UDate.convertToXSD(createDate);
- }
- silk.println(" <createDate value=\"" + createDate + "\"/>");
- } // end of optional createDate
- silk.println(" <dataAuthors>");
- for (String auth : dataAuthors) {
- silk.println("\t<dataAuthor name=\"" + auth + "\"/>");
- }
- silk.println(" </dataAuthors>"); // end of dataAuthors
- if (dateOfLastDataChange != null) {
- silk.println(" <lastDataChangeDate value=\"" + dateOfLastDataChange + "\"/>");
- }
- if (dateOfLastSuggestion != null) {
- silk.println(" <lastSuggestionDate value=\"" + dateOfLastSuggestion + "\"/>");
- }
- silk.println(" <indSerNum>" + indSerNumGen + "</indSerNum> ");
- silk.println(" <famSerNum>" + famSerNumGen + "</famSerNum> ");
- silk.println(" <polygamyPermit>" + polygamyPermit + "</polygamyPermit> ");
- if (userDefinedProperties != null) {
- silk.println("<userDefinedProperties>");
- Iterator iter = userDefinedProperties.entrySet().iterator();
- Map.Entry entry;
- while (iter.hasNext()) {
- silk.println("<UDP>");
- entry = (Map.Entry) iter.next();
- String propName = (String) entry.getKey();
- UserDefinedProperty udp = (UserDefinedProperty) entry.getValue();
- silk.println("<propertyName>" + propName + "</propertyName>");
- silk.println(udp.toSILKString("full"));
- silk.println("</UDP>");
- } // end of loop thru UDPs
- silk.println("</userDefinedProperties>");
- } // end of optional UDPs
- silk.println("</parameters>");
- silk.println("<editorSettings>");
- if (currentEgo != null) {
- silk.println(" <currentEgo n=\"" + currentEgo.serialNmbr + "\"/>");
- }
- if (editDirectory != null) {
- silk.println(" <editDirectory dir=\"" + editDirectory + "\"/>");
- }
- silk.println(editorParameters);
- if (kti.lastSerial != -1) {
- silk.println(" <lastPersonIndexed>" + kti.lastSerial + "</lastPersonIndexed>");
- }
- silk.println("</editorSettings>\n");
- if (domTheoryRef != null) {
- silk.println(domTheoryRef.toSILKString(""));
- }
- if (domTheoryAdr != null) {
- silk.println(domTheoryAdr.toSILKString(""));
- }
- silk.println("<individualCensus>");
- for (int i = 0; i < individualCensus.size(); i++) {
- Individual ind = individualCensus.get(i);
- silk.println(ind.toSILKString());
- }
- silk.println("</individualCensus>");
- silk.println("<familyCensus>");
- for (int i = 0; i < familyCensus.size(); i++) {
- Family fam = familyCensus.get(i);
- silk.println(fam.toSILKString());
- }
- silk.println("</familyCensus>");
- silk.println("<matrix>");
- if (ktm.matrix.size() > 0) {
- silk.println(ktm.toSILKString());
- }
- silk.println("</matrix>");
- silk.println("<dyadsUndefinedRef>");
- if (domTheoryRef != null && domTheoryRef.dyadsUndefined != null) {
- silk.print(domTheoryRef.dyadsUndefined.toSILKString());
- }
- silk.println("</dyadsUndefinedRef>");
- silk.println("<dyadsDefinedRef>");
- if (domTheoryRef != null && domTheoryRef.dyadsDefined != null) {
- silk.print(domTheoryRef.dyadsDefined.toSILKString());
- }
- silk.println("</dyadsDefinedRef>");
- if (domTheoryAdr != null && domTheoryAdr.dyadsUndefined != null) {
- silk.println("<dyadsUndefinedAddr>");
- silk.print(domTheoryAdr.dyadsUndefined.toSILKString());
- silk.println("</dyadsUndefinedAddr>");
- }
- if (domTheoryAdr != null && domTheoryAdr.dyadsDefined != null) {
- silk.println("<dyadsDefinedAddr>");
- silk.print(domTheoryAdr.dyadsDefined.toSILKString());
- silk.println("</dyadsDefinedAddr>");
- }
- if (!kti.isEmpty() && directory != null) {
- silk.println("\n<kinTypeIndex>");
- silk.println(kti.toSILKString());
- silk.println("</kinTypeIndex>");
- }
- if (!learningHistoryRef.isEmpty()) {
- silk.println("\n<learning-history type=\"Ref\">");
- Iterator iter = learningHistoryRef.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry<String, ArrayList<HistoryItem>> entry =
- (Map.Entry<String, ArrayList<HistoryItem>>) iter.next();
- String kinTerm = entry.getKey();
- ArrayList<HistoryItem> list = entry.getValue();
- silk.println("\t<history kinTerm=\"" + kinTerm + "\">");
- for (HistoryItem hi : list) {
- silk.println("\t" + hi.toSILKString());
- }
- silk.println("\t</history>");
- }
- silk.println("</learning-history>\n");
- }
- if (learningHistoryAdr != null && !learningHistoryAdr.isEmpty()) {
- silk.println("\n<learning-history type=\"Adr\">");
- Iterator iter = learningHistoryAdr.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry<String, ArrayList<HistoryItem>> entry =
- (Map.Entry<String, ArrayList<HistoryItem>>) iter.next();
- String kinTerm = entry.getKey();
- ArrayList<HistoryItem> list = entry.getValue();
- silk.println("\t<history kinTerm=\"" + kinTerm + "\">");
- for (HistoryItem hi : list) {
- silk.println("\t" + hi.toSILKString());
- }
- silk.println("\t</history>");
- }
- silk.println("</learning-history>\n");
- }
- if (!autoDefRef.isEmpty()) {
- printAutoDefs(silk, "Ref");
- }
- if (autoDefAdr != null && !autoDefAdr.isEmpty()) {
- printAutoDefs(silk, "Adr");
- }
- }
- void printAutoDefs(PrintWriter pw, String typ) {
- TreeMap<String, ArrayList<CB_Ptr>> autos =
- (typ.equals("Ref") ? autoDefRef : autoDefAdr);
- pw.println("<auto-def type=\"" + typ + "\">");
- Iterator typeIter = autos.entrySet().iterator();
- while (typeIter.hasNext()) {
- Map.Entry<String, ArrayList<CB_Ptr>> entry =
- (Map.Entry<String, ArrayList<CB_Ptr>>) typeIter.next();
- String kinType = entry.getKey();
- ArrayList<CB_Ptr> lst = entry.getValue();
- pw.println("\t<kinType type=\"" + kinType + "\">");
- for (CB_Ptr ptr : lst) {
- pw.println(ptr.toSILKString("\t\t"));
- }
- pw.println("\t</kinType>");
- }
- pw.println("</auto-def>\n");
- }
- public void printSuggestions(PrintWriter pw, DomainTheory dt, String typ) {
- TreeMap<String, ArrayList<Issue>> suggs = dt.issuesForUser;
- pw.println("<silkin-issues type=\"" + typ + "\">");
- Iterator suggIter = suggs.values().iterator();
- while (suggIter.hasNext()) {
- ArrayList<Issue> issues = (ArrayList<Issue>) suggIter.next();
- for (Issue issue : issues) {
- issue.toSILKFile(pw);
- }
- }
- pw.println("</silkin-issues>");
- }
- /** Update certain elements of this context from a newer one.
-
- @param newCtxt contains new or updated information. */
- public void updateFrom(Context newCtxt) throws KSParsingErrorException,
- JavaSystemException, KSBadHornClauseException,
- KSInternalErrorException, KSConstraintInconsistency {
- if (individualCensus.size() != newCtxt.individualCensus.size()
- || familyCensus.size() != newCtxt.familyCensus.size()) {
- throw new KSInternalErrorException("Number of individuals in XML file"
- + "\n does not match number in SILK file.");
- }
- for (int i = 0; i < individualCensus.size(); i++) {
- Individual newRec = newCtxt.individualCensus.get(i),
- oldRec = individualCensus.get(i);
- oldRec.updateFrom(newRec);
- } // end of loop through individuals
- for (int i = 0; i < familyCensus.size(); i++) {
- Family newRec = newCtxt.familyCensus.get(i),
- oldRec = familyCensus.get(i);
- oldRec.updateFrom(newRec);
- } // end of loop through families
- createDate = newCtxt.createDate;
- comments += newCtxt.comments;
- languageName = newCtxt.languageName;
- domTheoryRef = (domTheoryRefExists() ? newCtxt.domTheoryRef() : null);
- domTheoryAdr = (domTheoryAdrExists() ? newCtxt.domTheoryAdr() : null);
- ktm = newCtxt.ktm;
- Iterator egoIter = ktm.matrix.values().iterator();
- while (egoIter.hasNext()) {
- Iterator alterIter = ((TreeMap) egoIter.next()).values().iterator();
- while (alterIter.hasNext()) {
- TempNode tNode = (TempNode) alterIter.next();
- tNode.indiv = individualCensus.get(tNode.indNmbr);
- } // end of loop through cells
- } // end of loop thru rows
- editDirectory = newCtxt.editDirectory;
- polygamyPermit = newCtxt.polygamyPermit;
- currentEgo = newCtxt.currentEgo;
- userDefinedProperties =
- (newCtxt.userDefinedProperties != null ? newCtxt.userDefinedProperties : null);
- } // end of method updateFrom
- /** Designate a new Ego (interview subject).
-
- @param ego the new person whose data is being gathered (being interviewed). */
- public void changeEgoTo(Individual ego) {
- // First, store all data for currentEgo
- if (currentEgo != null) {
- ktm.updateRow(currentEgo, individualCensus);
- }
- // Now prep for the new currentEgo
- currentEgo = ego;
- if (ego == null) {
- return; // for final storage of KTM before shutdown
- }
- TreeMap egoRow = ktm.getRow(ego);
- for (int i = 0; i < individualCensus.size(); i++) {
- Individual person = individualCensus.get(i);
- person.dyad = null;
- person.node = new Node();
- if (egoRow != null && person != ego) {
- Node nod = (Node) egoRow.get(new Integer(person.serialNmbr));
- if (nod != null) {
- person.node = nod;
- }
- }
- } // end of loop thru all people
- } // end of method changeEgoTo
- /**
- Restore this context to a prior state, ELIMINATING all persons and families
- created with serial numbers greater-or-equal-to these. USE WITH CAUTION. After this purging,
- the census populations will contain 'nmbrIndivs' individuals and 'nmbrFams' families.
-
- @param nmbrIndivs lowest individual serial number to be removed.
- @param nmbrFams lowest family serial number to be removed.
-
- @throws KSInternalErrorException if the population counts do not add up
- to the proper figures after purging.
- */
- public void resetTo(int nmbrIndivs, int nmbrFams) throws KSInternalErrorException {
- if (nmbrIndivs == 0 && nmbrFams == 0) { // Erase all and start over.
- individualCensus = new ArrayList<Individual>();
- familyCensus = new ArrayList<Family>();
- currentEgo = null;
- indSerNumGen = 0;
- famSerNumGen = 0;
- return;
- }
- Individual currInd;
- Family fam, currFam;
- for (int i = individualCensus.size() - 1; i >= nmbrIndivs; i--) {
- // work from end of list back to reset point.
- currInd = individualCensus.get(i);
- indSerNumGen--;
- for (int j = 0; j < currInd.marriages.size(); j++) {
- fam = (Family) currInd.marriages.get(j);
- if (fam.husband == currInd) {
- fam.husband = null;
- } else if (fam.wife == currInd) {
- fam.wife = null;
- } else {
- String msg = "Indiv lists marriage but is neither H nor W.\n";
- msg += currInd + "\n";
- msg += fam;
- throw new KSInternalErrorException(msg);
- } // end of error
- } // end of for-each-marriage-she-is-in
- if (currInd.birthFamily != null) {
- fam = currInd.birthFamily;
- int k = fam.children.lastIndexOf(currInd);
- if ((k < 0) || (fam.nmbrOfKids <= 0)) {
- String msg2 = "Indiv lists birthFamily but is not a child in it.";
- msg2 += currInd + "\n";
- msg2 += fam;
- throw new KSInternalErrorException(msg2);
- } // end of error
- fam.children.remove(k);
- fam.nmbrOfKids--;
- } // end of remove-from-birthFamily
- individualCensus.remove(i);
- } // end of Individual purge
- // It is possible that families created after the reset point could have one or both
- // parents from prior to the reset point, and even kids created pre-reset. Ergo, we can't
- // do any error-checking before purging this family.
- for (int i = familyCensus.size() - 1; i >= nmbrFams; i--) {
- currFam = familyCensus.get(i);
- famSerNumGen--;
- if (currFam.husband != null) {
- int k = currFam.husband.marriages.lastIndexOf(currFam);
- currFam.husband.marriages.remove(k);
- } // end of husband processing
- if (currFam.wife != null) {
- int k = currFam.wife.marriages.lastIndexOf(currFam);
- currFam.wife.marriages.remove(k);
- } // end of husband processing
- for (int j = 0; j < currFam.nmbrOfKids; j++) {
- currInd = (Individual) currFam.children.get(j);
- currInd.birthFamily = null;
- } // end of kid processing
- familyCensus.remove(i);
- } // end of Family purge
- if ((familyCensus.size() != nmbrFams) || (individualCensus.size() != nmbrIndivs)) {
- throw new KSInternalErrorException("Population counts after reset-purge don't balance.");
- }
- return;
- } // end of method resetTo
- public void cleanNodeFields() {
- Individual ind;
- for (int i = 0; i < indSerNumGen; i++) {
- (individualCensus.get(i)).node = null;
- }
- } // end of method cleanNodeFields
- /** Searches through all persons on this context, seeking one with the target value
- that meets all the constraints. SEMANTIC NOTE: If the target value is a list of objects,
- this method considers another list to 'match' if it has the same elements IN ANY ORDER.
-
- @param arg an Argument (MathVariable or Constant) with a target value we want to match.
- @param starName the name of a UserDefinedPredicate that must hold the target value; must begin with '*'
- @param personVar the variable for the person we seek
- @param constraints holds all known constraints for varName
- @param badBindings a TreeMap (perhaps empty) of keys = argNames and Values = ALists of Individuals who shouldn't be chosen
- @param starBindings a list of {@link StarPropertyBinding}str
- @param bindings all the bindings of variables thus far
-
- @return an Individual conforming to this set of requirements, or null if none is found.
- */
- public Individual findConformingPerson(Argument arg, String starName, Variable personVar, ConstraintObj constraints,
- TreeMap badBindings, ArrayList<Object> starBindings, TreeMap bindings)
- throws KSConstraintInconsistency, KSInternalErrorException, ClassNotFoundException {
- if (arg.getVal().isEmpty()) {
- return null; // There's no target value, so we must punt.
- }
- boolean singleVal = true, bbOK;
- if (arg.getVal().size() > 1) {
- singleVal = false;
- }
- Object theVal = null;
- if (singleVal) {
- theVal = arg.getVal().get(0);
- }
- Iterator indIter = individualCensus.iterator();
- Individual ind;
- ArrayList<Object> badList = (ArrayList<Object>) badBindings.get(personVar.argName);
- UserDefinedProperty udp = (UserDefinedProperty) userDefinedProperties.get(starName); // using the Context's master copy to verify
- if ((!singleVal) && udp.singleValue) {
- throw new KSInternalErrorException("Multi-valued arg '" + arg.argName + "' linked to single-valued UDP "
- + starName + " for " + personVar.argName);
- }
- while (indIter.hasNext()) {
- ind = (Individual) indIter.next();
- if (badList != null && badList.contains(ind)) {
- bbOK = false;
- } else {
- bbOK = true;
- }
- udp = (UserDefinedProperty) ind.userDefinedProperties.get(starName);
- if (singleVal) { // single-valued arg
- if (udp.value.contains(theVal) && (udp.value.size() == 1) && bbOK
- && ind.meetsConstraintsStrictly(personVar, constraints, bindings, starBindings)) {
- return ind;
- }
- } // end of processing for single-valued arg
- else { // multi-valued arg
- boolean equality = true;
- if (udp.value.size() != arg.getVal().size()) {
- equality = false;
- }
- if (equality) {
- for (int i = 0; i < udp.value.size(); i++) {
- if (!arg.getVal().contains(udp.value.get(i))) {
- equality = false;
- }
- }
- }
- if (equality && bbOK
- && ind.meetsConstraintsStrictly(personVar, constraints, bindings, starBindings)) {
- return ind;
- }
- } // end of processing for multi-valued arg
- } // end of loop thru all persons
- return null;
- } // end of method findConformingPerson
- /** Searches through all persons on this context, seeking one with the target value
- that meets all the constraints.
-
- @param targetVal the person (target value) we want to match.
- @param starName the name of a UserDefinedPredicate that must hold the target value; must begin with '*'
- @param personVar the variable for the person we seek
- @param constraints holds all known constraints for varName
- @param badBindings a TreeMap (perhaps empty) of keys = argNames and Values = ALists of Individuals who shouldn't be chosen
- @param starBindings a list of {@link StarPropertyBinding}str
- @param bindings all the bindings of variables thus far
-
- @return an Individual conforming to this set of requirements, or null if none is found.
- */
- public Individual findConformingPerson(Individual targetVal, String starName, Variable personVar,
- ConstraintObj constraints, TreeMap badBindings, ArrayList<Object> starBindings, TreeMap bindings)
- throws KSConstraintInconsistency, KSInternalErrorException, ClassNotFoundException {
- Iterator indIter = individualCensus.iterator();
- Individual ind;
- boolean bbOK;
- UserDefinedProperty udp;
- while (indIter.hasNext()) {
- ind = (Individual) indIter.next();
- ArrayList<Object> badList = (ArrayList<Object>) badBindings.get(personVar.argName);
- bbOK = true;
- if (badList != null && badList.contains(ind)) {
- bbOK = false;
- }
- udp = (UserDefinedProperty) ind.userDefinedProperties.get(starName);
- if (udp.value.contains(targetVal) && (udp.value.size() == 1) && bbOK
- && ind.meetsConstraintsStrictly(personVar, constraints, bindings, starBindings)) {
- return ind;
- }
- } // end of loop thru all persons
- return null;
- } // end of method findConformingPerson
- /** Start from ego and create a {@link Dyad} for each named relationship encountered on a breadth-first
- walk of ego's family tree. We do the walk in 2 passes: the first pass uses ONLY biological links (i.e.
- spousal links and birth links). The second pass adds any Star-Links (based on UDPs) which add new relatives
- of Ego. This 2-pass method is required because kinship defined in terms …
Large files files are truncated, but you can click here to view the full file