1 /* 2 * "GEDKeeper", the personal genealogical database editor. 3 * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. 4 * 5 * This file is part of "GEDKeeper". 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 using System; 22 using BSLib.Calendar; 23 using GDModel.Providers.GEDCOM; 24 25 namespace GDModel 26 { 27 public enum GDMRestriction 28 { 29 rnNone, 30 rnLocked, 31 rnConfidential, 32 rnPrivacy, 33 34 rnLast = rnPrivacy 35 } 36 37 38 public abstract class GDMRecordWithEvents : GDMRecord, IGDMRecordWithEvents 39 { 40 private GDMList<GDMCustomEvent> fEvents; 41 private GDMRestriction fRestriction; 42 43 44 public bool HasEvents 45 { 46 get { return fEvents != null && fEvents.Count != 0; } 47 } 48 49 public GDMList<GDMCustomEvent> Events 50 { 51 get { 52 if (fEvents == null) { 53 fEvents = new GDMList<GDMCustomEvent>(); 54 } 55 56 return fEvents; 57 } 58 } 59 60 public GDMRestriction Restriction 61 { 62 get { return fRestriction; } 63 set { fRestriction = value; } 64 } 65 66 GDMRecordWithEvents(GDMTree tree)67 protected GDMRecordWithEvents(GDMTree tree) : base(tree) 68 { 69 } 70 Dispose(bool disposing)71 protected override void Dispose(bool disposing) 72 { 73 if (disposing) { 74 if (fEvents != null) fEvents.Dispose(); 75 } 76 base.Dispose(disposing); 77 } 78 TrimExcess()79 internal override void TrimExcess() 80 { 81 base.TrimExcess(); 82 83 if (fEvents != null) fEvents.TrimExcess(); 84 } 85 Clear()86 public override void Clear() 87 { 88 base.Clear(); 89 90 if (fEvents != null) fEvents.Clear(); 91 fRestriction = GDMRestriction.rnNone; 92 } 93 IsEmpty()94 public override bool IsEmpty() 95 { 96 // Restrictions are not checked because they are not important if other fields are empty. 97 return base.IsEmpty() && (fEvents == null || fEvents.Count == 0); 98 } 99 Assign(GDMTag source)100 public override void Assign(GDMTag source) 101 { 102 GDMRecordWithEvents sourceRec = source as GDMRecordWithEvents; 103 if (sourceRec == null) 104 throw new ArgumentException(@"Argument is null or wrong type", "source"); 105 106 base.Assign(source); 107 108 if (sourceRec.fEvents != null) { 109 for (int i = 0, count = sourceRec.fEvents.Count; i < count; i++) { 110 GDMCustomEvent sourceEvent = sourceRec.fEvents[i]; 111 GDMCustomEvent copy = (GDMCustomEvent)Activator.CreateInstance(sourceEvent.GetType()); 112 copy.Assign(sourceEvent); 113 AddEvent(copy); 114 } 115 } 116 117 fRestriction = sourceRec.Restriction; 118 } 119 MoveTo(GDMRecord targetRecord)120 public override void MoveTo(GDMRecord targetRecord) 121 { 122 GDMRecordWithEvents target = targetRecord as GDMRecordWithEvents; 123 if (target == null) 124 throw new ArgumentException(@"Argument is null or wrong type", "targetRecord"); 125 126 base.MoveTo(targetRecord); 127 128 while (fEvents != null && fEvents.Count > 0) { 129 GDMCustomEvent obj = fEvents.Extract(0); 130 target.AddEvent(obj); 131 } 132 133 target.Restriction = fRestriction; 134 } 135 ReplaceXRefs(GDMXRefReplacer map)136 public override void ReplaceXRefs(GDMXRefReplacer map) 137 { 138 base.ReplaceXRefs(map); 139 if (fEvents != null) fEvents.ReplaceXRefs(map); 140 } 141 FindEvent(string eventName)142 public GDMCustomEvent FindEvent(string eventName) 143 { 144 GDMCustomEvent result = null; 145 if (fEvents == null) return result; 146 147 int num = fEvents.Count; 148 for (int i = 0; i < num; i++) { 149 GDMCustomEvent evt = fEvents[i]; 150 151 if (evt.GetTagName() == eventName) { 152 result = evt; 153 break; 154 } 155 } 156 157 return result; 158 } 159 FindEvent(GEDCOMTagType eventType)160 public GDMCustomEvent FindEvent(GEDCOMTagType eventType) 161 { 162 GDMCustomEvent result = null; 163 if (fEvents == null) return result; 164 165 int evtType = (int)eventType; 166 int num = fEvents.Count; 167 for (int i = 0; i < num; i++) { 168 GDMCustomEvent evt = fEvents[i]; 169 170 if (evt.Id == evtType) { 171 result = evt; 172 break; 173 } 174 } 175 176 return result; 177 } 178 AddEvent(GDMCustomEvent evt)179 public abstract GDMCustomEvent AddEvent(GDMCustomEvent evt); 180 181 private static readonly float[] CA_VALUES = new float[] { 0.25f, 0.5f, 0.75f, 1.0f }; 182 GetCertaintyAssessment()183 public float GetCertaintyAssessment() 184 { 185 float result = 0; 186 float wsum = 0; 187 188 if (fEvents != null) { 189 int num1 = fEvents.Count; 190 for (int i = 0; i < num1; i++) { 191 GDMCustomEvent evt = fEvents[i]; 192 if (!evt.HasSourceCitations) continue; 193 194 int num2 = evt.SourceCitations.Count; 195 for (int k = 0; k < num2; k++) { 196 GDMSourceCitation cit = evt.SourceCitations[k]; 197 198 int ca = cit.GetValidCertaintyAssessment(); 199 int weight = (ca + 1); 200 201 result += (CA_VALUES[ca] * weight); 202 wsum += weight; 203 } 204 } 205 } 206 207 if (HasSourceCitations) { 208 int num3 = SourceCitations.Count; 209 for (int i = 0; i < num3; i++) { 210 GDMSourceCitation cit = SourceCitations[i]; 211 212 int ca = cit.GetValidCertaintyAssessment(); 213 int weight = (ca + 1); 214 215 result += (CA_VALUES[ca] * weight); 216 wsum += weight; 217 } 218 } 219 220 if (wsum != 0.0f) { 221 result /= wsum; 222 } else { 223 result = 0.0f; 224 } 225 226 return result; 227 } 228 GetUDN(string eventSign)229 public UDN GetUDN(string eventSign) 230 { 231 GDMCustomEvent evt = FindEvent(eventSign); 232 return (evt == null) ? UDN.CreateEmpty() : evt.GetUDN(); 233 } 234 235 /// <summary> 236 /// In the historical chronology of the year 0 does not exist. 237 /// Therefore, the digit 0 in the year value can be used as a sign of lack or error. 238 /// ChronologicalYear - introduced for the purposes of uniform chronology years in the Gregorian calendar. 239 /// Is estimated from -4714 BC to 3268 AD. 240 /// </summary> 241 /// <returns>chronological year</returns> GetChronologicalYear(string eventSign)242 public int GetChronologicalYear(string eventSign) 243 { 244 GDMCustomEvent evt = FindEvent(eventSign); 245 return (evt == null) ? 0 : evt.GetChronologicalYear(); 246 } 247 } 248 } 249