├── doc ├── media.PNG ├── note.PNG ├── family.PNG ├── gedcom.PNG ├── header.PNG ├── person.PNG ├── source.PNG ├── repository.PNG ├── submission.PNG ├── submitter.PNG ├── submission.ucls ├── jackson.txt └── submitter.ucls ├── .gitignore ├── src ├── main │ ├── resources │ │ ├── EventFact_iw.properties │ │ ├── EventFact_ru.properties │ │ ├── logging.properties │ │ ├── EventFact.properties │ │ └── EventFact_it.properties │ └── java │ │ └── org │ │ ├── folg │ │ └── gedcom │ │ │ ├── model │ │ │ ├── Visitable.java │ │ │ ├── Trailer.java │ │ │ ├── Change.java │ │ │ ├── MediaRef.java │ │ │ ├── LdsOrdinance.java │ │ │ ├── GedcomVersion.java │ │ │ ├── CharacterSet.java │ │ │ ├── DateTime.java │ │ │ ├── SpouseFamilyRef.java │ │ │ ├── ParentFamilyRef.java │ │ │ ├── ParentRelationship.java │ │ │ ├── GeneratorData.java │ │ │ ├── Association.java │ │ │ ├── Extensions.java │ │ │ ├── Submission.java │ │ │ ├── ChildRef.java │ │ │ ├── SourceCitationContainer.java │ │ │ ├── SpouseRef.java │ │ │ ├── ExtensionContainer.java │ │ │ ├── Generator.java │ │ │ ├── NoteRef.java │ │ │ ├── RepositoryRef.java │ │ │ ├── NoteContainer.java │ │ │ ├── MediaContainer.java │ │ │ ├── GeneratorCorporation.java │ │ │ ├── Visitor.java │ │ │ ├── SourceCitation.java │ │ │ ├── Media.java │ │ │ ├── Note.java │ │ │ ├── Repository.java │ │ │ ├── Address.java │ │ │ ├── PersonFamilyCommonContainer.java │ │ │ ├── Submitter.java │ │ │ ├── Header.java │ │ │ ├── Family.java │ │ │ ├── Source.java │ │ │ ├── Name.java │ │ │ ├── Person.java │ │ │ └── GedcomTag.java │ │ │ ├── parser │ │ │ ├── ErrorHandler.java │ │ │ ├── GedcomTypeAdapter.java │ │ │ ├── FieldRef.java │ │ │ ├── ExtensionsTypeAdapter.java │ │ │ ├── JsonParser.java │ │ │ └── TreeParser.java │ │ │ └── tools │ │ │ ├── PlaceWriter.java │ │ │ ├── Gedcom2Gedcom.java │ │ │ ├── Gedcom2Json.java │ │ │ ├── GedcomAnalyzer.java │ │ │ └── CountsCollector.java │ │ └── gedml │ │ └── GedcomLineParser.java └── test │ ├── java │ └── org │ │ └── folg │ │ ├── model │ │ ├── EventFactTest.java │ │ └── GedcomTest.java │ │ ├── gedcom │ │ └── parser │ │ │ ├── TreeParserTest.java │ │ │ ├── ModelParserTest.java │ │ │ └── JsonParserTest.java │ │ └── gedml │ │ └── GedcomParserTest.java │ └── resources │ ├── Case002-ReferenceIntegrity.ged │ └── Case001-AddressStructure.ged ├── release-procedure.txt ├── AUTHORS ├── examples └── EXAMPLES.md ├── README.md └── pom.xml /doc/media.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/media.PNG -------------------------------------------------------------------------------- /doc/note.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/note.PNG -------------------------------------------------------------------------------- /doc/family.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/family.PNG -------------------------------------------------------------------------------- /doc/gedcom.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/gedcom.PNG -------------------------------------------------------------------------------- /doc/header.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/header.PNG -------------------------------------------------------------------------------- /doc/person.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/person.PNG -------------------------------------------------------------------------------- /doc/source.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/source.PNG -------------------------------------------------------------------------------- /doc/repository.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/repository.PNG -------------------------------------------------------------------------------- /doc/submission.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/submission.PNG -------------------------------------------------------------------------------- /doc/submitter.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FamilySearch/gedcom5-java/HEAD/doc/submitter.PNG -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.lock 3 | *.swp 4 | target 5 | .idea 6 | *.iml 7 | nbproject 8 | out 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /src/main/resources/EventFact_iw.properties: -------------------------------------------------------------------------------- 1 | birt=\u05DC\u05D9\u05D3\u05D4 2 | buri=\u05E7\u05D1\u05D5\u05E8\u05D4 3 | deat=\u05DE\u05D5\u05D5\u05EA 4 | even=\u05D0\u05D9\u05E8\u05D5\u05E2 5 | marr=\u05E0\u05D9\u05E9\u05D5\u05D0\u05D9\u05DD 6 | other=\u05D0\u05D7\u05E8 7 | resi=\u05DE\u05D2\u05D5\u05E8\u05D9\u05DD 8 | -------------------------------------------------------------------------------- /release-procedure.txt: -------------------------------------------------------------------------------- 1 | To cut a new version: 2 | 3 | 1. export PGP_SECRET_KEYFILE=~/.ssh/gedcomx/gedcomx-pgp-key.asc 4 | 2. mvn -B -Prelease clean release:clean release:prepare -Dtag=$THIS_RELEASE_VERSION -DreleaseVersion=$THIS_RELEASE_VERSION -DdevelopmentVersion=$NEXT_SNAPSHOT_VERSION release:perform 5 | 3. mvn release:clean 6 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | This is a list of contributors to the source code 2 | 3 | The files in org.gedml were authored by: 4 | 5 | Michael Kay 6 | with additional contributions from 7 | Lynn Monson 8 | Nathan Powell 9 | Dallan Quass 10 | 11 | The files in org.folg.gedcom were authored by 12 | 13 | Dallan Quass 14 | -------------------------------------------------------------------------------- /src/main/resources/EventFact_ru.properties: -------------------------------------------------------------------------------- 1 | bapm=\u041A\u0440\u0435\u0449\u0435\u043D\u0438\u0435 2 | birt=\u0420\u043E\u0436\u0434\u0435\u043D\u0438\u0435 3 | deat=\u0421\u043C\u0435\u0440\u0442\u044C 4 | even=\u0421\u043E\u0431\u044B\u0442\u0438\u0435 5 | occu=\u041F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044F 6 | other=\u0414\u0440\u0443\u0433\u043E\u0435 7 | resi=\u041F\u0440\u043E\u0436\u0438\u0432\u0430\u043D\u0438\u0435 8 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Visitable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/25/11 22 | */ 23 | public interface Visitable { 24 | public void accept(Visitor visitor); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/parser/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.parser; 18 | 19 | /** 20 | * User: dallan 21 | * Date: 1/2/12 22 | */ 23 | public interface ErrorHandler { 24 | public void warning(String message, int lineNumber); 25 | public void error(String message, int lineNumber); 26 | public void fatalError(String message, int lineNumber); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Trailer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/26/11 22 | */ 23 | public class Trailer extends ExtensionContainer { 24 | // TODO do we need this? how many gedcoms attach stuff to the trailer? 25 | public void accept(Visitor visitor) { 26 | // ignore 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/org/folg/model/EventFactTest.java: -------------------------------------------------------------------------------- 1 | package org.folg.model; 2 | 3 | import org.folg.gedcom.model.EventFact; 4 | import org.testng.annotations.Test; 5 | 6 | import java.util.Locale; 7 | import java.util.Map; 8 | import java.util.ResourceBundle; 9 | 10 | import static org.testng.Assert.assertFalse; 11 | import static org.testng.Assert.assertNotNull; 12 | 13 | public class EventFactTest { 14 | @Test 15 | public void testPropertyResourceBundle() throws Exception { 16 | Map displayTypes = EventFact.DISPLAY_TYPE; 17 | assertNotNull(displayTypes); 18 | assertFalse(displayTypes.isEmpty()); 19 | ResourceBundle resourceBundle = ResourceBundle.getBundle("EventFact", Locale.getDefault()); 20 | assertNotNull(resourceBundle); 21 | for (String tag : displayTypes.keySet()) { 22 | String key = displayTypes.get(tag); 23 | assertNotNull(key); 24 | String displayType = resourceBundle.getString(key); 25 | assertNotNull(displayType); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/logging.properties: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # Global properties 3 | ############################################################ 4 | 5 | handlers = java.util.logging.ConsoleHandler 6 | 7 | # Default global logging level. 8 | .level= WARNING 9 | 10 | ############################################################ 11 | # Handler specific properties. 12 | # Describes specific configuration info for Handlers. 13 | ############################################################ 14 | 15 | java.util.logging.ConsoleHandler.level=INFO 16 | java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter 17 | 18 | #java.util.logging.FileHandler.pattern = %h/java.log 19 | java.util.logging.FileHandler.append = true 20 | java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter 21 | 22 | ############################################################ 23 | # Facility specific properties. 24 | # Provides extra control for each logger. 25 | ############################################################ 26 | 27 | #org.folg.gedcom.parser.level = INFO 28 | #org.folg.gedcom.tools.level = WARNING -------------------------------------------------------------------------------- /doc/submission.ucls: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test/java/org/folg/model/GedcomTest.java: -------------------------------------------------------------------------------- 1 | package org.folg.model; 2 | 3 | import org.folg.gedcom.model.Gedcom; 4 | import org.folg.gedcom.parser.ModelParser; 5 | import org.testng.annotations.Test; 6 | 7 | import java.io.InputStream; 8 | import java.net.URL; 9 | 10 | import static org.testng.Assert.assertEquals; 11 | import static org.testng.Assert.assertNotNull; 12 | 13 | public class GedcomTest { 14 | @Test 15 | public void testUpdateReferenceIntegrity() throws Exception { 16 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case002-ReferenceIntegrity.ged"); 17 | ModelParser modelParser = new ModelParser(); 18 | 19 | InputStream is = gedcomUrl.openStream(); 20 | assertNotNull(is); 21 | 22 | Gedcom gedcom = modelParser.parseGedcom(is); 23 | assertNotNull(gedcom); 24 | 25 | gedcom.createIndexes(); 26 | gedcom.updateReferences(); 27 | assertNotNull(gedcom); 28 | 29 | assertEquals(gedcom.getPerson("I2").getSpouseFamilyRefs().size(), 3); 30 | assertEquals(gedcom.getFamily("F1").getHusbandRefs().size(), 1); 31 | assertEquals(gedcom.getFamily("F1").getWifeRefs().size(), 1); 32 | assertEquals(gedcom.getFamily("F2").getChildRefs().size(), 1); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/EXAMPLES.md: -------------------------------------------------------------------------------- 1 | ## Examples 2 | See all parsers in [main/java/org/folg/gedcom/parser](../src/main/java/org/folg/gedcom/parser) directory. 3 | 4 | ### 1. Parse gedcom and print all people names 5 | 6 | String filePath = "/path-to-family-tree-file.ged"; 7 | File file = new File(filePath); 8 | 9 | ModelParser modelParser = new ModelParser(); 10 | Gedcom gedcom = modelParser.parseGedcom(file); 11 | List people = gedcom.getPeople(); 12 | System.out.println("People: " + people.size()); 13 | 14 | int index = 1; 15 | for (Person person : people) { 16 | for (Name name : person.getNames()) { 17 | System.out.printf("\n%d: %s %s", index, name.getSurname(), name.getGiven()); 18 | } 19 | 20 | index ++; 21 | } 22 | } 23 | 24 | ### 2. Parse gedcom and print all tags 25 | 26 | String filePath = "/path-to-family-tree-file.ged"; 27 | File file = new File(filePath); 28 | 29 | TreeParser treeParser = new TreeParser(); 30 | List gedcomTags = treeParser.parseGedcom(file); 31 | System.out.println("Tags: " + gedcomTags.size()); 32 | 33 | int index = 1; 34 | for (GedcomTag tag : gedcomTags) { 35 | 36 | System.out.printf("\n%d: %s tag with %d children", index, tag.getTag(), tag.getChildren().size()); 37 | index ++; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Change.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/25/11 22 | */ 23 | public class Change extends NoteContainer { 24 | private DateTime date = null; 25 | 26 | public DateTime getDateTime() { 27 | return date; 28 | } 29 | 30 | public void setDateTime(DateTime date) { 31 | this.date = date; 32 | } 33 | 34 | public void accept(Visitor visitor) { 35 | if (visitor.visit(this)) { 36 | if (date != null) { 37 | date.accept(visitor); 38 | } 39 | super.visitContainedObjects(visitor); 40 | visitor.endVisit(this); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/resources/EventFact.properties: -------------------------------------------------------------------------------- 1 | adop=Adoption 2 | afn=Ancestral File number 3 | anul=Annulment 4 | arvl=Arrival 5 | attr=Attribute 6 | bapm=Baptism 7 | barm=Bar mitzvah 8 | batm=Bat mitzvah 9 | birt=Birth 10 | bles=Blessing 11 | buri=Burial 12 | cast=Caste 13 | caus=Cause of death 14 | cens=Census 15 | chr=Christening 16 | claw=Common law marriage 17 | color=Color 18 | conf=Confirmation 19 | crem=Cremation 20 | deat=Death 21 | death_of_spouse=Death of spouse 22 | deed=Deed 23 | deg=Degree 24 | div=Divorce 25 | divf=Divorce filing 26 | dprt=Departure 27 | dscr=Physical description 28 | educ=Education 29 | elec=Elected 30 | email=Email 31 | emig=Emigration 32 | empl=Employment 33 | enga=Engagement 34 | even=Event 35 | excm=Excommunication 36 | eyes=Eyes 37 | fcom=First communion 38 | fnrl=Funeral 39 | grad=Graduation 40 | hair=Hair 41 | heig=Height 42 | ill=Illness 43 | immi=Immigration 44 | marb=Marriage banns 45 | marc=Marriage contract 46 | marl=Marriage license 47 | marr=Marriage 48 | mars=Marriage settlement 49 | mdcl=Medical 50 | milt=Military 51 | misn=Mission 52 | nams=Namesake 53 | nati=Nationality 54 | natu=Naturalization 55 | nchi=Number of children 56 | occu=Occupation 57 | ordn=Ordination 58 | other=Other 59 | phon=Phone 60 | prob=Probate 61 | prop=Property 62 | reli=Religion 63 | resi=Residence 64 | reti=Retirement 65 | sepa=Separated 66 | sex=Sex 67 | ssn=Social security number 68 | titl=Title 69 | weig=Weight 70 | will=Will 71 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/MediaRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: dallan 21 | * Date: 1/7/12 22 | */ 23 | public class MediaRef extends ExtensionContainer { 24 | private String ref = null; 25 | 26 | public String getRef() { 27 | return ref; 28 | } 29 | 30 | public void setRef(String ref) { 31 | this.ref = ref; 32 | } 33 | 34 | /** 35 | * Convenience function to dereference media 36 | * @param gedcom Gedcom 37 | * @return referenced media 38 | */ 39 | public Media getMedia(Gedcom gedcom) { 40 | return gedcom.getMedia(ref); 41 | } 42 | 43 | public void accept(Visitor visitor) { 44 | if (visitor.visit(this)) { 45 | super.visitContainedObjects(visitor); 46 | visitor.endVisit(this); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/resources/EventFact_it.properties: -------------------------------------------------------------------------------- 1 | adop=Adozione 2 | afn=Numero Ancestral File 3 | anul=Annullamento 4 | arvl=Arrivo 5 | attr=Attributo 6 | bapm=Battesimo 7 | barm=Bar mitzvah 8 | batm=Bat mitzvah 9 | birt=Nascita 10 | bles=Benedizione 11 | buri=Sepoltura 12 | cast=Casta 13 | caus=Causa di morte 14 | cens=Censimento 15 | chr=Battesimo 16 | claw=Unione di fatto 17 | color=Colore 18 | conf=Cresima 19 | crem=Cremazione 20 | deat=Morte 21 | death_of_spouse=Morte del coniuge 22 | deed=Atto 23 | deg=Diploma 24 | div=Divorzio 25 | divf=Richiesta di divorzio 26 | dprt=Partenza 27 | dscr=Descrizione fisica 28 | educ=Educazione 29 | elec=Eletto 30 | email=Email 31 | emig=Emigrazione 32 | empl=Impiego 33 | enga=Fidanzamento 34 | even=Evento 35 | excm=Scomunica 36 | eyes=Occhi 37 | fcom=Prima comunione 38 | fnrl=Funerale 39 | grad=Laurea 40 | hair=Capelli 41 | heig=Altezza 42 | ill=Malattia 43 | immi=Immigrazione 44 | marb=Pubblicazioni di matrimonio 45 | marc=Contratto di matrimonio 46 | marl=Licenza di matrimonio 47 | marr=Matrimonio 48 | mars=Accordo prematrimoniale 49 | mdcl=Visita medica 50 | milt=Militare 51 | misn=Missione 52 | nams=Omonimo 53 | nati=Nazionalit\u00E0 54 | natu=Naturalizzazione 55 | nchi=Numero di figli 56 | occu=Occupazione 57 | ordn=Ordinazione 58 | other=Altro 59 | phon=Telefono 60 | prob=Omologazione 61 | prop=Propriet\u00E0 62 | reli=Religione 63 | resi=Residenza 64 | reti=Pensionamento 65 | sepa=Separati 66 | sex=Sesso 67 | ssn=Numero di previdenza sociale 68 | titl=Titolo 69 | weig=Peso 70 | will=Testamento 71 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/LdsOrdinance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | */ 23 | public class LdsOrdinance extends EventFact { 24 | private String stat = null; 25 | private String temp = null; 26 | 27 | public String getStatus() { 28 | return stat; 29 | } 30 | 31 | public void setStatus(String stat) { 32 | this.stat = stat; 33 | } 34 | 35 | public String getTemple() { 36 | return temp; 37 | } 38 | 39 | public void setTemple(String temp) { 40 | this.temp = temp; 41 | } 42 | 43 | public void accept(Visitor visitor) { 44 | if (visitor.visit(this)) { 45 | super.visitContainedObjects(visitor); 46 | visitor.endVisit(this); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/resources/Case002-ReferenceIntegrity.ged: -------------------------------------------------------------------------------- 1 | 0 HEAD 2 | 1 GEDC 3 | 2 VERS 5.5.5 4 | 2 FORM LINEAGE-LINKED 5 | 3 VERS 5.5.5 6 | 1 CHAR UTF-8 7 | 1 SOUR gedcom.org 8 | 2 NAME The GEDCOM Site 9 | 2 VERS 5.5.5 10 | 2 CORP gedcom.org 11 | 3 ADDR 12 | 4 CITY LEIDEN 13 | 3 WWW www.gedcom.org 14 | 1 DATE 2 Oct 2019 15 | 2 TIME 0:00:00 16 | 1 FILE REMARR.GED 17 | 1 LANG English 18 | 1 SUBM @U1@ 19 | 0 @U1@ SUBM 20 | 1 NAME gedcom.org 21 | 1 ADDR 22 | 2 CITY Leiden 23 | 1 WWW www.gedcom.org 24 | 0 @I1@ INDI 25 | 1 NAME Peter /Sweet/ 26 | 2 SURN Sweet 27 | 2 GIVN Peter 28 | 1 SEX M 29 | 1 BIRT 30 | 2 DATE 7 Jul 1877 31 | 1 FAMS @F1@ 32 | 1 FAMS @F3@ 33 | 0 @I2@ INDI 34 | 1 NAME Mary /Encore/ 35 | 2 SURN Encore 36 | 2 GIVN Mary 37 | 1 SEX F 38 | 1 BIRT 39 | 2 DATE 4 May 1876 40 | 1 FAMS @F1@ 41 | 1 FAMS @F3@ 42 | 0 @I3@ INDI 43 | 1 NAME Juan /Donalds/ 44 | 2 SURN Donalds 45 | 2 GIVN Juan 46 | 1 SEX M 47 | 1 BIRT 48 | 2 DATE 8 Aug 1888 49 | 1 FAMS @F2@ 50 | 0 @I4@ INDI 51 | 1 NAME Juan /Donalds/ 52 | 2 SURN Donalds 53 | 2 GIVN Juan 54 | 1 SEX M 55 | 1 FAMC @F2@ 56 | 0 @F1@ FAM 57 | 1 MARR 58 | 2 DATE 1 Jan 1900 59 | 2 PLAC Amsterdam, Noord-Holland, Netherlands 60 | 1 DIV 61 | 2 DATE 10 Oct 1910 62 | 2 PLAC Amsterdam, Noord-Holland, Netherlands 63 | 0 @F2@ FAM 64 | 1 WIFE @I2@ 65 | 1 MARR 66 | 2 DATE 11 Nov 1911 67 | 2 PLAC Amsterdam, Noord-Holland, Netherlands 68 | 1 DIV 69 | 2 DATE 12 Dec 1912 70 | 2 PLAC Amsterdam, Noord-Holland, Netherlands 71 | 0 @F3@ FAM 72 | 1 MARR 73 | 2 DATE 1 Jan 1912 74 | 2 PLAC Amsterdam, Noord-Holland, Netherlands 75 | 0 TRLR -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/GedcomVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/25/11 22 | */ 23 | public class GedcomVersion extends ExtensionContainer { 24 | private String vers = null; 25 | private String form = null; 26 | 27 | public String getVersion() { 28 | return vers; 29 | } 30 | 31 | public void setVersion(String vers) { 32 | this.vers = vers; 33 | } 34 | 35 | public String getForm() { 36 | return form; 37 | } 38 | 39 | public void setForm(String form) { 40 | this.form = form; 41 | } 42 | 43 | public void accept(Visitor visitor) { 44 | if (visitor.visit(this)) { 45 | super.visitContainedObjects(visitor); 46 | visitor.endVisit(this); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/CharacterSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/26/11 22 | */ 23 | public class CharacterSet extends ExtensionContainer { 24 | private String value = null; 25 | private String vers = null; 26 | 27 | public String getValue() { 28 | return value; 29 | } 30 | 31 | public void setValue(String value) { 32 | this.value = value; 33 | } 34 | 35 | public String getVersion() { 36 | return vers; 37 | } 38 | 39 | public void setVersion(String vers) { 40 | this.vers = vers; 41 | } 42 | 43 | public void accept(Visitor visitor) { 44 | if (visitor.visit(this)) { 45 | super.visitContainedObjects(visitor); 46 | visitor.endVisit(this); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/DateTime.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/26/11 22 | */ 23 | public class DateTime extends ExtensionContainer { 24 | private String value = null; 25 | private String time = null; 26 | 27 | public String getValue() { 28 | return value; 29 | } 30 | 31 | public void setValue(String value) { 32 | this.value = value; 33 | } 34 | 35 | public String getTime() { 36 | return time; 37 | } 38 | 39 | public void setTime(String time) { 40 | this.time = time; 41 | } 42 | 43 | @Override 44 | public void accept(Visitor visitor) { 45 | if (visitor.visit(this)) { 46 | super.visitContainedObjects(visitor); 47 | visitor.endVisit(this); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/SpouseFamilyRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/28/11 22 | */ 23 | public class SpouseFamilyRef extends ExtensionContainer { 24 | private String ref; 25 | 26 | public String getRef() { 27 | return ref; 28 | } 29 | 30 | public void setRef(String ref) { 31 | this.ref = ref; 32 | } 33 | 34 | /** 35 | * Convenience function to dereference family 36 | * @param gedcom Gedcom 37 | * @return referenced family 38 | */ 39 | public Family getFamily(Gedcom gedcom) { 40 | return gedcom.getFamily(ref); 41 | } 42 | 43 | public void accept(Visitor visitor) { 44 | if (visitor.visit(this)) { 45 | super.visitContainedObjects(visitor); 46 | visitor.endVisit(this); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/ParentFamilyRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/28/11 22 | * 23 | * add: primary 24 | */ 25 | public class ParentFamilyRef extends SpouseFamilyRef { 26 | private String pedi; 27 | private String _primary; 28 | 29 | public String getRelationshipType() { 30 | return pedi; 31 | } 32 | 33 | public void setRelationshipType(String pedi) { 34 | this.pedi = pedi; 35 | } 36 | 37 | public String getPrimary() { 38 | return _primary; 39 | } 40 | 41 | public void setPrimary(String primary) { 42 | this._primary = primary; 43 | } 44 | 45 | public void accept(Visitor visitor) { 46 | if (visitor.visit(this)) { 47 | super.visitContainedObjects(visitor); 48 | visitor.endVisit(this); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/ParentRelationship.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | * 23 | * add: Notes and Media, which aren't seen in gedcoms in the wild 24 | */ 25 | public class ParentRelationship extends SourceCitationContainer { 26 | private String value = null; 27 | 28 | public String getValue() { 29 | return value; 30 | } 31 | 32 | public void setValue(String value) { 33 | this.value = value; 34 | } 35 | 36 | public void accept(Visitor visitor) { 37 | throw new RuntimeException("Not implemented - pass isFather"); 38 | } 39 | 40 | public void accept(Visitor visitor, boolean isFather) { 41 | if (visitor.visit(this, isFather)) { 42 | super.visitContainedObjects(visitor); 43 | visitor.endVisit(this); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/gedml/GedcomLineParser.java: -------------------------------------------------------------------------------- 1 | package org.gedml; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | * User: npowell 8 | * Date: May 2, 2007 9 | */ 10 | public class GedcomLineParser { 11 | private static final Pattern pGedcomLine = Pattern.compile( 12 | "^\\s*(\\d)\\s+(@([^@ ]+)@\\s+)?([a-zA-Z_0-9.]+)(\\s+@([^@ ]+)@)?(\\s(.*))?$", Pattern.DOTALL); // DOTALL for unicode line separator 13 | 14 | private static final int LEVEL_GROUP = 1; 15 | private static final int ID_GROUP = 3; 16 | private static final int TAG_GROUP = 4; 17 | private static final int XREF_GROUP = 6; 18 | private static final int VALUE_GROUP = 8; 19 | 20 | private Matcher m = null; 21 | 22 | public boolean parse(String line) { 23 | m = pGedcomLine.matcher(line); 24 | return m.find(); 25 | } 26 | 27 | public String getLevel() { 28 | return m.group(LEVEL_GROUP); 29 | } 30 | 31 | public String getXRef() { 32 | return m.group(XREF_GROUP); 33 | } 34 | 35 | public String getID() { 36 | return m.group(ID_GROUP); 37 | // TODO - necessary? 38 | // String returnValue = m.group(AFTER_ID_GROUP); 39 | // if (returnValue == null || returnValue.length() == 0) { 40 | // return returnValue; 41 | // } else { 42 | // return returnValue.replaceAll("[|#/]+", ""); 43 | // } 44 | } 45 | 46 | public String getTag() { 47 | return m.group(TAG_GROUP); 48 | } 49 | 50 | public String getValue() { 51 | return m.group(VALUE_GROUP); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/GeneratorData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/26/11 22 | */ 23 | public class GeneratorData extends ExtensionContainer { 24 | private String value = null; 25 | private String date = null; 26 | private String copr = null; 27 | 28 | public String getValue() { 29 | return value; 30 | } 31 | 32 | public void setValue(String value) { 33 | this.value = value; 34 | } 35 | 36 | public String getDate() { 37 | return date; 38 | } 39 | 40 | public void setDate(String date) { 41 | this.date = date; 42 | } 43 | 44 | public String getCopyright() { 45 | return copr; 46 | } 47 | 48 | public void setCopyright(String copr) { 49 | this.copr = copr; 50 | } 51 | 52 | public void accept(Visitor visitor) { 53 | if (visitor.visit(this)) { 54 | super.visitContainedObjects(visitor); 55 | visitor.endVisit(this); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Association.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: dallan 21 | * Date: 1/3/12 22 | */ 23 | public class Association extends ExtensionContainer { 24 | private String ref = null; 25 | private String type = null; 26 | private String rela = null; 27 | 28 | public String getRef() { 29 | return ref; 30 | } 31 | 32 | public void setRef(String ref) { 33 | this.ref = ref; 34 | } 35 | 36 | public Person getPerson(Gedcom gedcom) { 37 | return gedcom.getPerson(ref); 38 | } 39 | 40 | public String getType() { 41 | return type; 42 | } 43 | 44 | public void setType(String type) { 45 | this.type = type; 46 | } 47 | 48 | public String getRelation() { 49 | return rela; 50 | } 51 | 52 | public void setRelation(String rela) { 53 | this.rela = rela; 54 | } 55 | 56 | public void accept(Visitor visitor) { 57 | if (visitor.visit(this)) { 58 | super.visitContainedObjects(visitor); 59 | visitor.endVisit(this); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Extensions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import java.util.Set; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/18/11 26 | * 27 | * Make Extensions a class so we can use an ExtensionsTypeAdapter with Gson 28 | */ 29 | public class Extensions { 30 | private Map extensions; 31 | 32 | public Extensions() { 33 | extensions = new HashMap(); 34 | } 35 | 36 | public Map getExtensions() { 37 | return extensions; 38 | } 39 | 40 | public void setExtensions(Map extensions) { 41 | this.extensions = extensions; 42 | } 43 | 44 | public Object get(String key) { 45 | return extensions.get(key); 46 | } 47 | 48 | public void put(String key, Object extension) { 49 | extensions.put(key, extension); 50 | } 51 | 52 | public Set getKeys() { 53 | return extensions.keySet(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Submission.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | * 23 | * omit: submitter, famf, temp, ance, rin 24 | */ 25 | public class Submission extends ExtensionContainer { 26 | private String id = null; 27 | private String desc = null; 28 | private String ordi = null; 29 | 30 | public String getId() { 31 | return id; 32 | } 33 | 34 | public void setId(String id) { 35 | this.id = id; 36 | } 37 | 38 | public String getDescription() { 39 | return desc; 40 | } 41 | 42 | public void setDescription(String desc) { 43 | this.desc = desc; 44 | } 45 | 46 | public String getOrdinanceFlag() { 47 | return ordi; 48 | } 49 | 50 | public void setOrdinanceFlag(String ordi) { 51 | this.ordi = ordi; 52 | } 53 | 54 | public void accept(Visitor visitor) { 55 | if (visitor.visit(this)) { 56 | super.visitContainedObjects(visitor); 57 | visitor.endVisit(this); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /doc/jackson.txt: -------------------------------------------------------------------------------- 1 | NOTES ON USING JACKSON 2 | 3 | It's possible to use jackson instead of gson, but gson is more convenient, because 4 | jackson uses getter methods instead of fields, and we have a number of convenience 5 | getter functions that we would have to tell jackson to ignore. 6 | 7 | Here's a simple code snippet demonstrating jackson: 8 | 9 | ObjectMapper mapper = new ObjectMapper(); 10 | mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); 11 | .configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false); 12 | SimpleModule myModule = new SimpleModule("MyModule", new Version(1, 0, 0, null)) 13 | .addDeserializer(Extensions.class, new ExtensionsDeserializer()); 14 | mapper.registerModule(myModule); 15 | String json = mapper.writeValueAsString(gedcom); 16 | Gedcom gedcom = mapper.readValue(json, Gedcom.class); 17 | 18 | public class ExtensionsDeserializer extends JsonDeserializer { 19 | @Override 20 | @SuppressWarnings("unchecked") 21 | public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 22 | ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec(); 23 | ObjectNode root = (ObjectNode) mapper.readTree(jsonParser); 24 | Extensions extensions = new Extensions(); 25 | Iterator> iter = root.getFields(); 26 | while (iter.hasNext()) { 27 | Map.Entry entry = iter.next(); 28 | Class clazz = ... 29 | if (clazz != null) { 30 | extensions.put(key, mapper.readValue(entry.getValue(), clazz)); 31 | } 32 | else { 33 | extensions.put(key, entry.getValue()); 34 | } 35 | } 36 | return extensions; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/ChildRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | * 23 | * add: FatherRelationship, MotherRelationship 24 | */ 25 | public class ChildRef extends SpouseRef { 26 | private ParentRelationship _frel = null; 27 | private ParentRelationship _mrel = null; 28 | 29 | public ParentRelationship getFatherRelationship() { 30 | return _frel; 31 | } 32 | 33 | public void setFatherRelationship(ParentRelationship frel) { 34 | this._frel = frel; 35 | } 36 | 37 | public ParentRelationship getMotherRelationship() { 38 | return _mrel; 39 | } 40 | 41 | public void setMotherRelationship(ParentRelationship mrel) { 42 | this._mrel = mrel; 43 | } 44 | 45 | public void accept(Visitor visitor) { 46 | if (visitor.visit(this)) { 47 | if (_frel != null) { 48 | _frel.accept(visitor, true); 49 | } 50 | if (_mrel != null) { 51 | _mrel.accept(visitor, false); 52 | } 53 | super.visitContainedObjects(visitor); 54 | visitor.endVisit(this); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/SourceCitationContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/29/11 26 | */ 27 | public abstract class SourceCitationContainer extends MediaContainer { 28 | private List sourceCitations = null; 29 | 30 | public List getSourceCitations() { 31 | return sourceCitations != null ? sourceCitations : Collections.emptyList(); 32 | } 33 | 34 | public void setSourceCitations(List sourceCitations) { 35 | this.sourceCitations = sourceCitations; 36 | } 37 | 38 | public void addSourceCitation(SourceCitation sourceCitation) { 39 | if (sourceCitations == null) { 40 | sourceCitations = new ArrayList(); 41 | } 42 | sourceCitations.add(sourceCitation); 43 | } 44 | 45 | public void visitContainedObjects(Visitor visitor) { 46 | for (SourceCitation sourceCitation : getSourceCitations()) { 47 | sourceCitation.accept(visitor); 48 | } 49 | super.visitContainedObjects(visitor); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/SpouseRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | */ 23 | public class SpouseRef extends ExtensionContainer { 24 | private String ref = null; 25 | private String _pref = null; 26 | 27 | public String getRef() { 28 | return ref; 29 | } 30 | 31 | public void setRef(String ref) { 32 | this.ref = ref; 33 | } 34 | 35 | /** 36 | * Convenience function to dereference person 37 | * @param gedcom Gedcom 38 | * @return referenced person 39 | */ 40 | public Person getPerson(Gedcom gedcom) { 41 | return gedcom.getPerson(ref); 42 | } 43 | 44 | public String getPreferred() { 45 | return _pref; 46 | } 47 | 48 | public void setPreferred(String pref) { 49 | this._pref = pref; 50 | } 51 | 52 | public void accept(Visitor visitor) { 53 | throw new RuntimeException("Not implemented - pass isHusband"); 54 | } 55 | 56 | /** 57 | * Handle the visitor 58 | * @param visitor Visitor 59 | * @param isHusband false for wife; ChildRef overrides this method 60 | */ 61 | public void accept(Visitor visitor, boolean isHusband) { 62 | if (visitor.visit(this, isHusband)) { 63 | super.visitContainedObjects(visitor); 64 | visitor.endVisit(this); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/ExtensionContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.Collections; 20 | import java.util.Map; 21 | 22 | /** 23 | * User: Dallan 24 | * Date: 12/25/11 25 | */ 26 | public abstract class ExtensionContainer implements Visitable { 27 | private Extensions extensions = null; 28 | 29 | public Map getExtensions() { 30 | return extensions != null ? extensions.getExtensions() : Collections.emptyMap(); 31 | } 32 | 33 | public Object getExtension(String key) { 34 | return extensions != null ? extensions.get(key) : null; 35 | } 36 | 37 | public void setExtensions(Map exts) { 38 | if (exts != null && exts.size() > 0) { 39 | if (extensions == null) { 40 | extensions = new Extensions(); 41 | } 42 | extensions.setExtensions(exts); 43 | } 44 | else { 45 | extensions = null; 46 | } 47 | } 48 | 49 | public void putExtension(String id, Object extension) { 50 | if (extensions == null) { 51 | extensions = new Extensions(); 52 | } 53 | extensions.put(id, extension); 54 | } 55 | 56 | public void visitContainedObjects(Visitor visitor) { 57 | for (Map.Entry entry : getExtensions().entrySet()) { 58 | visitor.visit(entry.getKey(), entry.getValue()); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/tools/PlaceWriter.java: -------------------------------------------------------------------------------- 1 | package org.folg.gedcom.tools; 2 | 3 | import org.folg.gedcom.model.*; 4 | import org.folg.gedcom.parser.ModelParser; 5 | import org.kohsuke.args4j.CmdLineException; 6 | import org.kohsuke.args4j.CmdLineParser; 7 | import org.kohsuke.args4j.Option; 8 | import org.xml.sax.SAXParseException; 9 | 10 | import java.io.*; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | /** 15 | * User: dallan 16 | * Date: 1/7/12 17 | */ 18 | public class PlaceWriter extends Visitor { 19 | private static final Logger logger = LoggerFactory.getLogger("org.folg.gedcom.tools"); 20 | 21 | @Option(name="-i", required=true, usage="file or directory containing gedcom files to process") 22 | private File gedcomIn; 23 | 24 | @Option(name="-o", required=true, usage="target file for places") 25 | private File placesOut; 26 | 27 | private ModelParser parser; 28 | private PrintWriter out; 29 | 30 | public PlaceWriter() { 31 | parser = new ModelParser(); 32 | } 33 | 34 | @Override 35 | public boolean visit(EventFact eventFact) { 36 | String place = eventFact.getPlace(); 37 | if (place != null && place.length() > 0) { 38 | out.println(place); 39 | } 40 | return true; 41 | } 42 | 43 | public void processGedcom(File file) throws SAXParseException, IOException { 44 | Gedcom gedcom = parser.parseGedcom(file); 45 | gedcom.accept(this); 46 | } 47 | 48 | private void doMain() throws IOException, SAXParseException { 49 | out = new PrintWriter(new FileWriter(placesOut)); 50 | if (gedcomIn.isDirectory()) { 51 | for (File file : gedcomIn.listFiles()) { 52 | processGedcom(file); 53 | } 54 | } 55 | else if (gedcomIn.isFile()) { 56 | processGedcom(gedcomIn); 57 | } 58 | out.close(); 59 | } 60 | 61 | public static void main(String[] args) throws IOException, SAXParseException { 62 | PlaceWriter self = new PlaceWriter(); 63 | CmdLineParser parser = new CmdLineParser(self); 64 | try { 65 | parser.parseArgument(args); 66 | self.doMain(); 67 | } 68 | catch (CmdLineException e) { 69 | System.err.println(e.getMessage()); 70 | parser.printUsage(System.err); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/resources/Case001-AddressStructure.ged: -------------------------------------------------------------------------------- 1 | 0 HEAD 2 | 1 SOUR PAF 3 | 2 NAME MyCorporation Gedcom Generator 4 | 2 VERS 5.2.18.0 5 | 2 CORP MyCorporation, Inc. 6 | 3 ADDR 5000 MyCorpCampus Dr 7 | 4 CONT Hometown, ZZ 99999 8 | 4 CONT United States 9 | 4 ADR1 __ADR1_VALUE__ 10 | 4 ADR2 __ADR2_VALUE__ 11 | 4 ADR3 5000 MyCorpCampus Dr 12 | 4 CITY Hometown 13 | 4 STAE ZZ 14 | 4 POST 99999 15 | 4 CTRY United States 16 | 3 PHON 866-000-0000 17 | 3 EMAIL info@mycorporation.com 18 | 3 FAX 866-111-1111 19 | 3 WWW http://www.mycorporation.org/ 20 | 1 DATE 12 Dec 2012 21 | 2 TIME 12:12:12 22 | 1 GEDC 23 | 2 VERS 5.5 24 | 2 FORM LINEAGE-LINKED 25 | 1 CHAR UTF-8 26 | 1 SUBM @SUB1@ 27 | 0 @SUB1@ SUBM 28 | 1 NAME MyCorporation, Inc. 29 | 1 ADDR 5000 MyCorpCampus Dr 30 | 2 CONT Hometown, ZZ 99999 31 | 2 CONT United States 32 | 2 ADR1 __ADR1_VALUE__ 33 | 2 ADR2 __ADR2_VALUE__ 34 | 2 ADR3 5000 MyCorpCampus Dr 35 | 2 CITY Hometown 36 | 2 STAE ZZ 37 | 2 POST 99999 38 | 2 CTRY United States 39 | 1 PHON 866-000-0000 40 | 1 EMAIL info@mycorporation.com 41 | 1 FAX 866-111-1111 42 | 1 WWW http://www.mycorporation.org/ 43 | 0 @I1@ INDI 44 | 1 NAME MyGiven1 MyGiven2 /MySurname/ IV 45 | 1 BURI 46 | 2 ADDR Arlington National Cemetery 47 | 3 CONT State Hwy 110 & Memorial Dr 48 | 3 CONT Arlington, VA 22211 49 | 3 CONT United States 50 | 3 ADR1 __ADR1_VALUE__ 51 | 3 ADR2 __ADR2_VALUE__ 52 | 3 ADR3 __ADR3_VALUE__ 53 | 3 CITY Arlington 54 | 3 STAE VA 55 | 3 POST 22211 56 | 3 CTRY United States 57 | 2 PHON 877-907-8585 58 | 2 EMAIL info@arlingtoncemetery.mil 59 | 2 FAX 877-111-1111 60 | 2 WWW http://www.arlingtoncemetery.mil/ 61 | 1 ADDR 5000 MyCorpCampus Dr 62 | 2 CONT Hometown, ZZ 99999 63 | 2 CONT United States 64 | 2 ADR1 __ADR1_VALUE__ 65 | 2 ADR2 __ADR2_VALUE__ 66 | 2 ADR3 5000 MyCorpCampus Dr 67 | 2 CITY Hometown 68 | 2 STAE ZZ 69 | 2 POST 99999 70 | 2 CTRY United States 71 | 1 PHON 866-000-0000 72 | 1 EMAIL info@mycorporation.com 73 | 1 FAX 866-111-1111 74 | 1 WWW http://www.mycorporation.org/ 75 | 0 @REPO3@ REPO 76 | 1 NAME MyCorporation, Inc. 77 | 1 ADDR 5000 MyCorpCampus Dr 78 | 2 CONT Hometown, ZZ 99999 79 | 2 CONT United States 80 | 2 ADR1 __ADR1_VALUE__ 81 | 2 ADR2 __ADR2_VALUE__ 82 | 2 ADR3 5000 MyCorpCampus Dr 83 | 2 CITY Hometown 84 | 2 STAE ZZ 85 | 2 POST 99999 86 | 2 CTRY United States 87 | 1 PHON 866-000-0000 88 | 1 EMAIL info@mycorporation.com 89 | 1 FAX 866-111-1111 90 | 1 WWW https://www.mycorporation.com/ 91 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Generator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/25/11 22 | */ 23 | public class Generator extends ExtensionContainer { 24 | private String value = null; 25 | private String name = null; 26 | private String vers = null; 27 | private GeneratorCorporation corp = null; 28 | private GeneratorData data = null; 29 | 30 | public String getValue() { 31 | return value; 32 | } 33 | 34 | public void setValue(String value) { 35 | this.value = value; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | 46 | public String getVersion() { 47 | return vers; 48 | } 49 | 50 | public void setVersion(String vers) { 51 | this.vers = vers; 52 | } 53 | 54 | public GeneratorCorporation getGeneratorCorporation() { 55 | return corp; 56 | } 57 | 58 | public void setGeneratorCorporation(GeneratorCorporation corp) { 59 | this.corp = corp; 60 | } 61 | 62 | public GeneratorData getGeneratorData() { 63 | return data; 64 | } 65 | 66 | public void setGeneratorData(GeneratorData data) { 67 | this.data = data; 68 | } 69 | 70 | public void accept(Visitor visitor) { 71 | if (visitor.visit(this)) { 72 | if (corp != null) { 73 | corp.accept(visitor); 74 | } 75 | if (data != null) { 76 | data.accept(visitor); 77 | } 78 | super.visitContainedObjects(visitor); 79 | visitor.endVisit(this); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/NoteRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: dallan 25 | * Date: 1/3/12 26 | * don't make this a SourceCitationContainer, because that would allow notes within note refs 27 | */ 28 | public class NoteRef extends ExtensionContainer { 29 | private String ref = null; 30 | private List sourceCitations = null; 31 | 32 | public String getRef() { 33 | return ref; 34 | } 35 | 36 | public void setRef(String ref) { 37 | this.ref = ref; 38 | } 39 | 40 | /** 41 | * Convenience function to dereference note 42 | * @param gedcom Gedcom 43 | * @return referenced note 44 | */ 45 | public Note getNote(Gedcom gedcom) { 46 | return gedcom.getNote(ref); 47 | } 48 | 49 | public List getSourceCitations() { 50 | return sourceCitations != null ? sourceCitations : Collections.emptyList(); 51 | } 52 | 53 | public void setSourceCitations(List sourceCitations) { 54 | this.sourceCitations = sourceCitations; 55 | } 56 | 57 | public void addSourceCitation(SourceCitation sourceCitation) { 58 | if (sourceCitations == null) { 59 | sourceCitations = new ArrayList(); 60 | } 61 | sourceCitations.add(sourceCitation); 62 | } 63 | 64 | public void accept(Visitor visitor) { 65 | if (visitor.visit(this)) { 66 | for (SourceCitation sourceCitation : getSourceCitations()) { 67 | sourceCitation.accept(visitor); 68 | } 69 | super.visitContainedObjects(visitor); 70 | visitor.endVisit(this); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/parser/GedcomTypeAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.parser; 18 | 19 | import com.google.gson.*; 20 | import com.google.gson.reflect.TypeToken; 21 | import org.folg.gedcom.model.Extensions; 22 | import org.folg.gedcom.model.Gedcom; 23 | import org.folg.gedcom.model.GedcomTag; 24 | 25 | import java.lang.reflect.Type; 26 | import java.util.List; 27 | 28 | /** 29 | * User: Dallan 30 | * Date: 12/31/11 31 | */ 32 | public class GedcomTypeAdapter implements JsonSerializer, JsonDeserializer { 33 | 34 | private Gson gson; 35 | private ExtensionsTypeAdapter extensionsTypeAdapter; 36 | 37 | public GedcomTypeAdapter() { 38 | extensionsTypeAdapter = new ExtensionsTypeAdapter(); 39 | // built-in extension 40 | extensionsTypeAdapter.registerExtension(ModelParser.MORE_TAGS_EXTENSION_KEY, new TypeToken>(){}.getType()); 41 | gson = new GsonBuilder() 42 | .registerTypeAdapter(Extensions.class, extensionsTypeAdapter) 43 | .create(); 44 | } 45 | 46 | public void registerExtension(String extensionKey, Class clazz) { 47 | extensionsTypeAdapter.registerExtension(extensionKey, clazz); 48 | } 49 | 50 | public void registerExtension(String extensionKey, Type type) { 51 | extensionsTypeAdapter.registerExtension(extensionKey, type); 52 | } 53 | 54 | public JsonElement serialize(Gedcom src, Type typeOfSrc, JsonSerializationContext context) { 55 | return gson.toJsonTree(src); 56 | } 57 | 58 | public Gedcom deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 59 | Gedcom gedcom = gson.fromJson(json, Gedcom.class); 60 | gedcom.createIndexes(); 61 | return gedcom; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/RepositoryRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/30/11 22 | * 23 | * omit: multiple call numbers 24 | * add: value (a few sources inline the repo name as a value) 25 | * move: media type from under call number to directly under repository ref 26 | */ 27 | public class RepositoryRef extends NoteContainer { 28 | private String ref = null; 29 | private String value = null; 30 | private String caln = null; 31 | private String medi = null; 32 | private String isMediUnderCalnTag = null; // use string instead of boolean so it isn't saved to json when false 33 | 34 | public String getRef() { 35 | return ref; 36 | } 37 | 38 | public void setRef(String ref) { 39 | this.ref = ref; 40 | } 41 | 42 | public String getValue() { 43 | return value; 44 | } 45 | 46 | public void setValue(String value) { 47 | this.value = value; 48 | } 49 | 50 | public Repository getRepository(Gedcom gedcom) { 51 | return gedcom.getRepository(ref); 52 | } 53 | 54 | public String getCallNumber() { 55 | return caln; 56 | } 57 | 58 | public void setCallNumber(String caln) { 59 | this.caln = caln; 60 | } 61 | 62 | public String getMediaType() { 63 | return medi; 64 | } 65 | 66 | public void setMediaType(String medi) { 67 | this.medi = medi; 68 | } 69 | 70 | public boolean isMediUnderCalnTag() { 71 | return this.isMediUnderCalnTag != null; 72 | } 73 | 74 | public void setMediUnderCalnTag(boolean mediUnderCalnTag) { 75 | this.isMediUnderCalnTag = (mediUnderCalnTag ? "true" : null); 76 | } 77 | 78 | public void accept(Visitor visitor) { 79 | if (visitor.visit(this)) { 80 | super.visitContainedObjects(visitor); 81 | visitor.endVisit(this); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/test/java/org/folg/gedcom/parser/TreeParserTest.java: -------------------------------------------------------------------------------- 1 | package org.folg.gedcom.parser; 2 | 3 | import org.folg.gedcom.model.GedcomTag; 4 | import org.testng.annotations.Test; 5 | 6 | import java.io.File; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | import java.io.Reader; 10 | import java.net.URL; 11 | import java.util.List; 12 | 13 | import static org.testng.Assert.assertEquals; 14 | import static org.testng.Assert.assertNotNull; 15 | 16 | public class TreeParserTest { 17 | 18 | @Test 19 | public void testParse_withFile() throws Exception { 20 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case001-AddressStructure.ged"); 21 | File gedcomFile = new File(gedcomUrl.toURI()); 22 | TreeParser treeParser = new TreeParser(); 23 | 24 | List gedcomTags = treeParser.parseGedcom(gedcomFile); 25 | assertNotNull(gedcomTags); 26 | assertEquals(4, gedcomTags.size()); 27 | 28 | GedcomTag headTag = gedcomTags.get(0); 29 | assertNotNull(headTag); 30 | assertEquals("HEAD", headTag.getTag()); 31 | 32 | GedcomTag submissionTag = gedcomTags.get(1); 33 | assertNotNull(submissionTag); 34 | assertEquals("SUBM", submissionTag.getTag()); 35 | 36 | GedcomTag individualTag = gedcomTags.get(2); 37 | assertNotNull(individualTag); 38 | assertEquals("INDI", individualTag.getTag()); 39 | 40 | GedcomTag repoTag = gedcomTags.get(3); 41 | assertNotNull(repoTag); 42 | assertEquals("REPO", repoTag.getTag()); 43 | } 44 | 45 | @Test 46 | public void testParse_withInputStream() throws Exception { 47 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case001-AddressStructure.ged"); 48 | TreeParser treeParser = new TreeParser(); 49 | 50 | InputStream is = gedcomUrl.openStream(); 51 | assertNotNull(is); 52 | 53 | List gedcomTags = treeParser.parseGedcom(is); 54 | assertNotNull(gedcomTags); 55 | assertEquals(4, gedcomTags.size()); 56 | } 57 | 58 | @Test 59 | public void testParse_withReader() throws Exception { 60 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case001-AddressStructure.ged"); 61 | TreeParser treeParser = new TreeParser(); 62 | 63 | InputStream is = gedcomUrl.openStream(); 64 | assertNotNull(is); 65 | 66 | Reader reader = new InputStreamReader(is, "UTF-8"); 67 | 68 | List gedcomTags = treeParser.parseGedcom(reader); 69 | assertNotNull(gedcomTags); 70 | assertEquals(4, gedcomTags.size()); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/NoteContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/29/11 26 | */ 27 | public abstract class NoteContainer extends ExtensionContainer { 28 | private List noteRefs = null; 29 | private List notes = null; 30 | 31 | /** 32 | * Use this function in place of getNotes and getNoteRefs 33 | * @param gedcom Gedcom 34 | * @return inline notes as well as referenced notes 35 | */ 36 | public List getAllNotes(Gedcom gedcom) { 37 | List notes = new ArrayList(); 38 | for (NoteRef noteRef : getNoteRefs()) { 39 | Note note = noteRef.getNote(gedcom); 40 | if (note != null) { 41 | notes.add(note); 42 | } 43 | } 44 | notes.addAll(getNotes()); 45 | return notes; 46 | } 47 | 48 | public List getNoteRefs() { 49 | return noteRefs != null ? noteRefs : Collections.emptyList(); 50 | } 51 | 52 | public void setNoteRefs(List noteRefs) { 53 | this.noteRefs = noteRefs; 54 | } 55 | 56 | public void addNoteRef(NoteRef noteRef) { 57 | if (noteRefs == null) { 58 | noteRefs = new ArrayList(); 59 | } 60 | noteRefs.add(noteRef); 61 | } 62 | 63 | public List getNotes() { 64 | return notes != null ? notes : Collections.emptyList(); 65 | } 66 | 67 | public void setNotes(List notes) { 68 | this.notes = notes; 69 | } 70 | 71 | public void addNote(Note note) { 72 | if (notes == null) { 73 | notes = new ArrayList(); 74 | } 75 | notes.add(note); 76 | } 77 | 78 | public void visitContainedObjects(Visitor visitor) { 79 | for (NoteRef noteRef : getNoteRefs()) { 80 | noteRef.accept(visitor); 81 | } 82 | for (Note note : getNotes()) { 83 | note.accept(visitor); 84 | } 85 | super.visitContainedObjects(visitor); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/MediaContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/30/11 26 | */ 27 | public abstract class MediaContainer extends NoteContainer { 28 | private List mediaRefs = null; 29 | private List media = null; 30 | 31 | /** 32 | * Use this function in place of getMedia and getMediaRefs 33 | * @param gedcom Gedcom 34 | * @return inline media as well as referenced media 35 | */ 36 | public List getAllMedia(Gedcom gedcom) { 37 | List media = new ArrayList(); 38 | for (MediaRef mediaRef : getMediaRefs()) { 39 | Media m = mediaRef.getMedia(gedcom); 40 | if (m != null) { 41 | media.add(m); 42 | } 43 | } 44 | media.addAll(getMedia()); 45 | return media; 46 | } 47 | 48 | public List getMediaRefs() { 49 | return mediaRefs != null ? mediaRefs : Collections.emptyList(); 50 | } 51 | 52 | public void setMediaRefs(List mediaRefs) { 53 | this.mediaRefs = mediaRefs; 54 | } 55 | 56 | public void addMediaRef(MediaRef mediaRef) { 57 | if (mediaRefs == null) { 58 | mediaRefs = new ArrayList(); 59 | } 60 | mediaRefs.add(mediaRef); 61 | } 62 | 63 | public List getMedia() { 64 | return media != null ? media : Collections.emptyList(); 65 | } 66 | 67 | public void setMedia(List media) { 68 | this.media = media; 69 | } 70 | 71 | public void addMedia(Media mediaObject) { 72 | if (media == null) { 73 | media = new ArrayList(); 74 | } 75 | media.add(mediaObject); 76 | } 77 | 78 | public void visitContainedObjects(Visitor visitor) { 79 | for (MediaRef mediaRef : getMediaRefs()) { 80 | mediaRef.accept(visitor); 81 | } 82 | for (Media m : getMedia()) { 83 | m.accept(visitor); 84 | } 85 | super.visitContainedObjects(visitor); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/tools/Gedcom2Gedcom.java: -------------------------------------------------------------------------------- 1 | package org.folg.gedcom.tools; 2 | 3 | import org.folg.gedcom.model.Gedcom; 4 | import org.folg.gedcom.parser.ModelParser; 5 | import org.folg.gedcom.visitors.GedcomWriter; 6 | import org.kohsuke.args4j.CmdLineException; 7 | import org.kohsuke.args4j.CmdLineParser; 8 | import org.kohsuke.args4j.Option; 9 | import org.xml.sax.SAXParseException; 10 | 11 | import java.io.*; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | /** 16 | * User: dallan 17 | * Date: 1/7/12 18 | * 19 | * Convert a GEDCOM file or directory to the model and back again 20 | */ 21 | public class Gedcom2Gedcom { 22 | private static final Logger logger = LoggerFactory.getLogger("org.folg.gedcom.tools"); 23 | 24 | @Option(name="-i", required=true, usage="file or directory containing gedcom files to convert") 25 | private File gedcomIn; 26 | 27 | @Option(name="-o", required=false, usage="target directory") 28 | private File gedcomOut; 29 | 30 | private ModelParser parser; 31 | private GedcomWriter writer; 32 | 33 | public Gedcom2Gedcom() { 34 | parser = new ModelParser(); 35 | writer = new GedcomWriter(); 36 | } 37 | 38 | public void convertGedcom(File file) { 39 | try { 40 | Gedcom gedcom = parser.parseGedcom(file); 41 | OutputStream out = (gedcomOut != null ? new FileOutputStream(new File(gedcomOut, file.getName())) : 42 | new ByteArrayOutputStream()); 43 | writer.write(gedcom, out); 44 | if (gedcomOut != null) { 45 | out.close(); 46 | } 47 | else { 48 | System.out.println(out.toString()); 49 | } 50 | } catch (SAXParseException e) { 51 | logger.error("SaxParseException for file: "+file.getName()+" "+e.getMessage()+" @ "+e.getLineNumber()); 52 | } catch (IOException e) { 53 | logger.error("IOException for file: " + file.getName() + " " + e.getMessage()); 54 | } catch (RuntimeException e) { 55 | e.printStackTrace(); 56 | logger.error("Exception for file: "+file.getName()+" "+e.getMessage()); 57 | } 58 | } 59 | 60 | private void doMain() throws FileNotFoundException { 61 | if (gedcomIn.isDirectory()) { 62 | for (File file : gedcomIn.listFiles()) { 63 | convertGedcom(file); 64 | } 65 | } 66 | else if (gedcomIn.isFile()) { 67 | convertGedcom(gedcomIn); 68 | } 69 | } 70 | 71 | public static void main(String[] args) throws FileNotFoundException { 72 | Gedcom2Gedcom self = new Gedcom2Gedcom(); 73 | CmdLineParser parser = new CmdLineParser(self); 74 | try { 75 | parser.parseArgument(args); 76 | self.doMain(); 77 | } 78 | catch (CmdLineException e) { 79 | System.err.println(e.getMessage()); 80 | parser.printUsage(System.err); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/GeneratorCorporation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/25/11 22 | * 23 | * add: Www 24 | */ 25 | public class GeneratorCorporation extends ExtensionContainer { 26 | private String value = null; 27 | private Address addr = null; 28 | private String phon = null; 29 | private String _email = null; 30 | private String emailTag = null; 31 | private String fax = null; 32 | private String _www = null; 33 | private String wwwTag = null; 34 | 35 | public String getValue() { 36 | return value; 37 | } 38 | 39 | public void setValue(String value) { 40 | this.value = value; 41 | } 42 | 43 | public Address getAddress() { 44 | return addr; 45 | } 46 | 47 | public void setAddress(Address addr) { 48 | this.addr = addr; 49 | } 50 | 51 | public String getPhone() { 52 | return phon; 53 | } 54 | 55 | public void setPhone(String phon) { 56 | this.phon = phon; 57 | } 58 | 59 | public String getEmail() { 60 | return _email; 61 | } 62 | 63 | public void setEmail(String email) { 64 | this._email = email; 65 | } 66 | 67 | public String getEmailTag() { 68 | return emailTag; 69 | } 70 | 71 | public void setEmailTag(String emailTag) { 72 | this.emailTag = emailTag; 73 | } 74 | 75 | public String getFax() { 76 | return fax; 77 | } 78 | 79 | public void setFax(String fax) { 80 | this.fax = fax; 81 | } 82 | 83 | public String getWww() { 84 | return _www; 85 | } 86 | 87 | public void setWww(String www) { 88 | this._www = www; 89 | } 90 | 91 | public String getWwwTag() { 92 | return wwwTag; 93 | } 94 | 95 | public void setWwwTag(String wwwTag) { 96 | this.wwwTag = wwwTag; 97 | } 98 | 99 | public void accept(Visitor visitor) { 100 | if (visitor.visit(this)) { 101 | if (addr != null) { 102 | addr.accept(visitor); 103 | } 104 | super.visitContainedObjects(visitor); 105 | visitor.endVisit(this); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/tools/Gedcom2Json.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.tools; 18 | 19 | import org.folg.gedcom.parser.JsonParser; 20 | import org.folg.gedcom.parser.ModelParser; 21 | import org.folg.gedcom.model.Gedcom; 22 | import org.folg.gedcom.model.GedcomTag; 23 | import org.folg.gedcom.parser.TreeParser; 24 | import org.kohsuke.args4j.CmdLineException; 25 | import org.kohsuke.args4j.CmdLineParser; 26 | import org.kohsuke.args4j.Option; 27 | import org.xml.sax.SAXParseException; 28 | 29 | import java.io.File; 30 | import java.io.IOException; 31 | import java.io.PrintWriter; 32 | import java.util.List; 33 | 34 | /** 35 | * User: Dallan 36 | * Date: 1/1/12 37 | */ 38 | public class Gedcom2Json { 39 | @Option(name="-i", required=true, usage="gedcom file in") 40 | private File gedcomIn; 41 | 42 | @Option(name="-o", required=false, usage="json file out") 43 | private File jsonOut; 44 | 45 | @Option(name="-t", required=false, usage="use tree parser (use model parser by default)") 46 | private boolean useTreeParser = false; 47 | 48 | private void doMain() throws SAXParseException, IOException { 49 | String json; 50 | JsonParser jsonParser = new JsonParser(); 51 | if (useTreeParser) { 52 | TreeParser treeParser = new TreeParser(); 53 | List gedcomTags = treeParser.parseGedcom(gedcomIn); 54 | json = jsonParser.toJson(gedcomTags); 55 | } 56 | else { 57 | ModelParser modelParser = new ModelParser(); 58 | Gedcom gedcom = modelParser.parseGedcom(gedcomIn); 59 | json = jsonParser.toJson(gedcom); 60 | } 61 | if (jsonOut != null) { 62 | PrintWriter writer = new PrintWriter(jsonOut); 63 | writer.println(json); 64 | writer.close(); 65 | } 66 | else { 67 | System.out.println(json); 68 | } 69 | } 70 | 71 | public static void main(String[] args) throws SAXParseException, IOException { 72 | Gedcom2Json self = new Gedcom2Json(); 73 | CmdLineParser parser = new CmdLineParser(self); 74 | try { 75 | parser.parseArgument(args); 76 | self.doMain(); 77 | } 78 | catch (CmdLineException e) { 79 | System.err.println(e.getMessage()); 80 | parser.printUsage(System.err); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Visitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/25/11 22 | * 23 | * If you override these functions, return false if you don't want to visit an object's children 24 | */ 25 | public class Visitor { 26 | public boolean visit(Address address) {return true;} 27 | public boolean visit(Association association) {return true;} 28 | public boolean visit(Change change) {return true;} 29 | public boolean visit(CharacterSet characterSet) {return true;} 30 | public boolean visit(ChildRef childRef) {return true;} 31 | public boolean visit(DateTime dateTime) {return true;} 32 | public boolean visit(EventFact eventFact) {return true;} 33 | public boolean visit(String extensionKey, Object extension) {return true;} 34 | public boolean visit(Family family) {return true;} 35 | public boolean visit(Gedcom gedcom) {return true;} 36 | public boolean visit(GedcomVersion gedcomVersion) {return true;} 37 | public boolean visit(Generator generator) {return true;} 38 | public boolean visit(GeneratorCorporation generatorCorporation) {return true;} 39 | public boolean visit(GeneratorData generatorData) {return true;} 40 | public boolean visit(Header header) {return true;} 41 | public boolean visit(LdsOrdinance ldsOrdinance) {return true;} 42 | public boolean visit(Media media) {return true;} 43 | public boolean visit(MediaRef mediaRef) {return true;} 44 | public boolean visit(Name name) {return true;} 45 | public boolean visit(Note note) {return true;} 46 | public boolean visit(NoteRef noteRef) {return true;} 47 | public boolean visit(ParentFamilyRef parentFamilyRef) {return true;} 48 | public boolean visit(ParentRelationship parentRelationship, boolean isFather) {return true;} 49 | public boolean visit(Person person) {return true;} 50 | public boolean visit(Repository repository) {return true;} 51 | public boolean visit(RepositoryRef repositoryRef) {return true;} 52 | public boolean visit(Source source) {return true;} 53 | public boolean visit(SourceCitation sourceCitation) {return true;} 54 | public boolean visit(SpouseRef spouseRef, boolean isHusband) {return true;} 55 | public boolean visit(SpouseFamilyRef spouseFamilyRef) {return true;} 56 | public boolean visit(Submission submission) {return true;} 57 | public boolean visit(Submitter submitter) {return true;} 58 | public void endVisit(ExtensionContainer obj) {} 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/parser/FieldRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.parser; 18 | 19 | import java.lang.reflect.InvocationTargetException; 20 | import java.lang.reflect.Method; 21 | 22 | /** 23 | * User: Dallan 24 | * Date: 12/26/11 25 | */ 26 | public class FieldRef { 27 | private Object target; 28 | private String name; 29 | 30 | public FieldRef(Object target, String name) { 31 | this.target = target; 32 | this.name = name; 33 | } 34 | 35 | public String getClassFieldName() { 36 | return target.getClass().getName()+"."+name; 37 | } 38 | 39 | public Object getTarget() { 40 | return target; 41 | } 42 | 43 | public String getFieldName() { 44 | return name; 45 | } 46 | 47 | public void setValue(String value) throws NoSuchMethodException { 48 | try { 49 | Method method = target.getClass().getMethod("set"+name, String.class); 50 | method.invoke(target, value); 51 | } catch (InvocationTargetException e) { 52 | e.printStackTrace(); 53 | throw new RuntimeException(e); 54 | } catch (IllegalAccessException e) { 55 | e.printStackTrace(); 56 | throw new RuntimeException(e); 57 | } 58 | } 59 | 60 | public String getValue() throws NoSuchMethodException { 61 | try { 62 | Method method = target.getClass().getMethod("get"+name); 63 | return (String)method.invoke(target); 64 | } catch (InvocationTargetException e) { 65 | e.printStackTrace(); 66 | throw new RuntimeException(e); 67 | } catch (IllegalAccessException e) { 68 | e.printStackTrace(); 69 | throw new RuntimeException(e); 70 | } 71 | } 72 | 73 | public void appendValue(String value) throws NoSuchMethodException { 74 | try { 75 | String currentValue = getValue(); 76 | setValue((currentValue == null ? "" : currentValue) + value); 77 | } catch (NoSuchMethodException e) { 78 | // try "add" 79 | try { 80 | Method method = target.getClass().getMethod("add"+name, String.class); 81 | method.invoke(target, value); 82 | } catch (InvocationTargetException e1) { 83 | e1.printStackTrace(); 84 | throw new RuntimeException(e); 85 | } catch (IllegalAccessException e1) { 86 | e1.printStackTrace(); 87 | throw new RuntimeException(e); 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/parser/ExtensionsTypeAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.parser; 18 | 19 | import com.google.gson.*; 20 | import org.folg.gedcom.model.Extensions; 21 | 22 | import java.lang.reflect.Type; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | /** 27 | * User: Dallan 28 | * Date: 12/18/11 29 | */ 30 | public class ExtensionsTypeAdapter implements JsonSerializer, JsonDeserializer { 31 | private Gson gson; 32 | private Map classExtensions; 33 | private Map typeExtensions; 34 | 35 | public ExtensionsTypeAdapter() { 36 | gson = new Gson(); 37 | classExtensions = new HashMap(); 38 | typeExtensions = new HashMap(); 39 | } 40 | 41 | public void registerExtension(String extensionKey, Class clazz) { 42 | classExtensions.put(extensionKey, clazz); 43 | } 44 | 45 | public void registerExtension(String extensionKey, Type type) { 46 | typeExtensions.put(extensionKey, type); 47 | } 48 | 49 | public JsonElement serialize(Extensions src, Type typeOfSrc, JsonSerializationContext context) { 50 | JsonObject o = new JsonObject(); 51 | for (Map.Entry entry : src.getExtensions().entrySet()) { 52 | String key = entry.getKey(); 53 | Object extension = entry.getValue(); 54 | JsonElement elm = (extension instanceof JsonElement ? (JsonElement) extension : gson.toJsonTree(extension)); 55 | o.add(key, elm); 56 | } 57 | return o; 58 | } 59 | 60 | @SuppressWarnings("unchecked") 61 | public Extensions deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 62 | JsonObject o = json.getAsJsonObject(); 63 | Extensions extensions = new Extensions(); 64 | for (Map.Entry entry : o.entrySet()) { 65 | String key = entry.getKey(); 66 | JsonElement jsonElement = entry.getValue(); 67 | Object extension; 68 | Type type = typeExtensions.get(key); 69 | if (type != null) { 70 | extension = gson.fromJson(jsonElement, type); 71 | } 72 | else { 73 | Class clazz = classExtensions.get(key); 74 | if (clazz != null) { 75 | extension = gson.fromJson(jsonElement, clazz); 76 | } 77 | else { 78 | extension = jsonElement; 79 | } 80 | } 81 | extensions.put(key, extension); 82 | } 83 | return extensions; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/SourceCitation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | * 23 | * omit: event, data 24 | * add: text and date from data 25 | */ 26 | public class SourceCitation extends MediaContainer { 27 | public static enum DataTagContents {DATE, TEXT, COMBINED, SEPARATE}; 28 | 29 | private String ref = null; 30 | private String value = null; 31 | private String page = null; 32 | private String date = null; 33 | private String text = null; 34 | private String quay = null; 35 | // yuck - some gedcom's don't use the data tag, some include write both text and date under the same tag, others use two data tags 36 | private DataTagContents dataTagContents = null; // set to null in default case (no data tag) so it isn't saved to json 37 | 38 | public String getRef() { 39 | return ref; 40 | } 41 | 42 | public void setRef(String ref) { 43 | this.ref = ref; 44 | } 45 | 46 | public Source getSource(Gedcom gedcom) { 47 | return gedcom.getSource(ref); 48 | } 49 | 50 | /** 51 | * Use this function to get text from value or text field 52 | * @return text, or value if text is empty 53 | */ 54 | public String getTextOrValue() { 55 | return text != null ? text : value; 56 | } 57 | 58 | public String getValue() { 59 | return value; 60 | } 61 | 62 | public void setValue(String value) { 63 | this.value = value; 64 | } 65 | 66 | public String getText() { 67 | return text; 68 | } 69 | 70 | public void setText(String text) { 71 | this.text = text; 72 | } 73 | 74 | public String getPage() { 75 | return page; 76 | } 77 | 78 | public void setPage(String page) { 79 | this.page = page; 80 | } 81 | 82 | public String getDate() { 83 | return date; 84 | } 85 | 86 | public void setDate(String date) { 87 | this.date = date; 88 | } 89 | 90 | public String getQuality() { 91 | return quay; 92 | } 93 | 94 | public void setQuality(String quay) { 95 | this.quay = quay; 96 | } 97 | 98 | public DataTagContents getDataTagContents() { 99 | return this.dataTagContents; 100 | } 101 | 102 | public void setDataTagContents(DataTagContents dataTagContents) { 103 | this.dataTagContents = dataTagContents; 104 | } 105 | 106 | public void accept(Visitor visitor) { 107 | if (visitor.visit(this)) { 108 | super.visitContainedObjects(visitor); 109 | visitor.endVisit(this); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Media.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | * 23 | * omit: Linked objects, Reference number, Rin 24 | * add: File, primary, type, scrapbook, slideshow 25 | */ 26 | public class Media extends NoteContainer { 27 | private String id = null; 28 | private String form = null; 29 | private String titl = null; 30 | private String blob = null; 31 | private Change chan = null; 32 | private String _file = null; 33 | private String fileTag = null; 34 | private String _prim = null; 35 | private String _type = null; 36 | private String _scbk = null; 37 | private String _sshow = null; 38 | 39 | public String getId() { 40 | return id; 41 | } 42 | 43 | public void setId(String id) { 44 | this.id = id; 45 | } 46 | 47 | public String getFormat() { 48 | return form; 49 | } 50 | 51 | public void setFormat(String form) { 52 | this.form = form; 53 | } 54 | 55 | public String getTitle() { 56 | return titl; 57 | } 58 | 59 | public void setTitle(String titl) { 60 | this.titl = titl; 61 | } 62 | 63 | public String getBlob() { 64 | return blob; 65 | } 66 | 67 | public void setBlob(String blob) { 68 | this.blob = blob; 69 | } 70 | 71 | public Change getChange() { 72 | return chan; 73 | } 74 | 75 | public void setChange(Change chan) { 76 | this.chan = chan; 77 | } 78 | 79 | public String getFile() { 80 | return _file; 81 | } 82 | 83 | public void setFile(String _file) { 84 | this._file = _file; 85 | } 86 | 87 | public String getFileTag() { 88 | return fileTag; 89 | } 90 | 91 | public void setFileTag(String fileTag) { 92 | this.fileTag = fileTag; 93 | } 94 | 95 | public String getPrimary() { 96 | return _prim; 97 | } 98 | 99 | public void setPrimary(String prim) { 100 | this._prim = prim; 101 | } 102 | 103 | public String getType() { 104 | return _type; 105 | } 106 | 107 | public void setType(String type) { 108 | this._type = type; 109 | } 110 | 111 | public String getScrapbook() { 112 | return _scbk; 113 | } 114 | 115 | public void setScrapbook(String scbk) { 116 | this._scbk = scbk; 117 | } 118 | 119 | public String getSlideShow() { 120 | return _sshow; 121 | } 122 | 123 | public void setSlideShow(String sshow) { 124 | this._sshow = sshow; 125 | } 126 | 127 | public void accept(Visitor visitor) { 128 | if (visitor.visit(this)) { 129 | if (chan != null) { 130 | chan.accept(visitor); 131 | } 132 | super.visitContainedObjects(visitor); 133 | visitor.endVisit(this); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Note.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/26/11 26 | * 27 | * omit: reference number 28 | * don't make this a SourceCitationContainer, because that would allow nested notes 29 | */ 30 | public class Note extends ExtensionContainer { 31 | private String id = null; 32 | private String value = null; 33 | private String rin = null; 34 | private Change chan = null; 35 | private List sourceCitations = null; 36 | private boolean sourceCitationsUnderValue = false; // yuck: Reunion does this: 0 NOTE 1 CONT ... 2 SOUR; remember for round-trip 37 | 38 | public String getId() { 39 | return id; 40 | } 41 | 42 | public void setId(String id) { 43 | this.id = id; 44 | } 45 | 46 | public String getValue() { 47 | return value; 48 | } 49 | 50 | public void setValue(String value) { 51 | this.value = value; 52 | } 53 | 54 | public String getRin() { 55 | return rin; 56 | } 57 | 58 | public void setRin(String rin) { 59 | this.rin = rin; 60 | } 61 | 62 | public Change getChange() { 63 | return chan; 64 | } 65 | 66 | public void setChange(Change chan) { 67 | this.chan = chan; 68 | } 69 | 70 | public List getSourceCitations() { 71 | return sourceCitations != null ? sourceCitations : Collections.emptyList(); 72 | } 73 | 74 | public void setSourceCitations(List sourceCitations) { 75 | this.sourceCitations = sourceCitations; 76 | } 77 | 78 | public void addSourceCitation(SourceCitation sourceCitation) { 79 | if (sourceCitations == null) { 80 | sourceCitations = new ArrayList(); 81 | } 82 | sourceCitations.add(sourceCitation); 83 | } 84 | 85 | public boolean isSourceCitationsUnderValue() { 86 | return sourceCitationsUnderValue; 87 | } 88 | 89 | public void setSourceCitationsUnderValue(boolean sourceRefsUnderValue) { 90 | this.sourceCitationsUnderValue = sourceRefsUnderValue; 91 | } 92 | 93 | public void visitContainedObjects(Visitor visitor, boolean includeSourceCitations) { 94 | if (chan != null) { 95 | chan.accept(visitor); 96 | } 97 | if (includeSourceCitations) { 98 | for (SourceCitation sourceCitation : getSourceCitations()) { 99 | sourceCitation.accept(visitor); 100 | } 101 | } 102 | super.visitContainedObjects(visitor); 103 | } 104 | 105 | public void visitContainedObjects(Visitor visitor) { 106 | visitContainedObjects(visitor, true); 107 | } 108 | 109 | public void accept(Visitor visitor) { 110 | if (visitor.visit(this)) { 111 | this.visitContainedObjects(visitor); 112 | visitor.endVisit(this); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Repository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/29/11 22 | * 23 | * omit: Reference number 24 | * add: Www, Email 25 | */ 26 | public class Repository extends NoteContainer { 27 | private String id = null; 28 | private String value = null; 29 | private String name = null; 30 | private Address addr = null; 31 | private String phon = null; 32 | private String fax = null; 33 | private String rin = null; 34 | private Change chan = null; 35 | private String _email = null; 36 | private String emailTag = null; 37 | private String _www = null; 38 | private String wwwTag = null; 39 | 40 | public String getId() { 41 | return id; 42 | } 43 | 44 | public void setId(String id) { 45 | this.id = id; 46 | } 47 | 48 | public String getValue() { 49 | return value; 50 | } 51 | 52 | public void setValue(String value) { 53 | this.value = value; 54 | } 55 | 56 | public String getName() { 57 | return name; 58 | } 59 | 60 | public void setName(String name) { 61 | this.name = name; 62 | } 63 | 64 | public Address getAddress() { 65 | return addr; 66 | } 67 | 68 | public void setAddress(Address addr) { 69 | this.addr = addr; 70 | } 71 | 72 | public String getPhone() { 73 | return phon; 74 | } 75 | 76 | public void setPhone(String phon) { 77 | this.phon = phon; 78 | } 79 | 80 | public String getFax() { 81 | return fax; 82 | } 83 | 84 | public void setFax(String fax) { 85 | this.fax = fax; 86 | } 87 | 88 | public String getRin() { 89 | return rin; 90 | } 91 | 92 | public void setRin(String rin) { 93 | this.rin = rin; 94 | } 95 | 96 | public Change getChange() { 97 | return chan; 98 | } 99 | 100 | public void setChange(Change chan) { 101 | this.chan = chan; 102 | } 103 | 104 | public String getEmail() { 105 | return _email; 106 | } 107 | 108 | public void setEmail(String email) { 109 | this._email = email; 110 | } 111 | 112 | public String getEmailTag() { 113 | return emailTag; 114 | } 115 | 116 | public void setEmailTag(String emailTag) { 117 | this.emailTag = emailTag; 118 | } 119 | 120 | public String getWww() { 121 | return _www; 122 | } 123 | 124 | public void setWww(String www) { 125 | this._www = www; 126 | } 127 | 128 | public String getWwwTag() { 129 | return wwwTag; 130 | } 131 | 132 | public void setWwwTag(String wwwTag) { 133 | this.wwwTag = wwwTag; 134 | } 135 | 136 | public void accept(Visitor visitor) { 137 | if (visitor.visit(this)) { 138 | if (addr != null) { 139 | addr.accept(visitor); 140 | } 141 | if (chan != null) { 142 | chan.accept(visitor); 143 | } 144 | super.visitContainedObjects(visitor); 145 | visitor.endVisit(this); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Address.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/26/11 22 | * 23 | * add: name 24 | * note: addressLine1+2 are rarely used; addresses are generally stored in Value 25 | */ 26 | public class Address extends ExtensionContainer { 27 | private String value = null; 28 | private String adr1 = null; 29 | private String adr2 = null; 30 | private String adr3 = null; 31 | private String city = null; 32 | private String stae = null; 33 | private String post = null; 34 | private String ctry = null; 35 | private String _name = null; 36 | 37 | private void appendValue(StringBuilder buf, String value) { 38 | if (value != null) { 39 | if (buf.length() > 0) { 40 | buf.append("\n"); 41 | } 42 | buf.append(value); 43 | } 44 | } 45 | 46 | public String getDisplayValue() { 47 | StringBuilder buf = new StringBuilder(); 48 | appendValue(buf, value); 49 | appendValue(buf, adr1); 50 | appendValue(buf, adr2); 51 | appendValue(buf, adr3); 52 | appendValue(buf, (city != null ? city : "")+(city != null && stae != null ? ", " : "")+(stae != null ? stae : "")+ 53 | ((city != null || stae != null) && post != null ? " " : "")+(post != null ? post : "")); 54 | appendValue(buf, ctry); 55 | return buf.toString(); 56 | } 57 | public String getValue() { 58 | return value; 59 | } 60 | 61 | public void setValue(String value) { 62 | this.value = value; 63 | } 64 | 65 | public String getAddressLine1() { 66 | return adr1; 67 | } 68 | 69 | public void setAddressLine1(String adr1) { 70 | this.adr1 = adr1; 71 | } 72 | 73 | public String getAddressLine2() { 74 | return adr2; 75 | } 76 | 77 | public void setAddressLine2(String adr2) { 78 | this.adr2 = adr2; 79 | } 80 | 81 | public String getAddressLine3() { 82 | return adr3; 83 | } 84 | 85 | public void setAddressLine3(String adr3) { 86 | this.adr3 = adr3; 87 | } 88 | 89 | public String getCity() { 90 | return city; 91 | } 92 | 93 | public void setCity(String city) { 94 | this.city = city; 95 | } 96 | 97 | public String getState() { 98 | return stae; 99 | } 100 | 101 | public void setState(String stae) { 102 | this.stae = stae; 103 | } 104 | 105 | public String getPostalCode() { 106 | return post; 107 | } 108 | 109 | public void setPostalCode(String post) { 110 | this.post = post; 111 | } 112 | 113 | public String getCountry() { 114 | return ctry; 115 | } 116 | 117 | public void setCountry(String ctry) { 118 | this.ctry = ctry; 119 | } 120 | 121 | public String getName() { 122 | return _name; 123 | } 124 | 125 | public void setName(String name) { 126 | this._name = name; 127 | } 128 | 129 | public void accept(Visitor visitor) { 130 | if (visitor.visit(this)) { 131 | super.visitContainedObjects(visitor); 132 | visitor.endVisit(this); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/PersonFamilyCommonContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/28/11 26 | */ 27 | public abstract class PersonFamilyCommonContainer extends SourceCitationContainer { 28 | private List eventsFacts = null; 29 | private List ldsOrdinances = null; 30 | private List refns = null; 31 | private String rin = null; 32 | private Change chan = null; 33 | private String _uid = null; 34 | private String uidTag = null; 35 | 36 | public List getEventsFacts() { 37 | return eventsFacts != null ? eventsFacts : Collections.emptyList(); 38 | } 39 | 40 | public void setEventsFacts(List eventsFacts) { 41 | this.eventsFacts = eventsFacts; 42 | } 43 | 44 | public void addEventFact(EventFact eventFact) { 45 | if (eventsFacts == null) { 46 | eventsFacts = new ArrayList(); 47 | } 48 | eventsFacts.add(eventFact); 49 | } 50 | 51 | public List getLdsOrdinances() { 52 | return ldsOrdinances != null ? ldsOrdinances : Collections.emptyList(); 53 | } 54 | 55 | public void setLdsOrdinances(List ldsOrdinances) { 56 | this.ldsOrdinances = ldsOrdinances; 57 | } 58 | 59 | public void addLdsOrdinance(LdsOrdinance ldsOrdinance) { 60 | if (ldsOrdinances == null) { 61 | ldsOrdinances = new ArrayList(); 62 | } 63 | ldsOrdinances.add(ldsOrdinance); 64 | } 65 | 66 | public List getReferenceNumbers() { 67 | return refns != null ? refns : Collections.emptyList(); 68 | } 69 | 70 | public void setReferenceNumbers(List refns) { 71 | this.refns = refns; 72 | } 73 | 74 | public void addReferenceNumber(String refn) { 75 | if (refns == null) { 76 | refns = new ArrayList(); 77 | } 78 | refns.add(refn); 79 | } 80 | 81 | public String getRin() { 82 | return rin; 83 | } 84 | 85 | public void setRin(String rin) { 86 | this.rin = rin; 87 | } 88 | 89 | public Change getChange() { 90 | return chan; 91 | } 92 | 93 | public void setChange(Change chan) { 94 | this.chan = chan; 95 | } 96 | 97 | public String getUid() { 98 | return _uid; 99 | } 100 | 101 | public void setUid(String uid) { 102 | this._uid = uid; 103 | } 104 | 105 | public String getUidTag() { 106 | return uidTag; 107 | } 108 | 109 | public void setUidTag(String uidTag) { 110 | this.uidTag = uidTag; 111 | } 112 | 113 | public void visitContainedObjects(Visitor visitor) { 114 | for (EventFact eventFact : getEventsFacts()) { 115 | eventFact.accept(visitor); 116 | } 117 | for (LdsOrdinance ldsOrdinance : getLdsOrdinances()) { 118 | ldsOrdinance.accept(visitor); 119 | } 120 | if (chan != null) { 121 | chan.accept(visitor); 122 | } 123 | super.visitContainedObjects(visitor); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Submitter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/27/11 22 | * 23 | * add: value, Www, Email 24 | */ 25 | public class Submitter extends ExtensionContainer { 26 | private String id = null; 27 | private String value = null; 28 | private Address addr = null; 29 | private String phon = null; 30 | private String fax = null; 31 | private String name = null; 32 | private Change chan = null; 33 | private String rin = null; 34 | private String lang = null; 35 | private String _www = null; 36 | private String wwwTag = null; 37 | private String _email = null; 38 | private String emailTag = null; 39 | 40 | public String getId() { 41 | return id; 42 | } 43 | 44 | public void setId(String id) { 45 | this.id = id; 46 | } 47 | 48 | public String getValue() { 49 | return value; 50 | } 51 | 52 | public void setValue(String value) { 53 | this.value = value; 54 | } 55 | 56 | public Address getAddress() { 57 | return addr; 58 | } 59 | 60 | public void setAddress(Address addr) { 61 | this.addr = addr; 62 | } 63 | 64 | public String getPhone() { 65 | return phon; 66 | } 67 | 68 | public void setPhone(String phon) { 69 | this.phon = phon; 70 | } 71 | 72 | public String getFax() { 73 | return fax; 74 | } 75 | 76 | public void setFax(String fax) { 77 | this.fax = fax; 78 | } 79 | 80 | public String getName() { 81 | return name; 82 | } 83 | 84 | public void setName(String name) { 85 | this.name = name; 86 | } 87 | 88 | public Change getChange() { 89 | return chan; 90 | } 91 | 92 | public void setChange(Change chan) { 93 | this.chan = chan; 94 | } 95 | 96 | public String getRin() { 97 | return rin; 98 | } 99 | 100 | public void setRin(String rin) { 101 | this.rin = rin; 102 | } 103 | 104 | public String getLanguage() { 105 | return lang; 106 | } 107 | 108 | public void setLanguage(String lang) { 109 | this.lang = lang; 110 | } 111 | 112 | public String getWww() { 113 | return _www; 114 | } 115 | 116 | public void setWww(String www) { 117 | this._www = www; 118 | } 119 | 120 | public String getWwwTag() { 121 | return wwwTag; 122 | } 123 | 124 | public void setWwwTag(String wwwTag) { 125 | this.wwwTag = wwwTag; 126 | } 127 | 128 | public String getEmail() { 129 | return _email; 130 | } 131 | 132 | public void setEmail(String email) { 133 | this._email = email; 134 | } 135 | 136 | public String getEmailTag() { 137 | return emailTag; 138 | } 139 | 140 | public void setEmailTag(String emailTag) { 141 | this.emailTag = emailTag; 142 | } 143 | 144 | public void accept(Visitor visitor) { 145 | if (visitor.visit(this)) { 146 | if (addr != null) { 147 | addr.accept(visitor); 148 | } 149 | if (chan != null) { 150 | chan.accept(visitor); 151 | } 152 | super.visitContainedObjects(visitor); 153 | visitor.endVisit(this); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /doc/submitter.ucls: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Header.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/25/11 22 | * 23 | * omit: Submitter, Submission, Place 24 | */ 25 | public class Header extends NoteContainer { 26 | private Generator sour = null; 27 | private String dest = null; 28 | private DateTime date = null; 29 | private String submRef = null; 30 | private String subnRef = null; 31 | private Submission subn = null; 32 | private String file = null; 33 | private String copr = null; 34 | private GedcomVersion gedc = null; 35 | private CharacterSet charset = null; 36 | private String lang = null; 37 | 38 | public Generator getGenerator() { 39 | return sour; 40 | } 41 | 42 | public void setGenerator(Generator sour) { 43 | this.sour = sour; 44 | } 45 | 46 | public String getDestination() { 47 | return dest; 48 | } 49 | 50 | public void setDestination(String dest) { 51 | this.dest = dest; 52 | } 53 | 54 | public DateTime getDateTime() { 55 | return date; 56 | } 57 | 58 | public void setDateTime(DateTime date) { 59 | this.date = date; 60 | } 61 | 62 | public String getSubmitterRef() { 63 | return submRef; 64 | } 65 | 66 | public void setSubmitterRef(String submRef) { 67 | this.submRef = submRef; 68 | } 69 | 70 | public Submitter getSubmitter(Gedcom gedcom) { 71 | return gedcom.getSubmitter(submRef); 72 | } 73 | 74 | /** 75 | * Use Gedcom.getSubmission in place of this function 76 | * @return submission reference 77 | */ 78 | public String getSubmissionRef() { 79 | return subnRef; 80 | } 81 | 82 | public void setSubmissionRef(String subnRef) { 83 | this.subnRef = subnRef; 84 | } 85 | 86 | /** 87 | * Use Gedcom.getSubmission in place of this function 88 | * @return submission 89 | */ 90 | public Submission getSubmission() { 91 | return subn; 92 | } 93 | 94 | public void setSubmission(Submission subn) { 95 | this.subn = subn; 96 | } 97 | 98 | public String getFile() { 99 | return file; 100 | } 101 | 102 | public void setFile(String file) { 103 | this.file = file; 104 | } 105 | 106 | public String getCopyright() { 107 | return copr; 108 | } 109 | 110 | public void setCopyright(String copr) { 111 | this.copr = copr; 112 | } 113 | 114 | public GedcomVersion getGedcomVersion() { 115 | return gedc; 116 | } 117 | 118 | public void setGedcomVersion(GedcomVersion gedc) { 119 | this.gedc = gedc; 120 | } 121 | 122 | public CharacterSet getCharacterSet() { 123 | return charset; 124 | } 125 | 126 | public void setCharacterSet(CharacterSet charset) { 127 | this.charset = charset; 128 | } 129 | 130 | public String getLanguage() { 131 | return lang; 132 | } 133 | 134 | public void setLanguage(String lang) { 135 | this.lang = lang; 136 | } 137 | 138 | public void accept(Visitor visitor) { 139 | if (visitor.visit(this)) { 140 | if (sour != null) { 141 | sour.accept(visitor); 142 | } 143 | if (date != null) { 144 | date.accept(visitor); 145 | } 146 | if (subn != null) { 147 | subn.accept(visitor); 148 | } 149 | if (gedc != null) { 150 | gedc.accept(visitor); 151 | } 152 | if (charset != null) { 153 | charset.accept(visitor); 154 | } 155 | super.visitContainedObjects(visitor); 156 | visitor.endVisit(this); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/parser/JsonParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.parser; 18 | 19 | import com.google.gson.Gson; 20 | import com.google.gson.GsonBuilder; 21 | import org.folg.gedcom.model.Gedcom; 22 | import org.folg.gedcom.model.GedcomTag; 23 | 24 | import java.io.*; 25 | import java.nio.charset.Charset; 26 | import java.util.List; 27 | 28 | /** 29 | * User: dallan 30 | * Date: 1/2/12 31 | */ 32 | public class JsonParser { 33 | private Gson gson; 34 | 35 | public JsonParser() { 36 | gson = new GsonBuilder() 37 | .setPrettyPrinting() 38 | .registerTypeAdapter(Gedcom.class, new GedcomTypeAdapter()) 39 | .create(); 40 | } 41 | 42 | /** 43 | * Convert json-encoded string to Gedcom object 44 | * 45 | * @param json json-encoded string 46 | * @return Gedcom object 47 | */ 48 | public Gedcom fromJson(String json) { 49 | return gson.fromJson(json, Gedcom.class); 50 | } 51 | 52 | /** 53 | * Read Gedcom object from json character stream 54 | * 55 | * @param reader json source reader 56 | * @return Gedcom object 57 | */ 58 | public Gedcom fromJson(Reader reader) { 59 | return gson.fromJson(reader, Gedcom.class); 60 | } 61 | 62 | /** 63 | * Read Gedcom object from json byte stream 64 | * 65 | * @param is json source stream 66 | * @return Gedcom object 67 | */ 68 | public Gedcom fromJson(InputStream is) { 69 | InputStreamReader reader = new InputStreamReader(is, Charset.forName("UTF-8")); 70 | return gson.fromJson(reader, Gedcom.class); 71 | } 72 | 73 | /** 74 | * Convert Gedcom object to json 75 | * 76 | * @param gedcom Gedcom 77 | * @return json-encoded string 78 | */ 79 | public String toJson(Gedcom gedcom) { 80 | return gson.toJson(gedcom); 81 | } 82 | 83 | /** 84 | * Convert output of TreeParser to json 85 | * 86 | * @param gedcomTags output of TreeParser 87 | * @return json-encoded string 88 | */ 89 | public String toJson(List gedcomTags) { 90 | return gson.toJson(gedcomTags); 91 | } 92 | 93 | /** 94 | * Write Gedcom object to json character stream 95 | * 96 | * @param gedcom Gedcom object 97 | * @param writer json output writer 98 | */ 99 | public void write(Gedcom gedcom, Writer writer) { 100 | gson.toJson(gedcom, writer); 101 | close(writer); 102 | } 103 | 104 | /** 105 | * Write Gedcom object to json byte stream 106 | * 107 | * @param gedcom Gedcom object 108 | * @param os json output stream 109 | */ 110 | public void write(Gedcom gedcom, OutputStream os) { 111 | OutputStreamWriter writer = new OutputStreamWriter(os, Charset.forName("UTF-8")); 112 | gson.toJson(gedcom, writer); 113 | close(writer); 114 | } 115 | 116 | /** 117 | * Write Gedcom Tags from TreeParser to json character stream 118 | * 119 | * @param gedcomTags Gedcom tags 120 | * @param writer json output writer 121 | */ 122 | public void write(List gedcomTags, Writer writer) { 123 | gson.toJson(gedcomTags, writer); 124 | close(writer); 125 | } 126 | 127 | /** 128 | * Write Gedcom Tags from TreeParser to json byte stream 129 | * 130 | * @param gedcomTags Gedcom tags 131 | * @param os json output stream 132 | */ 133 | public void write(List gedcomTags, OutputStream os) { 134 | OutputStreamWriter writer = new OutputStreamWriter(os, Charset.forName("UTF-8")); 135 | gson.toJson(gedcomTags, writer); 136 | close(writer); 137 | } 138 | 139 | private void close(Writer writer) { 140 | try { 141 | if (writer != null) { 142 | writer.close(); 143 | } 144 | } catch (IOException e) { 145 | throw new IllegalStateException("Closing writer failed", e); 146 | } 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Family.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/27/11 26 | * 27 | * omit: Submitter, Reference type 28 | * add: Uid 29 | */ 30 | public class Family extends PersonFamilyCommonContainer { 31 | private String id = null; 32 | private List husbandRefs = null; // may be >1 if not sure which one (presumably one is preferred) 33 | private List wifeRefs = null; // ditto 34 | private List childRefs = null; 35 | 36 | public String getId() { 37 | return id; 38 | } 39 | 40 | public void setId(String id) { 41 | this.id = id; 42 | } 43 | 44 | private List getFamilyMembers(Gedcom gedcom, List memberRefs, boolean preferredFirst) { 45 | List members = new ArrayList(); 46 | for (SpouseRef memberRef : memberRefs) { 47 | Person member = memberRef.getPerson(gedcom); 48 | if (member != null) { 49 | if (preferredFirst && "Y".equals(memberRef.getPreferred())) { 50 | members.add(0, member); 51 | } 52 | else { 53 | members.add(member); 54 | } 55 | } 56 | } 57 | return members; 58 | } 59 | 60 | /** 61 | * Convenience function to dereference husband refs 62 | * Return preferred in first position 63 | * @param gedcom Gedcom 64 | * @return list of husbands, generally just one unless there are several alternatives with one preferred 65 | */ 66 | public List getHusbands(Gedcom gedcom) { 67 | return getFamilyMembers(gedcom, getHusbandRefs(), true); 68 | } 69 | 70 | public List getHusbandRefs() { 71 | return husbandRefs != null ? husbandRefs : Collections.emptyList(); 72 | } 73 | 74 | public void setHusbandRefs(List husbandRefs) { 75 | this.husbandRefs = husbandRefs; 76 | } 77 | 78 | public void addHusband(SpouseRef husband) { 79 | if (husbandRefs == null) { 80 | husbandRefs = new ArrayList(); 81 | } 82 | husbandRefs.add(husband); 83 | } 84 | 85 | /** 86 | * Convenience function to dereference wife refs 87 | * Return preferred in first position 88 | * @param gedcom Gedcom 89 | * @return list of wives, generally just one unless there are several alternatives with one preferred 90 | */ 91 | public List getWives(Gedcom gedcom) { 92 | return getFamilyMembers(gedcom, getWifeRefs(), true); 93 | } 94 | 95 | public List getWifeRefs() { 96 | return wifeRefs != null ? wifeRefs : Collections.emptyList(); 97 | } 98 | 99 | public void setWifeRefs(List wifeRefs) { 100 | this.wifeRefs = wifeRefs; 101 | } 102 | 103 | public void addWife(SpouseRef wife) { 104 | if (wifeRefs == null) { 105 | wifeRefs = new ArrayList(); 106 | } 107 | wifeRefs.add(wife); 108 | } 109 | 110 | /** 111 | * Convenience function to dereference child refs 112 | * @param gedcom Gedcom 113 | * @return list of children 114 | */ 115 | public List getChildren(Gedcom gedcom) { 116 | return getFamilyMembers(gedcom, getChildRefs(), false); 117 | } 118 | 119 | public List getChildRefs() { 120 | return childRefs != null ? childRefs : Collections.emptyList(); 121 | } 122 | 123 | public void setChildRefs(List childRefs) { 124 | this.childRefs = childRefs; 125 | } 126 | 127 | public void addChild(ChildRef childRef) { 128 | if (childRefs == null) { 129 | childRefs = new ArrayList(); 130 | } 131 | childRefs.add(childRef); 132 | } 133 | 134 | public void accept(Visitor visitor) { 135 | if (visitor.visit(this)) { 136 | for (SpouseRef husband : getHusbandRefs()) { 137 | husband.accept(visitor, true); 138 | } 139 | for (SpouseRef wife : getWifeRefs()) { 140 | wife.accept(visitor, false); 141 | } 142 | for (ChildRef childRef : getChildRefs()) { 143 | childRef.accept(visitor); 144 | } 145 | super.visitContainedObjects(visitor); 146 | visitor.endVisit(this); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/tools/GedcomAnalyzer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.tools; 18 | 19 | import org.folg.gedcom.parser.ErrorHandler; 20 | import org.folg.gedcom.parser.ModelParser; 21 | import org.kohsuke.args4j.CmdLineException; 22 | import org.kohsuke.args4j.CmdLineParser; 23 | import org.kohsuke.args4j.Option; 24 | import org.xml.sax.SAXParseException; 25 | 26 | import java.io.File; 27 | import java.io.FileNotFoundException; 28 | import java.io.IOException; 29 | import java.io.PrintWriter; 30 | import java.util.HashSet; 31 | import java.util.Set; 32 | import org.slf4j.Logger; 33 | import org.slf4j.LoggerFactory; 34 | 35 | /** 36 | * User: dallan 37 | * Date: 1/2/12 38 | */ 39 | public class GedcomAnalyzer implements ErrorHandler { 40 | private static final Logger logger = LoggerFactory.getLogger("org.folg.gedcom.tools"); 41 | 42 | @Option(name="-i", required=true, usage="file or directory containing gedcom files to analyze") 43 | private File gedcomIn; 44 | 45 | @Option(name="-w", required=false, usage="warnings file out") 46 | private File warningsOut; 47 | 48 | @Option(name="-e", required=false, usage="errors file out") 49 | private File errorsOut; 50 | 51 | private ModelParser parser; 52 | private Set warnings; 53 | private Set errors; 54 | private CountsCollector ccWarnings; 55 | private CountsCollector ccErrors; 56 | private int cntWarnings; 57 | private int cntErrors; 58 | private int cntTotal; 59 | private File file; 60 | 61 | public GedcomAnalyzer() { 62 | parser = new ModelParser(); 63 | parser.setErrorHandler(this); 64 | ccWarnings = new CountsCollector(); 65 | ccErrors = new CountsCollector(); 66 | cntTotal = 0; 67 | cntWarnings = 0; 68 | cntErrors = 0; 69 | } 70 | 71 | public void warning(String message, int lineNumber) { 72 | logger.info(message+" @ "+lineNumber); 73 | warnings.add(message); 74 | } 75 | 76 | public void error(String message, int lineNumber) { 77 | logger.warn(message+" @ "+lineNumber); 78 | errors.add(message); 79 | } 80 | 81 | public void fatalError(String message, int lineNumber) { 82 | // we'll log this below 83 | } 84 | 85 | public void analyzeGedcom(File gedcomFile) { 86 | warnings = new HashSet(); 87 | errors = new HashSet(); 88 | this.file = gedcomFile; 89 | 90 | try { 91 | parser.parseGedcom(gedcomFile); 92 | if (warnings.size() > 0 || errors.size() > 0) { 93 | cntWarnings++; 94 | } 95 | if (errors.size() > 0) { 96 | cntErrors++; 97 | } 98 | for (String warning : warnings) { 99 | ccWarnings.add(warning); 100 | } 101 | for (String error : errors) { 102 | ccErrors.add(error); 103 | } 104 | } catch (SAXParseException e) { 105 | logger.error("SaxParseException for file: "+file.getName()+" "+e.getMessage()+" @ "+e.getLineNumber()); 106 | } catch (IOException e) { 107 | logger.error("IOException for file: " + file.getName() + " " + e.getMessage()); 108 | } catch (RuntimeException e) { 109 | e.printStackTrace(); 110 | logger.error("Exception for file: "+file.getName()+" "+e.getMessage()); 111 | } 112 | } 113 | 114 | public CountsCollector getWarnings() { 115 | return ccWarnings; 116 | } 117 | 118 | public CountsCollector getErrors() { 119 | return ccErrors; 120 | } 121 | 122 | private void doMain() throws FileNotFoundException { 123 | if (gedcomIn.isDirectory()) { 124 | for (File file : gedcomIn.listFiles()) { 125 | analyzeGedcom(file); 126 | } 127 | } 128 | else if (gedcomIn.isFile()) { 129 | analyzeGedcom(gedcomIn); 130 | } 131 | 132 | System.out.println("Total="+cntTotal+" with warnings="+ cntWarnings +" with errors="+ cntErrors); 133 | getWarnings().writeSorted(false, 1, warningsOut != null ? new PrintWriter(warningsOut) : new PrintWriter(System.out)); 134 | getErrors().writeSorted(false, 1, errorsOut != null ? new PrintWriter(errorsOut) : new PrintWriter(System.out)); 135 | } 136 | 137 | public static void main(String[] args) throws FileNotFoundException { 138 | GedcomAnalyzer self = new GedcomAnalyzer(); 139 | CmdLineParser parser = new CmdLineParser(self); 140 | try { 141 | parser.parseArgument(args); 142 | self.doMain(); 143 | } 144 | catch (CmdLineException e) { 145 | System.err.println(e.getMessage()); 146 | parser.printUsage(System.err); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/tools/CountsCollector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.tools; 18 | 19 | import java.io.PrintWriter; 20 | import java.util.*; 21 | 22 | /** 23 | * General class to collect counts 24 | * 25 | * User: dallan 26 | * Date: 1/2/12 27 | */ 28 | public class CountsCollector { 29 | HashMap counts; 30 | 31 | public class Counter { 32 | int count; 33 | Counter() { 34 | count = 0; 35 | } 36 | public String toString() { 37 | return String.valueOf(count); 38 | } 39 | } 40 | 41 | public int size() { 42 | return counts.size(); 43 | } 44 | 45 | private class ValueComparator implements Comparator> { 46 | public int compare(Map.Entry me1, Map.Entry me2) { 47 | if (me1.getValue().count < me2.getValue().count || 48 | (me1.getValue().count == me2.getValue().count && 49 | me1.getKey().compareTo(me2.getKey()) < 0)) { 50 | return 1; 51 | } 52 | else { 53 | return -1; 54 | } 55 | } 56 | 57 | public boolean equals(Map.Entry me1, Map.Entry me2) { 58 | return (me1.getValue().count == me2.getValue().count && 59 | me1.getKey().equals(me2.getKey())); 60 | } 61 | } 62 | 63 | private class KeyComparator implements Comparator> { 64 | public int compare(Map.Entry me1, Map.Entry me2) { 65 | return (me1.getKey().compareTo(me2.getKey())); 66 | } 67 | 68 | public boolean equals(Map.Entry me1, Map.Entry me2) { 69 | return (me1.getKey().equals(me2.getKey())); 70 | } 71 | } 72 | 73 | public CountsCollector() { 74 | counts = new HashMap(); 75 | } 76 | 77 | public void add(String key) { 78 | add(key, 1); 79 | } 80 | 81 | public void add(String key, int count) { 82 | if (key != null) { 83 | Counter c = counts.get(key); 84 | if (c == null) { 85 | c = new Counter(); 86 | counts.put(key, c); 87 | } 88 | c.count += count; 89 | } 90 | } 91 | 92 | public void remove(String key) { 93 | counts.remove(key); 94 | } 95 | 96 | public int getCount(String key) { 97 | Counter c = counts.get(key); 98 | if (c == null) { 99 | return 0; 100 | } 101 | else { 102 | return c.count; 103 | } 104 | } 105 | 106 | public Set getKeys() { 107 | return counts.keySet(); 108 | } 109 | 110 | public void addAll(Set keys) { 111 | Iterator iter = keys.iterator(); 112 | while (iter.hasNext()) { 113 | add(iter.next()); 114 | } 115 | } 116 | 117 | /** 118 | * Returns the collection sorted and filtered 119 | * @param byKey if true, sort by key; otherwise sort descending by count 120 | * @param minCount only include items greater than minCount 121 | * @return the collection sorted and filtered 122 | */ 123 | public SortedSet> getSortedSet(boolean byKey, int minCount) { 124 | Comparator> comp; 125 | if (byKey) { 126 | comp = new KeyComparator(); 127 | } 128 | else { 129 | comp = new ValueComparator(); 130 | } 131 | SortedSet> ss = new TreeSet>(comp); 132 | Iterator> iter = counts.entrySet().iterator(); 133 | while (iter.hasNext()) { 134 | Map.Entry entry = iter.next(); 135 | if (entry.getValue().count >= minCount) { 136 | ss.add(entry); 137 | } 138 | } 139 | return ss; 140 | } 141 | 142 | /** 143 | * Write the stats in sorted order 144 | * @param byKey if true, sort by key value; otherwise sort by count 145 | * @param minCount write out only those entries having count greater than minCount 146 | * @param writer PrintWriter to write to 147 | */ 148 | public void writeSorted(boolean byKey, int minCount, PrintWriter writer) { 149 | // add all entries in the hash map appearing at least minCount times into the sorted set 150 | SortedSet> ss = getSortedSet(byKey, minCount); 151 | Iterator> iter = ss.iterator(); 152 | while (iter.hasNext()) { 153 | Map.Entry entry = iter.next(); 154 | writer.println(entry.getKey() + "\t" + entry.getValue()); 155 | } 156 | writer.flush(); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Source.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | /** 20 | * User: Dallan 21 | * Date: 12/29/11 22 | * 23 | * omit: data 24 | * add: media type, call number, type, uid, paren, italic, date 25 | */ 26 | public class Source extends MediaContainer { 27 | private String id = null; 28 | private String auth = null; 29 | private String titl = null; 30 | private String abbr = null; 31 | private String publ = null; 32 | private String text = null; 33 | private RepositoryRef repo = null; 34 | private String refn = null; 35 | private String rin = null; 36 | private Change chan = null; 37 | private String medi = null; 38 | private String caln = null; 39 | private String _type = null; 40 | private String typeTag = null; 41 | private String _uid = null; 42 | private String uidTag = null; 43 | private String _paren = null; 44 | private String _italic = null; 45 | private String date = null; 46 | 47 | public String getId() { 48 | return id; 49 | } 50 | 51 | public void setId(String id) { 52 | this.id = id; 53 | } 54 | 55 | public String getAuthor() { 56 | return auth; 57 | } 58 | 59 | public void setAuthor(String auth) { 60 | this.auth = auth; 61 | } 62 | 63 | public String getTitle() { 64 | return titl; 65 | } 66 | 67 | public void setTitle(String titl) { 68 | this.titl = titl; 69 | } 70 | 71 | public String getAbbreviation() { 72 | return abbr; 73 | } 74 | 75 | public void setAbbreviation(String abbr) { 76 | this.abbr = abbr; 77 | } 78 | 79 | public String getPublicationFacts() { 80 | return publ; 81 | } 82 | 83 | public void setPublicationFacts(String publ) { 84 | this.publ = publ; 85 | } 86 | 87 | public String getText() { 88 | return text; 89 | } 90 | 91 | public void setText(String text) { 92 | this.text = text; 93 | } 94 | 95 | public RepositoryRef getRepositoryRef() { 96 | return repo; 97 | } 98 | 99 | public void setRepositoryRef(RepositoryRef repo) { 100 | this.repo = repo; 101 | } 102 | 103 | public Repository getRepository(Gedcom gedcom) { 104 | return repo != null ? repo.getRepository(gedcom) : null; 105 | } 106 | 107 | public String getReferenceNumber() { 108 | return refn; 109 | } 110 | 111 | public void setReferenceNumber(String refn) { 112 | this.refn = refn; 113 | } 114 | 115 | public String getRin() { 116 | return rin; 117 | } 118 | 119 | public void setRin(String rin) { 120 | this.rin = rin; 121 | } 122 | 123 | public Change getChange() { 124 | return chan; 125 | } 126 | 127 | public void setChange(Change chan) { 128 | this.chan = chan; 129 | } 130 | 131 | public String getCallNumber() { 132 | return caln; 133 | } 134 | 135 | public void setCallNumber(String caln) { 136 | this.caln = caln; 137 | } 138 | 139 | public String getMediaType() { 140 | return medi; 141 | } 142 | 143 | public void setMediaType(String medi) { 144 | this.medi = medi; 145 | } 146 | 147 | public String getType() { 148 | return _type; 149 | } 150 | 151 | public void setType(String _type) { 152 | this._type = _type; 153 | } 154 | 155 | public String getTypeTag() { 156 | return typeTag; 157 | } 158 | 159 | public void setTypeTag(String typeTag) { 160 | this.typeTag = typeTag; 161 | } 162 | 163 | public String getUid() { 164 | return _uid; 165 | } 166 | 167 | public void setUid(String _uid) { 168 | this._uid = _uid; 169 | } 170 | 171 | public String getUidTag() { 172 | return uidTag; 173 | } 174 | 175 | public void setUidTag(String uidTag) { 176 | this.uidTag = uidTag; 177 | } 178 | 179 | public String getParen() { 180 | return _paren; 181 | } 182 | 183 | public void setParen(String paren) { 184 | this._paren = paren; 185 | } 186 | 187 | public String getItalic() { 188 | return _italic; 189 | } 190 | 191 | public void setItalic(String italic) { 192 | this._italic = italic; 193 | } 194 | 195 | public String getDate() { 196 | return date; 197 | } 198 | 199 | public void setDate(String date) { 200 | this.date = date; 201 | } 202 | 203 | public void accept(Visitor visitor) { 204 | if (visitor.visit(this)) { 205 | if (repo != null) { 206 | repo.accept(visitor); 207 | } 208 | if (chan != null) { 209 | chan.accept(visitor); 210 | } 211 | super.visitContainedObjects(visitor); 212 | visitor.endVisit(this); 213 | } 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/parser/TreeParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.parser; 18 | 19 | import org.folg.gedcom.model.GedcomTag; 20 | import org.gedml.GedcomParser; 21 | import org.xml.sax.*; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.Reader; 27 | import java.util.List; 28 | import java.util.Stack; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | /** 33 | * Call parseGedcom to parse a gedcom file into a list of GedcomTag's 34 | * User: Dallan 35 | * Date: 12/23/11 36 | */ 37 | public class TreeParser implements ContentHandler, org.xml.sax.ErrorHandler { 38 | private static final Logger logger = LoggerFactory.getLogger("org.folg.gedcom.parser"); 39 | 40 | private Locator locator; 41 | private GedcomTag tree; 42 | private Stack nodeStack; 43 | private ErrorHandler errorHandler = null; 44 | 45 | @Override 46 | public void setDocumentLocator(Locator locator) { 47 | this.locator = locator; 48 | } 49 | 50 | @Override 51 | public void startDocument() throws SAXException { 52 | tree = null; 53 | nodeStack = new Stack(); 54 | } 55 | 56 | @Override 57 | public void endDocument() throws SAXException { 58 | // ignore 59 | } 60 | 61 | @Override 62 | public void startPrefixMapping(String prefix, String uri) throws SAXException { 63 | // ignore 64 | } 65 | 66 | @Override 67 | public void endPrefixMapping(String prefix) throws SAXException { 68 | // ignore 69 | } 70 | 71 | @Override 72 | public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { 73 | GedcomTag node = new GedcomTag(atts.getValue("ID"), localName, atts.getValue("REF")); 74 | if (tree == null) { 75 | tree = node; 76 | } 77 | else { 78 | nodeStack.peek().addChild(node); 79 | } 80 | nodeStack.push(node); 81 | } 82 | 83 | @Override 84 | public void endElement(String uri, String localName, String qName) throws SAXException { 85 | nodeStack.pop(); 86 | } 87 | 88 | @Override 89 | public void characters(char[] ch, int start, int length) throws SAXException { 90 | String s = new String(ch, start, length); 91 | GedcomTag tos = nodeStack.peek(); 92 | tos.appendValue(s); 93 | } 94 | 95 | @Override 96 | public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { 97 | // ignore 98 | } 99 | 100 | @Override 101 | public void processingInstruction(String target, String data) throws SAXException { 102 | // ignore 103 | } 104 | 105 | @Override 106 | public void skippedEntity(String name) throws SAXException { 107 | // ignore 108 | } 109 | 110 | @Override 111 | public void warning(SAXParseException exception) throws SAXException { 112 | if (errorHandler != null) { 113 | errorHandler.warning(exception.getMessage(), exception.getLineNumber()); 114 | } 115 | else { 116 | logger.info(exception.getMessage() + " @ " + exception.getLineNumber()); 117 | } 118 | } 119 | 120 | @Override 121 | public void error(SAXParseException exception) throws SAXException { 122 | if (errorHandler != null) { 123 | errorHandler.error(exception.getMessage(), exception.getLineNumber()); 124 | } 125 | else { 126 | logger.warn(exception.getMessage() + " @ " + exception.getLineNumber()); 127 | } 128 | } 129 | 130 | @Override 131 | public void fatalError(SAXParseException exception) throws SAXException { 132 | if (errorHandler != null) { 133 | errorHandler.fatalError(exception.getMessage(), exception.getLineNumber()); 134 | } 135 | else { 136 | logger.error(exception.getMessage() + " @ " + exception.getLineNumber()); 137 | } 138 | } 139 | 140 | public void setErrorHandler(ErrorHandler errorHandler) { 141 | this.errorHandler = errorHandler; 142 | } 143 | 144 | public List parseGedcom(File gedcomFile) throws SAXParseException, IOException { 145 | GedcomParser parser = gedcomParser(); 146 | parser.parse(gedcomFile.toURI().toString()); 147 | return tree.getChildren(); 148 | } 149 | 150 | public List parseGedcom(InputStream is) throws SAXParseException, IOException { 151 | GedcomParser parser = gedcomParser(); 152 | parser.parse(is); 153 | return tree.getChildren(); 154 | } 155 | 156 | public List parseGedcom(Reader reader) throws SAXParseException, IOException { 157 | GedcomParser parser = gedcomParser(); 158 | parser.parse(reader); 159 | return tree.getChildren(); 160 | } 161 | 162 | private GedcomParser gedcomParser() { 163 | GedcomParser parser = new GedcomParser(); 164 | parser.setContentHandler(this); 165 | parser.setErrorHandler(this); 166 | return parser; 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Name.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | 20 | /** 21 | * User: Dallan 22 | * Date: 12/25/11 23 | * 24 | * add: type, aka, married name, media 25 | * (Media objects are very rare in gedcoms in the wild) 26 | * note: _aka and _marrnm should be their own Name, but this would break round-tripping, so do it as a separate step 27 | */ 28 | public class Name extends SourceCitationContainer { 29 | private String value = null; 30 | private String givn = null; 31 | private String surn = null; 32 | private String npfx = null; 33 | private String nsfx = null; 34 | private String spfx = null; 35 | private String nick = null; 36 | private String fone = null; 37 | private String romn = null; 38 | private String _type = null; 39 | private String typeTag = null; 40 | private String _aka = null; 41 | private String akaTag = null; 42 | private String foneTag = null; 43 | private String romnTag = null; 44 | private String _marrnm = null; 45 | private String marrnmTag = null; 46 | 47 | private void appendValue(StringBuilder buf, String value) { 48 | if (value != null) { 49 | if (buf.length() > 0) { 50 | buf.append(' '); 51 | } 52 | buf.append(value); 53 | } 54 | } 55 | 56 | public String getDisplayValue() { 57 | if (value != null) { 58 | return value; 59 | } 60 | else { 61 | StringBuilder buf = new StringBuilder(); 62 | appendValue(buf, npfx); 63 | appendValue(buf, givn); 64 | appendValue(buf, spfx); 65 | appendValue(buf, surn); 66 | appendValue(buf, nsfx); 67 | return buf.toString(); 68 | } 69 | } 70 | 71 | public String getValue() { 72 | return value; 73 | } 74 | 75 | public void setValue(String value) { 76 | this.value = value; 77 | } 78 | 79 | public String getGiven() { 80 | return givn; 81 | } 82 | 83 | public void setGiven(String givn) { 84 | this.givn = givn; 85 | } 86 | 87 | public String getSurname() { 88 | return surn; 89 | } 90 | 91 | public void setSurname(String surn) { 92 | this.surn = surn; 93 | } 94 | 95 | public String getPrefix() { 96 | return npfx; 97 | } 98 | 99 | public void setPrefix(String npfx) { 100 | this.npfx = npfx; 101 | } 102 | 103 | public String getSuffix() { 104 | return nsfx; 105 | } 106 | 107 | public void setSuffix(String nsfx) { 108 | this.nsfx = nsfx; 109 | } 110 | 111 | /** 112 | * Rarely used 113 | * @return surname prefix 114 | */ 115 | public String getSurnamePrefix() { 116 | return spfx; 117 | } 118 | 119 | public void setSurnamePrefix(String spfx) { 120 | this.spfx = spfx; 121 | } 122 | 123 | public String getNickname() { 124 | return nick; 125 | } 126 | 127 | public void setNickname(String nick) { 128 | this.nick = nick; 129 | } 130 | 131 | /** 132 | * Name has a type of ALIA when the GEDCOM had a ALIA sub-tag of INDI 133 | * @return The type. 134 | */ 135 | public String getType() { 136 | return _type; 137 | } 138 | 139 | public void setType(String _type) { 140 | this._type = _type; 141 | } 142 | 143 | public String getTypeTag() { 144 | return typeTag; 145 | } 146 | 147 | public void setTypeTag(String typeTag) { 148 | this.typeTag = typeTag; 149 | } 150 | 151 | public String getAka() { 152 | return _aka; 153 | } 154 | 155 | public void setAka(String _aka) { 156 | this._aka = _aka; 157 | } 158 | 159 | public String getAkaTag() { 160 | return akaTag; 161 | } 162 | 163 | public void setAkaTag(String akaTag) { 164 | this.akaTag = akaTag; 165 | } 166 | 167 | public String getRomn() { 168 | return romn; 169 | } 170 | 171 | public void setRomn(String romn) { 172 | this.romn = romn; 173 | } 174 | 175 | public String getRomnTag() { 176 | return romnTag; 177 | } 178 | 179 | public void setRomnTag(String romnTag) { 180 | this.romnTag = romnTag; 181 | } 182 | 183 | public String getFone() { 184 | return fone; 185 | } 186 | 187 | public void setFone(String fone) { 188 | this.fone = fone; 189 | } 190 | 191 | public String getFoneTag() { 192 | return foneTag; 193 | } 194 | 195 | public void setFoneTag(String foneTag) { 196 | this.foneTag = foneTag; 197 | } 198 | 199 | 200 | public String getMarriedName() { 201 | return _marrnm; 202 | } 203 | 204 | public void setMarriedName(String _marrnm) { 205 | this._marrnm = _marrnm; 206 | } 207 | 208 | public String getMarriedNameTag() { 209 | return marrnmTag; 210 | } 211 | 212 | public void setMarriedNameTag(String marrnmTag) { 213 | this.marrnmTag = marrnmTag; 214 | } 215 | 216 | public void accept(Visitor visitor) { 217 | if (visitor.visit(this)) { 218 | super.visitContainedObjects(visitor); 219 | visitor.endVisit(this); 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Here is a parser that converts GEDCOM files to a _de facto_ object model. 2 | 3 | See examples in [examples](examples/EXAMPLES.md) directory. 4 | 5 | De Facto object model 6 | --------------------- 7 | 8 | _De Facto_ means _"In fact or in practice; in actual use or existence, 9 | regardless of official or legal status."_ 10 | 11 | The parser converts GEDCOM files to an object model that includes all of the 12 | information found in the majority of GEDCOMs in the wild. 13 | The model includes additional tags over those in the official GEDCOM standard, 14 | because they are commonly used in GEDCOM files, and excludes a few tags from 15 | the official GEDCOM standard that are never or only rarely used. 16 | 17 | Further, most of the information from GEDCOMs that cannot be represnted directly 18 | in the model is represented as _extensions_ so it is not lost. 19 | 20 | The object model includes classes and attributes for every GEDCOM tag sequence 21 | appearing in more than 4% of the 7000 GEDCOMs submitted to 22 | [WeRelate.org](http://www.werelate.org) over the past five years, with the 23 | exception of four software-specific _schema_ tags: 24 | _SCHEMA, _EVENT_DEFN, _PLAC_DEFN, and _EVDEF, generated by _Family Tree Maker_, 25 | _Personal Ancestral File_, _Legacy_, and _RootsMagic_ respectively. 26 | 27 | Additional information found in the GEDCOMs, such as the schema tags mentioned 28 | above, is represented in the model by extending model objects with the ability to 29 | store lists of additional tags. 30 | 31 | The result is that object model directly represents _all_ of the information found 32 | in nearly 50% of the GEDCOMs. This may not sound like a large percentage, but 33 | due to the standard not being updated in over 10 years, nearly everyone adds 34 | their own custom tags. So having a relatively simple object model represent all 35 | tags found in nearly 50% of GEDCOMs is an accomplishment. 36 | 37 | If we also include the additional tags storable on model objects, the 38 | model is able to represent all of the information found in roughly 98% of the 39 | GEDCOMs submitted to WeRelate. 40 | 41 | The object model has the normal classes you'd expect for a GEDCOM-based object model: 42 | people, families, source citations, sources, notes, repositories, etc. 43 | The purpose of this project is not to propose a new object model, but to _expose_ 44 | the object model that is currently used by genealogists and make it easy to work with. 45 | 46 | A new proposed object model could use this project to convert existing GEDCOM files 47 | to the new model by first converting them to the de facto object model, then 48 | transforming the objects into the proposed object model. 49 | 50 | For more information about the object model, 51 | __[see the wiki](https://github.com/DallanQ/Gedcom/wiki)__. 52 | 53 | Extendible 54 | ---------- 55 | 56 | Developers can add custom extensions to the model. An extension might annotate 57 | people with warnings about suspicious dates for example. 58 | 59 | Parsers 60 | ------- 61 | 62 | The project includes three parsers: 63 | 64 | * from GEDCOM to the de facto object model (ModelParser): the object model and custom extensions 65 | can be saved as a json file, 66 | 67 | * from GEDCOM to a general tree-based object model that captures _everything_ within 68 | the GEDCOM file (TreeParser); the tree-based object model can also be saved as a json file, 69 | 70 | * from json to the de facto object model or the tree-based object model (JsonPrser), 71 | 72 | as well as a GEDCOM export tool: 73 | 74 | * from the de facto object model to GEDCOM (GedcomWriter). 75 | 76 | Round-trippable 77 | --------------- 78 | 79 | It is possible to do a round-trip: parse a GEDCOM file into the object model, 80 | save it to json, read it back from json, and export it back to GEDCOM, without 81 | any loss of information for the majority (over 94%) of GEDCOM files. 82 | 83 | The round-trip capability allows anyone to create programs that read gedcom files, 84 | do interesting things like generate warnings for suspicious dates in the GEDCOM, 85 | allow the user to correct the warnings, and save the information back as a GEDCOM 86 | file without loss of information from the original GEDCOM for the vast majority of 87 | GEDCOM files. 88 | 89 | Building 90 | -------- 91 | 92 | You'll need maven. `mvn install` creates the jar file. 93 | 94 | Tools 95 | ----- 96 | 97 | * _Gedcom2Json.java_ converts a GEDCOM to a JSON file using either the model parser or the tree parser. 98 | 99 | * _Gedcom2Gedcom.java_ round-trips a GEDCOM file or a directory of GEDCOM files from GEDCOM, to the 100 | object model, and back to GEDCOM (in a different directory). 101 | 102 | * _CompareGedcom2Gedcom.java_ does the thing as Gedcom2Gedcom, and then compares the resulting GEDCOM 103 | to the original, reporting any differences. 104 | 105 | * _GedcomAnalyzer.java_ parses a GEDCOM file or a directory of GEDCOM files and reports tags that are 106 | stored as extensions and errors. 107 | 108 | * _PlaceWriter.java_ extracts all places from a directory of GEDCOM files, as an example of walking 109 | the model using a Visitor pattern. This function was written in just a few lines due to the other 110 | classes in this project. 111 | 112 | The tools can be run using the `gedcom.jar` archive from the `target` directory: 113 | `java -cp target/gedcom.jar org.folg.gedcom.tools. ` 114 | 115 | For example: `java -cp target/gedcom.jar org.folg.gedcom.tools.Gedcom2Json -i mytree.ged -o mytree.json` 116 | 117 | Roadmap 118 | ------- 119 | 120 | * Once a GEDCOM has been imported, it still needs to be checked for referential integrity, and 121 | missing back-references must be added. For example, if person A references family B, but family B does 122 | not reference person A, we need to add a reference from family B to person A. 123 | 124 | * If we're willing to forego round-trippability, we can handle additional tags that are stored as 125 | extensions currently. For example, some GEDCOMs use FAMILY instead of FAM for family tags. We 126 | could create Family objects from FAMILY tags, just as we do with FAM tags, but they would be exported 127 | as FAM tags, not FAMILY tags. -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/Person.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * User: Dallan 25 | * Date: 12/25/11 26 | * 27 | * omit: Submitter, Reference type, Restriction, >1 anci, >1 desi 28 | * add: Uid, Address, phone, email, title (is a Name) 29 | * change: alia from xref to Name 30 | */ 31 | public class Person extends PersonFamilyCommonContainer { 32 | private String id = null; 33 | private List names = null; 34 | private List famc = null; 35 | private List fams = null; 36 | private List assos = null; 37 | private String anci = null; 38 | private String desi = null; 39 | private String rfn = null; 40 | private Address addr = null; 41 | private String phon = null; 42 | private String fax = null; 43 | private String email = null; 44 | private String emailTag = null; 45 | private String _www = null; 46 | private String wwwTag = null; 47 | 48 | public String getId() { 49 | return id; 50 | } 51 | 52 | public void setId(String id) { 53 | this.id = id; 54 | } 55 | 56 | public List getNames() { 57 | return names != null ? names : Collections.emptyList(); 58 | } 59 | 60 | public void setNames(List names) { 61 | this.names = names; 62 | } 63 | 64 | public void addName(Name name) { 65 | if (names == null) { 66 | names = new ArrayList(); 67 | } 68 | names.add(name); 69 | } 70 | 71 | private List getFamilies(Gedcom gedcom, List familyRefs) { 72 | List families = new ArrayList(); 73 | for (SpouseFamilyRef familyRef : familyRefs) { 74 | Family family = familyRef.getFamily(gedcom); 75 | if (family != null) { 76 | families.add(family); 77 | } 78 | } 79 | return families; 80 | } 81 | 82 | /** 83 | * Convenience function to dereference parent family refs 84 | * @param gedcom Gedcom 85 | * @return list of parent families 86 | */ 87 | public List getParentFamilies(Gedcom gedcom) { 88 | return getFamilies(gedcom, getParentFamilyRefs()); 89 | } 90 | 91 | public List getParentFamilyRefs() { 92 | return famc != null ? famc : Collections.emptyList(); 93 | } 94 | 95 | public void setParentFamilyRefs(List famc) { 96 | this.famc = famc; 97 | } 98 | 99 | public void addParentFamilyRef(ParentFamilyRef parentFamilyRef) { 100 | if (famc == null) { 101 | famc = new ArrayList(); 102 | } 103 | famc.add(parentFamilyRef); 104 | } 105 | 106 | /** 107 | * Convenience function to dereference spouse family refs 108 | * @param gedcom Gedcom 109 | * @return list of spouse families 110 | */ 111 | public List getSpouseFamilies(Gedcom gedcom) { 112 | return getFamilies(gedcom, getSpouseFamilyRefs()); 113 | } 114 | 115 | public List getSpouseFamilyRefs() { 116 | return fams != null ? fams : Collections.emptyList(); 117 | } 118 | 119 | public void setSpouseFamilyRefs(List fams) { 120 | this.fams = fams; 121 | } 122 | 123 | public void addSpouseFamilyRef(SpouseFamilyRef spouseFamilyRef) { 124 | if (fams == null) { 125 | fams = new ArrayList(); 126 | } 127 | fams.add(spouseFamilyRef); 128 | } 129 | 130 | public List getAssociations() { 131 | return assos != null ? assos : Collections.emptyList(); 132 | } 133 | 134 | public void setAssociations(List assos) { 135 | this.assos = assos; 136 | } 137 | 138 | public void addAssociation(Association asso) { 139 | if (assos == null) { 140 | assos = new ArrayList(); 141 | } 142 | assos.add(asso); 143 | } 144 | 145 | public String getAncestorInterestSubmitterRef() { 146 | return anci; 147 | } 148 | 149 | public void setAncestorInterestSubmitterRef(String anci) { 150 | this.anci = anci; 151 | } 152 | 153 | public String getDescendantInterestSubmitterRef() { 154 | return desi; 155 | } 156 | 157 | public void setDescendantInterestSubmitterRef(String desi) { 158 | this.desi = desi; 159 | } 160 | 161 | public String getRecordFileNumber() { 162 | return rfn; 163 | } 164 | 165 | public void setRecordFileNumber(String rfn) { 166 | this.rfn = rfn; 167 | } 168 | 169 | public Address getAddress() { 170 | return addr; 171 | } 172 | 173 | public void setAddress(Address addr) { 174 | this.addr = addr; 175 | } 176 | 177 | public String getPhone() { 178 | return phon; 179 | } 180 | 181 | public void setPhone(String phon) { 182 | this.phon = phon; 183 | } 184 | 185 | public String getFax() { 186 | return fax; 187 | } 188 | 189 | public void setFax(String fax) { 190 | this.fax = fax; 191 | } 192 | 193 | public String getEmail() { 194 | return email; 195 | } 196 | 197 | public void setEmail(String email) { 198 | this.email = email; 199 | } 200 | 201 | public String getEmailTag() { 202 | return emailTag; 203 | } 204 | 205 | public void setEmailTag(String emailTag) { 206 | this.emailTag = emailTag; 207 | } 208 | 209 | public String getWww() { 210 | return _www; 211 | } 212 | 213 | public void setWww(String www) { 214 | this._www = www; 215 | } 216 | 217 | public String getWwwTag() { 218 | return wwwTag; 219 | } 220 | 221 | public void setWwwTag(String wwwTag) { 222 | this.wwwTag = wwwTag; 223 | } 224 | 225 | public void accept(Visitor visitor) { 226 | if (visitor.visit(this)) { 227 | for (Name name : getNames()) { 228 | name.accept(visitor); 229 | } 230 | for (ParentFamilyRef parentFamilyRef : getParentFamilyRefs()) { 231 | parentFamilyRef.accept(visitor); 232 | } 233 | for (SpouseFamilyRef spouseFamilyRef : getSpouseFamilyRefs()) { 234 | spouseFamilyRef.accept(visitor); 235 | } 236 | for (Association association : getAssociations()) { 237 | association.accept(visitor); 238 | } 239 | if (addr != null) { 240 | addr.accept(visitor); 241 | } 242 | super.visitContainedObjects(visitor); 243 | visitor.endVisit(this); 244 | } 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /src/test/java/org/folg/gedcom/parser/ModelParserTest.java: -------------------------------------------------------------------------------- 1 | package org.folg.gedcom.parser; 2 | 3 | import org.folg.gedcom.model.*; 4 | import org.testng.annotations.Test; 5 | 6 | import java.io.File; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | import java.io.Reader; 10 | import java.net.URL; 11 | 12 | import static org.testng.Assert.assertEquals; 13 | import static org.testng.Assert.assertNotNull; 14 | 15 | 16 | public class ModelParserTest { 17 | @Test 18 | public void testAddressStructureParsing() throws Exception { 19 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case001-AddressStructure.ged"); 20 | File gedcomFile = new File(gedcomUrl.toURI()); 21 | ModelParser modelParser = new ModelParser(); 22 | 23 | Gedcom gedcom = modelParser.parseGedcom(gedcomFile); 24 | assertNotNull(gedcom); 25 | 26 | gedcom.createIndexes(); 27 | 28 | assertNotNull(gedcom.getHeader()); 29 | assertNotNull(gedcom.getHeader().getGenerator()); 30 | GeneratorCorporation generatorCorporation = gedcom.getHeader().getGenerator().getGeneratorCorporation(); 31 | assertNotNull(generatorCorporation); 32 | assertEquals(generatorCorporation.getAddress().getValue() 33 | , "5000 MyCorpCampus Dr\n" + 34 | "Hometown, ZZ 99999\n" + 35 | "United States"); 36 | assertEquals(generatorCorporation.getAddress().getAddressLine1(), "__ADR1_VALUE__"); 37 | assertEquals(generatorCorporation.getAddress().getAddressLine2(), "__ADR2_VALUE__"); 38 | assertEquals(generatorCorporation.getAddress().getAddressLine3(), "5000 MyCorpCampus Dr"); 39 | assertEquals(generatorCorporation.getAddress().getCity(), "Hometown"); 40 | assertEquals(generatorCorporation.getAddress().getState(), "ZZ"); 41 | assertEquals(generatorCorporation.getAddress().getPostalCode(), "99999"); 42 | assertEquals(generatorCorporation.getAddress().getCountry(), "United States"); 43 | assertEquals(generatorCorporation.getPhone(), "866-000-0000"); 44 | assertEquals(generatorCorporation.getEmail(), "info@mycorporation.com"); 45 | assertEquals(generatorCorporation.getFax(), "866-111-1111"); 46 | assertEquals(generatorCorporation.getWww(), "http://www.mycorporation.org/"); 47 | 48 | Submitter submitter = gedcom.getSubmitter("SUB1"); 49 | assertNotNull(submitter); 50 | assertEquals(submitter.getAddress().getValue() 51 | , "5000 MyCorpCampus Dr\n" + 52 | "Hometown, ZZ 99999\n" + 53 | "United States"); 54 | assertEquals(submitter.getAddress().getAddressLine1(), "__ADR1_VALUE__"); 55 | assertEquals(submitter.getAddress().getAddressLine2(), "__ADR2_VALUE__"); 56 | assertEquals(submitter.getAddress().getAddressLine3(), "5000 MyCorpCampus Dr"); 57 | assertEquals(submitter.getAddress().getCity(), "Hometown"); 58 | assertEquals(submitter.getAddress().getState(), "ZZ"); 59 | assertEquals(submitter.getAddress().getPostalCode(), "99999"); 60 | assertEquals(submitter.getAddress().getCountry(), "United States"); 61 | assertEquals(submitter.getPhone(), "866-000-0000"); 62 | assertEquals(submitter.getEmail(), "info@mycorporation.com"); 63 | assertEquals(submitter.getFax(), "866-111-1111"); 64 | assertEquals(submitter.getWww(), "http://www.mycorporation.org/"); 65 | 66 | assertNotNull(gedcom.getPeople()); 67 | assertEquals(gedcom.getPeople().size(), 1); 68 | Person person = gedcom.getPeople().get(0); 69 | assertNotNull(person); 70 | assertEquals(person.getAddress().getValue() 71 | , "5000 MyCorpCampus Dr\n" + 72 | "Hometown, ZZ 99999\n" + 73 | "United States"); 74 | assertEquals(person.getAddress().getAddressLine1(), "__ADR1_VALUE__"); 75 | assertEquals(person.getAddress().getAddressLine2(), "__ADR2_VALUE__"); 76 | assertEquals(person.getAddress().getAddressLine3(), "5000 MyCorpCampus Dr"); 77 | assertEquals(person.getAddress().getCity(), "Hometown"); 78 | assertEquals(person.getAddress().getState(), "ZZ"); 79 | assertEquals(person.getAddress().getPostalCode(), "99999"); 80 | assertEquals(person.getAddress().getCountry(), "United States"); 81 | assertEquals(person.getPhone(), "866-000-0000"); 82 | assertEquals(person.getEmail(), "info@mycorporation.com"); 83 | assertEquals(person.getFax(), "866-111-1111"); 84 | assertEquals(person.getWww(), "http://www.mycorporation.org/"); 85 | 86 | assertNotNull(person.getEventsFacts()); 87 | assertEquals(person.getEventsFacts().size(), 1); 88 | EventFact eventFact = person.getEventsFacts().get(0); 89 | assertEquals(eventFact.getAddress().getValue() 90 | , "Arlington National Cemetery\n" + 91 | "State Hwy 110 & Memorial Dr\n" + 92 | "Arlington, VA 22211\n" + 93 | "United States"); 94 | assertEquals(eventFact.getAddress().getAddressLine1(), "__ADR1_VALUE__"); 95 | assertEquals(eventFact.getAddress().getAddressLine2(), "__ADR2_VALUE__"); 96 | assertEquals(eventFact.getAddress().getAddressLine3(), "__ADR3_VALUE__"); 97 | assertEquals(eventFact.getAddress().getCity(), "Arlington"); 98 | assertEquals(eventFact.getAddress().getState(), "VA"); 99 | assertEquals(eventFact.getAddress().getPostalCode(), "22211"); 100 | assertEquals(eventFact.getAddress().getCountry(), "United States"); 101 | assertEquals(eventFact.getPhone(), "877-907-8585"); 102 | assertEquals(eventFact.getEmail(), "info@arlingtoncemetery.mil"); 103 | assertEquals(eventFact.getFax(), "877-111-1111"); 104 | assertEquals(eventFact.getWww(), "http://www.arlingtoncemetery.mil/"); 105 | 106 | assertNotNull(gedcom.getRepositories()); 107 | assertEquals(gedcom.getRepositories().size(), 1); 108 | Repository repository = gedcom.getRepositories().get(0); 109 | assertEquals(repository.getAddress().getValue() 110 | , "5000 MyCorpCampus Dr\n" + 111 | "Hometown, ZZ 99999\n" + 112 | "United States"); 113 | assertEquals(repository.getAddress().getAddressLine1(), "__ADR1_VALUE__"); 114 | assertEquals(repository.getAddress().getAddressLine2(), "__ADR2_VALUE__"); 115 | assertEquals(repository.getAddress().getAddressLine3(), "5000 MyCorpCampus Dr"); 116 | assertEquals(repository.getAddress().getCity(), "Hometown"); 117 | assertEquals(repository.getAddress().getState(), "ZZ"); 118 | assertEquals(repository.getAddress().getPostalCode(), "99999"); 119 | assertEquals(repository.getAddress().getCountry(), "United States"); 120 | assertEquals(repository.getPhone(), "866-000-0000"); 121 | assertEquals(repository.getEmail(), "info@mycorporation.com"); 122 | assertEquals(repository.getFax(), "866-111-1111"); 123 | assertEquals(repository.getWww(), "https://www.mycorporation.com/"); 124 | } 125 | 126 | @Test 127 | public void testParse_withInputStream() throws Exception { 128 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case001-AddressStructure.ged"); 129 | ModelParser modelParser = new ModelParser(); 130 | 131 | InputStream is = gedcomUrl.openStream(); 132 | assertNotNull(is); 133 | 134 | Gedcom gedcom = modelParser.parseGedcom(is); 135 | assertNotNull(gedcom); 136 | } 137 | 138 | @Test 139 | public void testParse_withReader() throws Exception { 140 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case001-AddressStructure.ged"); 141 | ModelParser modelParser = new ModelParser(); 142 | 143 | InputStream is = gedcomUrl.openStream(); 144 | assertNotNull(is); 145 | 146 | Reader reader = new InputStreamReader(is, "UTF-8"); 147 | 148 | Gedcom gedcom = modelParser.parseGedcom(reader); 149 | assertNotNull(gedcom); 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /src/test/java/org/folg/gedml/GedcomParserTest.java: -------------------------------------------------------------------------------- 1 | package org.folg.gedml; 2 | 3 | import org.gedml.GedcomParser; 4 | import org.testng.annotations.Test; 5 | import org.xml.sax.*; 6 | 7 | import java.io.*; 8 | import java.net.URL; 9 | import java.nio.charset.Charset; 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | import static org.testng.Assert.assertEquals; 15 | import static org.testng.Assert.assertFalse; 16 | import static org.testng.Assert.assertTrue; 17 | 18 | public class GedcomParserTest { 19 | 20 | class MockContentHandler implements ContentHandler { 21 | 22 | final List tags; 23 | 24 | MockContentHandler() { 25 | this.tags = new ArrayList(); 26 | } 27 | 28 | @Override 29 | public void setDocumentLocator(Locator locator) { 30 | 31 | } 32 | 33 | @Override 34 | public void startDocument() { 35 | 36 | } 37 | 38 | @Override 39 | public void endDocument() { 40 | 41 | } 42 | 43 | @Override 44 | public void startPrefixMapping(String prefix, String uri) { 45 | 46 | } 47 | 48 | @Override 49 | public void endPrefixMapping(String prefix) { 50 | 51 | } 52 | 53 | @Override 54 | public void startElement(String uri, String localName, String qName, Attributes atts) { 55 | this.tags.add(localName); 56 | } 57 | 58 | @Override 59 | public void endElement(String uri, String localName, String qName) { 60 | 61 | } 62 | 63 | @Override 64 | public void characters(char[] ch, int start, int length) { 65 | 66 | } 67 | 68 | @Override 69 | public void ignorableWhitespace(char[] ch, int start, int length) { 70 | 71 | } 72 | 73 | @Override 74 | public void processingInstruction(String target, String data) { 75 | 76 | } 77 | 78 | @Override 79 | public void skippedEntity(String name) { 80 | 81 | } 82 | 83 | } 84 | 85 | class MockErrorHandler implements ErrorHandler { 86 | 87 | @Override 88 | public void warning(SAXParseException exception) { 89 | 90 | } 91 | 92 | @Override 93 | public void error(SAXParseException exception) { 94 | 95 | } 96 | 97 | @Override 98 | public void fatalError(SAXParseException exception) { 99 | 100 | } 101 | } 102 | 103 | class MockReader extends Reader { 104 | 105 | private final StringReader internalReader; 106 | boolean readWasCalled = false; 107 | boolean closeWasCalled = false; 108 | 109 | MockReader(String chars) { 110 | this.internalReader = new StringReader(chars); 111 | } 112 | 113 | @Override 114 | public int read(char[] cbuf, int off, int len) throws IOException { 115 | this.readWasCalled = true; 116 | return internalReader.read(cbuf, off, len); 117 | } 118 | 119 | @Override 120 | public void close() { 121 | this.closeWasCalled = true; 122 | internalReader.close(); 123 | } 124 | } 125 | 126 | class MockInputStream extends InputStream { 127 | 128 | private final ByteArrayInputStream internalStream; 129 | boolean readWasCalled = false; 130 | 131 | MockInputStream(String chars) { 132 | this.internalStream = new ByteArrayInputStream(chars.getBytes(Charset.forName("UTF-8"))); 133 | } 134 | 135 | @Override 136 | public int read() { 137 | this.readWasCalled = true; 138 | return internalStream.read(); 139 | } 140 | } 141 | 142 | @Test 143 | public void testParse_withInputSourceAndCharacterStream() throws Exception { 144 | MockContentHandler contentHandler = new MockContentHandler(); 145 | MockErrorHandler errorHandler = new MockErrorHandler(); 146 | 147 | String mockSystemId = "Mock system Id"; 148 | MockReader characterStream = new MockReader("0 HEAD\n1 CHAR UTF-8\n0 @I1@ INDI\n"); 149 | MockInputStream byteStream = new MockInputStream("I should not get called!"); 150 | InputSource input = new InputSource(); 151 | input.setCharacterStream(characterStream); 152 | input.setByteStream(byteStream); 153 | input.setSystemId(mockSystemId); 154 | 155 | GedcomParser parser = new GedcomParser(); 156 | parser.setContentHandler(contentHandler); 157 | parser.setErrorHandler(errorHandler); 158 | parser.parse(input); 159 | 160 | assertTrue(characterStream.readWasCalled, "Failed to read character stream"); 161 | assertTrue(characterStream.closeWasCalled, "Failed to close character stream"); 162 | assertFalse(byteStream.readWasCalled, "Should not have read byte stream"); 163 | assertEquals(parser.getSystemId(), mockSystemId); 164 | 165 | assertEquals(contentHandler.tags, Arrays.asList("GED", "HEAD", "CHAR", "INDI")); 166 | } 167 | 168 | @Test 169 | public void testParse_withInputSourceAndByteStream() throws Exception { 170 | MockContentHandler contentHandler = new MockContentHandler(); 171 | MockErrorHandler errorHandler = new MockErrorHandler(); 172 | 173 | String mockSystemId = "Mock system Id"; 174 | MockReader characterStream = new MockReader("I should not get called!"); 175 | MockInputStream byteStream = new MockInputStream("0 HEAD\n1 CHAR UTF-8\n0 @I1@ INDI\n"); 176 | InputSource input = new InputSource(); 177 | input.setByteStream(byteStream); 178 | input.setSystemId(mockSystemId); 179 | 180 | GedcomParser parser = new GedcomParser(); 181 | parser.setContentHandler(contentHandler); 182 | parser.setErrorHandler(errorHandler); 183 | parser.parse(input); 184 | 185 | assertFalse(characterStream.readWasCalled, "Should not have read character stream"); 186 | assertFalse(characterStream.closeWasCalled, "Should not have closed character stream"); 187 | assertTrue(byteStream.readWasCalled, "Failed to read byte stream"); 188 | assertEquals(parser.getSystemId(), mockSystemId); 189 | 190 | assertEquals(contentHandler.tags, Arrays.asList("GED", "HEAD", "CHAR", "INDI")); 191 | } 192 | 193 | @Test 194 | public void testParse_withInputSourceAndSystemId() throws Exception { 195 | MockContentHandler contentHandler = new MockContentHandler(); 196 | MockErrorHandler errorHandler = new MockErrorHandler(); 197 | 198 | URL gedcomUrl = this.getClass().getClassLoader().getResource("Case001-AddressStructure.ged"); 199 | String expectedSystemId = gedcomUrl.toString(); 200 | MockReader characterStream = new MockReader("I should not get called!"); 201 | MockInputStream byteStream = new MockInputStream("0 HEAD\n1 CHAR UTF-8\n0 @I1@ INDI\n"); 202 | InputSource input = new InputSource(); 203 | input.setSystemId(expectedSystemId); 204 | 205 | GedcomParser parser = new GedcomParser(); 206 | parser.setContentHandler(contentHandler); 207 | parser.setErrorHandler(errorHandler); 208 | parser.parse(input); 209 | 210 | assertFalse(characterStream.readWasCalled, "Should not have read character stream"); 211 | assertFalse(characterStream.closeWasCalled, "Should not have closed character stream"); 212 | assertFalse(byteStream.readWasCalled, "Failed to read byte stream"); 213 | assertEquals(parser.getSystemId(), expectedSystemId); 214 | 215 | assertEquals(contentHandler.tags.size(), 91); 216 | assertEquals(contentHandler.tags.get(0), "GED"); 217 | assertEquals(contentHandler.tags.get(1), "HEAD"); 218 | } 219 | 220 | } 221 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | org.familysearch.gedcom 4 | gedcom 5 | 1.15.0-SNAPSHOT 6 | jar 7 | GEDCOM 5.x Reader/Writer 8 | GEDCOM 5.x Reader/Writer 9 | https://github.com/FamilySearch/Gedcom 10 | 11 | 12 | UTF-8 13 | 14 | 6.5.2 15 | 1.6.4 16 | true 17 | 18 | 19 | 20 | scm:git:git@github.com:FamilySearch/gedcom5-java.git 21 | scm:git:git@github.com:FamilySearch/gedcom5-java.git 22 | https://github.com/FamilySearch/gedcom5-java 23 | 1.12.0 24 | 25 | 26 | 27 | 28 | Dallan Quass 29 | dallan@werelate.org 30 | 31 | 32 | Michael Kay 33 | mhkay@iclway.co.uk 34 | 35 | 36 | Lynn Monson 37 | http://lmonson.com 38 | 39 | 40 | Nathan Powell 41 | nathanielpowell.org 42 | 43 | 44 | Ryan Heaton 45 | heatonra@familysearch.org 46 | 47 | 48 | 49 | 50 | 51 | Dallan Quass 52 | dallan@werelate.org 53 | 54 | 55 | Ryan Heaton 56 | heatonra@familysearch.org 57 | 58 | 59 | 60 | 61 | 62 | Th Apache License, Version 2.0 63 | http://www.apache.org/licenses/LICENSE-2.0 64 | 65 | 66 | 67 | 68 | 69 | 70 | org.sonatype.plugins 71 | nexus-staging-maven-plugin 72 | 1.6.5 73 | true 74 | 75 | ossrh 76 | https://oss.sonatype.org/ 77 | true 78 | 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-release-plugin 83 | 2.5.1 84 | 85 | true 86 | false 87 | release 88 | deploy 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-surefire-plugin 94 | 2.10 95 | 96 | ${skipTests} 97 | 98 | 99 | 100 | maven-compiler-plugin 101 | 2.3.2 102 | 103 | 1.8 104 | 1.8 105 | 106 | 107 | 108 | org.apache.maven.plugins 109 | maven-assembly-plugin 110 | 3.3.0 111 | 112 | 113 | with-deps 114 | package 115 | 116 | single 117 | 118 | 119 | false 120 | false 121 | ${project.artifactId} 122 | 123 | jar-with-dependencies 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | release 135 | 136 | 137 | 138 | org.apache.maven.plugins 139 | maven-javadoc-plugin 140 | 2.10.1 141 | 142 | 143 | attach-javadocs 144 | 145 | jar 146 | 147 | 148 | 149 | 150 | 151 | org.apache.maven.plugins 152 | maven-source-plugin 153 | 2.2.1 154 | 155 | 156 | attach-sources 157 | package 158 | 159 | jar 160 | 161 | 162 | 163 | 164 | 165 | org.kohsuke 166 | pgp-maven-plugin 167 | 1.1 168 | 169 | 170 | sign-artifacts 171 | verify 172 | 173 | sign 174 | 175 | 176 | 177 | 178 | keyfile:${env.PGP_SECRET_KEYFILE} 179 | literal: 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | com.google.code.gson 190 | gson 191 | 2.8.9 192 | compile 193 | 194 | 195 | args4j 196 | args4j 197 | 2.0.16 198 | 199 | 200 | org.slf4j 201 | slf4j-jdk14 202 | 1.6.4 203 | provided 204 | 205 | 206 | 207 | 208 | org.testng 209 | testng 210 | ${testng.version} 211 | test 212 | 213 | 214 | org.slf4j 215 | slf4j-api 216 | ${slf-api.version} 217 | 218 | 219 | 220 | 221 | 222 | ossrh 223 | https://oss.sonatype.org/content/repositories/snapshots 224 | 225 | 226 | ossrh 227 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 228 | 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /src/main/java/org/folg/gedcom/model/GedcomTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Foundation for On-Line Genealogy, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.folg.gedcom.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | /** 26 | * Simple data structure for a gedcom node - json-friendly 27 | * User: Dallan 28 | * Date: 12/23/11 29 | */ 30 | public class GedcomTag implements Comparable { 31 | private static final Logger logger = LoggerFactory.getLogger("org.folg.gedcom.model"); 32 | 33 | private String id; 34 | private String tag; 35 | private String ref; 36 | private String value; 37 | private String parentTagName; // used by ModelParser to store tags under string fields 38 | private List children; 39 | 40 | public GedcomTag(String id, String tag, String ref) { 41 | this.id = id; 42 | this.tag = tag; 43 | this.ref = ref; 44 | this.value = null; 45 | this.parentTagName = null; 46 | this.children = null; 47 | } 48 | 49 | public String getId() { 50 | return id; 51 | } 52 | 53 | public void setId(String id) { 54 | this.id = id; 55 | } 56 | 57 | public String getTag() { 58 | return tag; 59 | } 60 | 61 | public void setTag(String tag) { 62 | this.tag = tag; 63 | } 64 | 65 | public String getRef() { 66 | return ref; 67 | } 68 | 69 | public void setRef(String ref) { 70 | this.ref = ref; 71 | } 72 | 73 | public String getParentTagName() { 74 | return parentTagName; 75 | } 76 | 77 | public void setParentTagName(String parentTagName) { 78 | this.parentTagName = parentTagName; 79 | } 80 | 81 | public String getValue() { 82 | return value; 83 | } 84 | 85 | public void setValue(String value) { 86 | this.value = value; 87 | } 88 | 89 | public void appendValue(String value) { 90 | if (this.value == null) { 91 | this.value = value; 92 | } else { 93 | this.value += value; 94 | } 95 | } 96 | 97 | public List getChildren() { 98 | return children != null ? children : Collections.emptyList(); 99 | } 100 | 101 | public void setChildren(List children) { 102 | this.children = children; 103 | } 104 | 105 | public void addChild(GedcomTag child) { 106 | if (children == null) { 107 | children = new ArrayList(); 108 | } 109 | children.add(child); 110 | } 111 | 112 | private ArrayList getSortedChildren(List children) { 113 | ArrayList sortedChildren = new ArrayList(children.size()); 114 | sortedChildren.addAll(children); 115 | Collections.sort(sortedChildren); 116 | return sortedChildren; 117 | } 118 | 119 | public boolean isEmpty() { 120 | return (id == null || id.length() == 0) && 121 | (ref == null || ref.length() == 0) && 122 | (parentTagName == null || parentTagName.length() == 0) && 123 | (value == null || value.length() == 0) && 124 | (children == null || children.size() == 0); 125 | } 126 | 127 | @Override 128 | public boolean equals(Object o) { 129 | if (this == o) return true; 130 | if (o == null || getClass() != o.getClass()) return false; 131 | 132 | GedcomTag gt = (GedcomTag) o; 133 | 134 | if (!(tag == null ? "" : tag).equals(gt.tag == null ? "" : gt.tag)) { 135 | return false; 136 | } 137 | if (!(id == null ? "" : id).equals(gt.id == null ? "" : gt.id)) { 138 | return false; 139 | } 140 | if (!(ref == null ? "" : ref).equals(gt.ref == null ? "" : gt.ref)) { 141 | return false; 142 | } 143 | if (!(parentTagName == null ? "" : parentTagName).equals(gt.parentTagName == null ? "" : gt.parentTagName)) { 144 | return false; 145 | } 146 | if (!(value == null ? "" : value).equals(gt.value == null ? "" : gt.value)) { 147 | return false; 148 | } 149 | if (getChildren().size() != gt.getChildren().size()) { 150 | return false; 151 | } 152 | 153 | // this is horribly inefficient - if we're going to do this a lot during production we need to rewrite it 154 | // but as-is, it's convenient for debugging 155 | ArrayList sortedChildren = getSortedChildren(getChildren()); 156 | ArrayList compareChildren = getSortedChildren(gt.getChildren()); 157 | 158 | for (int indx = 0; indx < sortedChildren.size(); indx++) { 159 | if (!sortedChildren.get(indx).equals(compareChildren.get(indx))) { 160 | logger.info("!tag="+sortedChildren.get(indx).toString()+"<=>"+compareChildren.get(indx).toString()); 161 | return false; 162 | } 163 | } 164 | return true; 165 | } 166 | 167 | @Override 168 | public int hashCode() { 169 | int result = id != null && id.length() > 0 ? id.hashCode() : 0; 170 | result = 31 * result + (tag != null && tag.length() > 0 ? tag.hashCode() : 0); 171 | result = 31 * result + (ref != null && ref.length() > 0 ? ref.hashCode() : 0); 172 | result = 31 * result + (parentTagName != null && parentTagName.length() > 0 ? parentTagName.hashCode() : 0); 173 | result = 31 * result + (value != null && value.length() > 0 ? value.hashCode() : 0); 174 | 175 | // Calculate the children hash code based on the actual value of each child hashcode 176 | // result = 31 * result + (children != null ? children.hashCode() : 0); 177 | if (children != null) { 178 | for (GedcomTag child : getSortedChildren(children)) { 179 | result = 31 * result + child.hashCode(); 180 | } 181 | } 182 | 183 | return result; 184 | } 185 | 186 | @Override 187 | public String toString() { 188 | StringBuilder buf = new StringBuilder(); 189 | if (tag != null) { 190 | buf.append(" tag:"+tag); 191 | } 192 | if (id != null) { 193 | buf.append(" id:"+id); 194 | } 195 | if (ref != null) { 196 | buf.append(" ref:"+ref); 197 | } 198 | if (parentTagName != null) { 199 | buf.append(" parentTag:"+parentTagName); 200 | } 201 | if (value != null) { 202 | buf.append(" value:"+value); 203 | } 204 | if (children != null) { 205 | buf.append(" ["); 206 | for (GedcomTag child : getSortedChildren(children)) { 207 | buf.append(child.toString()); 208 | } 209 | buf.append(" ]"); 210 | } 211 | return buf.toString(); 212 | } 213 | 214 | public int compareTo(GedcomTag tag) { 215 | int c = (getTag() == null ? "" : getTag()).compareTo(tag.getTag() == null ? "" : tag.getTag()); 216 | if (c != 0) return c; 217 | c = (getId() == null ? "" : getId()).compareTo(tag.getId() == null ? "" : tag.getId()); 218 | if (c != 0) return c; 219 | c = (getRef() == null ? "" : getRef()).compareTo(tag.getRef() == null ? "" : tag.getRef()); 220 | if (c != 0) return c; 221 | c = (getParentTagName() == null ? "" : getParentTagName()).compareTo(tag.getParentTagName() == null ? "" : tag.getParentTagName()); 222 | if (c != 0) return c; 223 | c = (getValue() == null ? "" : getValue()).compareTo(tag.getValue() == null ? "" : tag.getValue()); 224 | if (c != 0) return c; 225 | // compare hashcode because that compares children as well 226 | return new Integer(this.hashCode()).compareTo(new Integer(tag.hashCode())); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/test/java/org/folg/gedcom/parser/JsonParserTest.java: -------------------------------------------------------------------------------- 1 | package org.folg.gedcom.parser; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | import org.folg.gedcom.model.*; 7 | import org.testng.annotations.Test; 8 | 9 | import java.io.*; 10 | import java.nio.charset.Charset; 11 | import java.util.Collections; 12 | 13 | import static org.testng.Assert.*; 14 | 15 | public class JsonParserTest { 16 | 17 | @Test 18 | public void testToJson_gedcom() { 19 | String expectedLanguage = "English"; 20 | String expectedCopyright = "2019"; 21 | String expectedName = "Bobby /ROBERTSON/"; 22 | String expectedId = "I1"; 23 | 24 | Header header = new Header(); 25 | header.setLanguage(expectedLanguage); 26 | header.setCopyright(expectedCopyright); 27 | 28 | Name name = new Name(); 29 | name.setValue(expectedName); 30 | Person individual = new Person(); 31 | individual.setId(expectedId); 32 | individual.setNames(Collections.singletonList(name)); 33 | 34 | Gedcom gedcom = new Gedcom(); 35 | gedcom.setHeader(header); 36 | gedcom.addPerson(individual); 37 | 38 | JsonParser jsonParser = new JsonParser(); 39 | String json = jsonParser.toJson(gedcom); 40 | assertNotNull(json); 41 | 42 | com.google.gson.JsonParser gsonParser = new com.google.gson.JsonParser(); 43 | JsonElement jsonElement = gsonParser.parse(json); 44 | assertNotNull(jsonElement); 45 | assertTrue(jsonElement.isJsonObject()); 46 | 47 | JsonObject jsonObject = jsonElement.getAsJsonObject(); 48 | 49 | JsonElement head = jsonObject.get("head"); 50 | assertNotNull(head); 51 | assertTrue(head.isJsonObject()); 52 | 53 | JsonObject headObj = head.getAsJsonObject(); 54 | 55 | JsonElement copr = headObj.get("copr"); 56 | assertNotNull(copr); 57 | assertTrue(copr.isJsonPrimitive()); 58 | assertEquals(expectedCopyright, copr.getAsString()); 59 | 60 | JsonElement lang = headObj.get("lang"); 61 | assertNotNull(lang); 62 | assertTrue(lang.isJsonPrimitive()); 63 | assertEquals(expectedLanguage, lang.getAsString()); 64 | 65 | JsonElement people = jsonObject.get("people"); 66 | assertNotNull(people); 67 | assertTrue(people.isJsonArray()); 68 | 69 | JsonArray peopleArray = people.getAsJsonArray(); 70 | assertEquals(1, peopleArray.size()); 71 | 72 | JsonElement indi = peopleArray.get(0); 73 | assertNotNull(indi); 74 | assertTrue(indi.isJsonObject()); 75 | 76 | JsonObject indiObj = indi.getAsJsonObject(); 77 | 78 | JsonElement id = indiObj.get("id"); 79 | assertNotNull(id); 80 | assertTrue(id.isJsonPrimitive()); 81 | assertEquals(expectedId, id.getAsString()); 82 | 83 | JsonElement names = indiObj.get("names"); 84 | assertNotNull(names); 85 | assertTrue(names.isJsonArray()); 86 | 87 | JsonArray namesArray = names.getAsJsonArray(); 88 | assertEquals(1, namesArray.size()); 89 | 90 | JsonElement nameElt = namesArray.get(0); 91 | assertNotNull(nameElt); 92 | assertTrue(nameElt.isJsonObject()); 93 | 94 | JsonObject nameObj = nameElt.getAsJsonObject(); 95 | 96 | JsonElement nameValue = nameObj.get("value"); 97 | assertNotNull(nameValue); 98 | assertTrue(nameValue.isJsonPrimitive()); 99 | assertEquals(expectedName, nameValue.getAsString()); 100 | } 101 | 102 | @Test 103 | public void testToJson_gedcomTags() { 104 | GedcomTag tag = new GedcomTag("", "head", ""); 105 | JsonParser jsonParser = new JsonParser(); 106 | String json = jsonParser.toJson(Collections.singletonList(tag)); 107 | 108 | assertGedcomTagsJson(json); 109 | } 110 | 111 | @Test 112 | public void testFromJson() { 113 | Header header = new Header(); 114 | header.setLanguage("English"); 115 | header.setCopyright("2019"); 116 | 117 | Gedcom gedcom = new Gedcom(); 118 | gedcom.setHeader(header); 119 | 120 | JsonParser jsonParser = new JsonParser(); 121 | String json = jsonParser.toJson(gedcom); 122 | 123 | assertGedcomJson(gedcom, json); 124 | } 125 | 126 | @Test 127 | public void testFromJson_withReader() { 128 | Header header = new Header(); 129 | header.setLanguage("English"); 130 | header.setCopyright("2019"); 131 | 132 | Gedcom gedcom = new Gedcom(); 133 | gedcom.setHeader(header); 134 | 135 | JsonParser jsonParser = new JsonParser(); 136 | String json = jsonParser.toJson(gedcom); 137 | 138 | StringReader reader = new StringReader(json); 139 | Gedcom actualGedcom = jsonParser.fromJson(reader); 140 | assertNotNull(actualGedcom); 141 | assertEquals(gedcom.getHeader().getLanguage(), actualGedcom.getHeader().getLanguage()); 142 | assertEquals(gedcom.getHeader().getCopyright(), actualGedcom.getHeader().getCopyright()); 143 | } 144 | 145 | @Test 146 | public void testFromJson_withInputStream() { 147 | Header header = new Header(); 148 | header.setLanguage("English"); 149 | header.setCopyright("2019"); 150 | 151 | Gedcom gedcom = new Gedcom(); 152 | gedcom.setHeader(header); 153 | 154 | JsonParser jsonParser = new JsonParser(); 155 | String json = jsonParser.toJson(gedcom); 156 | 157 | ByteArrayInputStream is = new ByteArrayInputStream(json.getBytes(Charset.forName("UTF-8"))); 158 | Gedcom actualGedcom = jsonParser.fromJson(is); 159 | assertNotNull(actualGedcom); 160 | assertEquals(gedcom.getHeader().getLanguage(), actualGedcom.getHeader().getLanguage()); 161 | assertEquals(gedcom.getHeader().getCopyright(), actualGedcom.getHeader().getCopyright()); 162 | } 163 | 164 | @Test 165 | public void testWrite_withGedcomAndWriter() { 166 | Header header = new Header(); 167 | header.setLanguage("English"); 168 | header.setCopyright("2019"); 169 | 170 | Gedcom gedcom = new Gedcom(); 171 | gedcom.setHeader(header); 172 | 173 | Writer writer = new StringWriter(); 174 | JsonParser jsonParser = new JsonParser(); 175 | jsonParser.write(gedcom, writer); 176 | 177 | assertGedcomJson(gedcom, writer.toString()); 178 | } 179 | 180 | @Test 181 | public void testWrite_withGedcomAndOutputStream() { 182 | Header header = new Header(); 183 | header.setLanguage("English"); 184 | header.setCopyright("2019"); 185 | 186 | Gedcom gedcom = new Gedcom(); 187 | gedcom.setHeader(header); 188 | 189 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 190 | JsonParser jsonParser = new JsonParser(); 191 | jsonParser.write(gedcom, os); 192 | 193 | assertGedcomJson(gedcom, os.toString()); 194 | } 195 | 196 | @Test 197 | public void testWrite_withGedcomTagsAndWriter() { 198 | GedcomTag tag = new GedcomTag("", "head", ""); 199 | 200 | Writer writer = new StringWriter(); 201 | JsonParser jsonParser = new JsonParser(); 202 | jsonParser.write(Collections.singletonList(tag), writer); 203 | 204 | assertGedcomTagsJson(writer.toString()); 205 | } 206 | 207 | @Test 208 | public void testWrite_withGedcomTagsAndOutputStream() { 209 | GedcomTag tag = new GedcomTag("", "head", ""); 210 | 211 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 212 | JsonParser jsonParser = new JsonParser(); 213 | jsonParser.write(Collections.singletonList(tag), os); 214 | 215 | assertGedcomTagsJson(os.toString()); 216 | } 217 | 218 | private void assertGedcomJson(Gedcom gedcom, String json) { 219 | JsonParser jsonParser = new JsonParser(); 220 | Gedcom actualGedcom = jsonParser.fromJson(json); 221 | assertNotNull(actualGedcom); 222 | assertEquals(gedcom.getHeader().getLanguage(), actualGedcom.getHeader().getLanguage()); 223 | assertEquals(gedcom.getHeader().getCopyright(), actualGedcom.getHeader().getCopyright()); 224 | } 225 | 226 | private void assertGedcomTagsJson(String json) { 227 | com.google.gson.JsonParser gsonParser = new com.google.gson.JsonParser(); 228 | JsonElement jsonElement = gsonParser.parse(json); 229 | assertNotNull(jsonElement); 230 | assertTrue(jsonElement.isJsonArray()); 231 | 232 | JsonArray jsonArray = jsonElement.getAsJsonArray(); 233 | 234 | JsonElement head = jsonArray.get(0); 235 | assertNotNull(head); 236 | assertTrue(head.isJsonObject()); 237 | 238 | JsonObject headObj = head.getAsJsonObject(); 239 | 240 | JsonElement jsonTag = headObj.get("tag"); 241 | assertNotNull(jsonTag); 242 | assertTrue(jsonTag.isJsonPrimitive()); 243 | assertEquals("head", jsonTag.getAsString()); 244 | } 245 | 246 | } 247 | --------------------------------------------------------------------------------