8 |
8 |
*/
|
9 |
9 |
package eu.etaxonomy.cdm.app.pesi.merging;
|
10 |
10 |
|
|
11 |
import java.util.HashSet;
|
|
12 |
import java.util.List;
|
11 |
13 |
import java.util.Optional;
|
12 |
14 |
import java.util.Set;
|
13 |
15 |
import java.util.UUID;
|
... | ... | |
17 |
19 |
import org.springframework.transaction.TransactionStatus;
|
18 |
20 |
|
19 |
21 |
import eu.etaxonomy.cdm.api.service.DeleteResult;
|
|
22 |
import eu.etaxonomy.cdm.api.service.config.SynonymDeletionConfigurator;
|
20 |
23 |
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
|
21 |
24 |
import eu.etaxonomy.cdm.app.common.CdmDestinations;
|
22 |
25 |
import eu.etaxonomy.cdm.common.CdmRegEx;
|
... | ... | |
25 |
28 |
import eu.etaxonomy.cdm.database.ICdmDataSource;
|
26 |
29 |
import eu.etaxonomy.cdm.io.api.application.CdmIoApplicationController;
|
27 |
30 |
import eu.etaxonomy.cdm.io.common.mapping.out.DbLastActionMapper;
|
|
31 |
import eu.etaxonomy.cdm.io.pesi.erms.ErmsTransformer;
|
28 |
32 |
import eu.etaxonomy.cdm.io.pesi.out.PesiTransformer;
|
29 |
33 |
import eu.etaxonomy.cdm.model.common.Annotation;
|
30 |
34 |
import eu.etaxonomy.cdm.model.common.CdmBase;
|
... | ... | |
40 |
44 |
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
|
41 |
45 |
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
|
42 |
46 |
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
|
|
47 |
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
|
43 |
48 |
|
44 |
49 |
/**
|
45 |
50 |
* @author a.mueller
|
... | ... | |
55 |
60 |
|
56 |
61 |
private void invoke(ICdmDataSource source){
|
57 |
62 |
app = CdmIoApplicationController.NewInstance(source, DbSchemaValidation.VALIDATE, false);
|
58 |
|
|
59 |
|
while(booleanAnswer("New merge")){
|
|
63 |
doInvoke();
|
|
64 |
}
|
|
65 |
private void doInvoke(){
|
|
66 |
List<List<String>> fileData = null;
|
|
67 |
String next = nextMerge(fileData);
|
|
68 |
while(next.equalsIgnoreCase("m")|| next.equals("f")){
|
60 |
69 |
TransactionStatus tx = app.startTransaction();
|
61 |
|
Taxon[] taxa = null;
|
62 |
|
while (taxa == null) {
|
63 |
|
taxa = readTaxa();
|
|
70 |
TaxonInformation taxonInformation;
|
|
71 |
if (next.equalsIgnoreCase("f")){
|
|
72 |
if (fileData == null){
|
|
73 |
fileData = getFileData();
|
|
74 |
}else if (fileData.isEmpty()){
|
|
75 |
fileData = null;
|
|
76 |
next = nextMerge(fileData);
|
|
77 |
continue;
|
|
78 |
}
|
|
79 |
taxonInformation = readLineFromFile(fileData);
|
|
80 |
if (taxonInformation == null){
|
|
81 |
app.rollbackTransaction(tx);
|
|
82 |
nextMerge(fileData);
|
|
83 |
continue;
|
|
84 |
}
|
|
85 |
}else{
|
|
86 |
TaxonBase<?>[] taxa = null;
|
|
87 |
while (taxa == null) {
|
|
88 |
taxa = readTaxa();
|
|
89 |
}
|
|
90 |
taxonInformation = new TaxonInformation();
|
|
91 |
taxonInformation.taxon2 = taxa[0];
|
|
92 |
taxonInformation.taxon1 = taxa[1];
|
|
93 |
}
|
|
94 |
|
|
95 |
try {
|
|
96 |
mergeTaxa(tx, taxonInformation);
|
|
97 |
} catch (Exception e) {
|
|
98 |
e.printStackTrace();
|
|
99 |
app.rollbackTransaction(tx);
|
|
100 |
continue;
|
64 |
101 |
}
|
65 |
|
boolean commit = compareTaxa(taxa);
|
66 |
|
if (commit){
|
67 |
|
moveTaxonInformation(taxa[0],taxa[1]);
|
|
102 |
next = nextMerge(fileData);
|
|
103 |
}
|
|
104 |
}
|
|
105 |
|
|
106 |
private boolean mergeTaxa(TransactionStatus tx, TaxonInformation taxonInformation) {
|
|
107 |
boolean commit = compareTaxa(taxonInformation);
|
|
108 |
if (commit){
|
|
109 |
moveTaxonInformation(taxonInformation);
|
|
110 |
}
|
|
111 |
if (commit){
|
|
112 |
app.commitTransaction(tx);
|
|
113 |
if (taxonInformation.taxonToUse == 1 && taxonInformation.nameToUse == 1){
|
|
114 |
removeTaxon(taxonInformation.taxon2);
|
|
115 |
}else if (booleanAnswer("Information moved. Delete old taxon")){
|
|
116 |
removeTaxon(taxonInformation.taxonToUse == 2 ? taxonInformation.taxon1 : taxonInformation.taxon2);
|
68 |
117 |
}
|
69 |
|
if (commit){
|
70 |
|
app.commitTransaction(tx);
|
71 |
|
if (booleanAnswer("Information moved. Delete old taxon")){
|
72 |
|
removeTaxon(taxa[0]);
|
|
118 |
}else{
|
|
119 |
app.rollbackTransaction(tx);
|
|
120 |
}
|
|
121 |
return commit;
|
|
122 |
}
|
|
123 |
|
|
124 |
private class TaxonInformation{
|
|
125 |
TaxonBase<?> taxon1;
|
|
126 |
TaxonBase<?> taxon2;
|
|
127 |
int taxonToUse = 1; //
|
|
128 |
int nameToUse = 1;
|
|
129 |
}
|
|
130 |
|
|
131 |
/**
|
|
132 |
* Reads a line from the file, returns it's taxon information and removes
|
|
133 |
* the line from the input list.
|
|
134 |
*/
|
|
135 |
private TaxonInformation readLineFromFile(List<List<String>> fileData) {
|
|
136 |
List<String> line = fileData.get(0);
|
|
137 |
TaxonInformation taxonInformation = new TaxonInformation();
|
|
138 |
taxonInformation.taxon1 = taxonByString(line.get(0));
|
|
139 |
taxonInformation.taxon2 = taxonByString(line.get(1));
|
|
140 |
|
|
141 |
if (taxonInformation.taxon1 == null || taxonInformation.taxon2 == null){
|
|
142 |
boolean cancel = booleanAnswer("Taxon1 or Taxon2 could not be read from DB! Cancel record");
|
|
143 |
if (cancel){
|
|
144 |
fileData.remove(0);
|
|
145 |
}
|
|
146 |
return null;
|
|
147 |
}
|
|
148 |
|
|
149 |
try {
|
|
150 |
Integer taxonToUse = Integer.valueOf(line.get(2));
|
|
151 |
if (1 != taxonInformation.taxonToUse){
|
|
152 |
booleanAnswer("Stay taxon is not '1'");
|
|
153 |
}
|
|
154 |
Integer nameToUse = "".equals(line.get(3))? taxonToUse: Integer.valueOf(line.get(3));
|
|
155 |
if (taxonToUse != 1 && taxonToUse != 2 && taxonToUse != 0){
|
|
156 |
boolean cancel = booleanAnswer("taxonToUse is not 0, 1 or 2. Cancel record");
|
|
157 |
if (cancel){
|
|
158 |
fileData.remove(0);
|
73 |
159 |
}
|
|
160 |
return null;
|
|
161 |
}else if (taxonToUse == 0){
|
|
162 |
logger.warn("Record marked as homonym. No merge: " + taxonInformation.taxon1.getName().getNameCache());
|
|
163 |
fileData.remove(0);
|
|
164 |
return null;
|
74 |
165 |
}else{
|
75 |
|
app.rollbackTransaction(tx);
|
|
166 |
taxonInformation.taxonToUse = taxonToUse;
|
76 |
167 |
}
|
|
168 |
if (nameToUse == null){
|
|
169 |
nameToUse = taxonToUse;
|
|
170 |
}
|
|
171 |
if (nameToUse != 1 && nameToUse != 2){
|
|
172 |
logger.warn("Name to use has incorrect value: " + nameToUse);
|
|
173 |
}else{
|
|
174 |
taxonInformation.nameToUse = nameToUse;
|
|
175 |
}
|
|
176 |
} catch (NumberFormatException e) {
|
|
177 |
e.printStackTrace();
|
|
178 |
taxonInformation = null;
|
77 |
179 |
}
|
|
180 |
fileData.remove(0);
|
|
181 |
return taxonInformation;
|
78 |
182 |
}
|
79 |
183 |
|
80 |
|
private boolean compareTaxa(Taxon[] taxa) {
|
81 |
|
Taxon removeTaxon = taxa[0];
|
82 |
|
Taxon stayTaxon = taxa[1];
|
|
184 |
private List<List<String>> getFileData() {
|
|
185 |
List<List<String>> result = null;
|
|
186 |
while(result == null){
|
|
187 |
String input = CdmUtils.readInputLine("Path and filename: ");
|
|
188 |
result = readCsvFile(input);
|
|
189 |
}
|
|
190 |
return result;
|
|
191 |
}
|
|
192 |
|
|
193 |
private String nextMerge(List<List<String>> fileData) {
|
|
194 |
if (fileData != null){
|
|
195 |
return "f";
|
|
196 |
}
|
|
197 |
do{
|
|
198 |
String input = CdmUtils.readInputLine("Next input: manual[m], file[f], quit[q]: ");
|
|
199 |
if (input.matches("[mMfFqQ]")){
|
|
200 |
return input;
|
|
201 |
}
|
|
202 |
}while (true);
|
|
203 |
}
|
|
204 |
|
|
205 |
private boolean compareTaxa(TaxonInformation taxonInformation) {
|
|
206 |
TaxonBase<?> removeTaxon = taxonInformation.taxon2;
|
|
207 |
TaxonBase<?> stayTaxon = taxonInformation.taxon1;
|
83 |
208 |
String nc1 = removeTaxon.getName().getNameCache();
|
84 |
209 |
String nc2 = stayTaxon.getName().getNameCache();
|
85 |
210 |
|
86 |
211 |
String ft1 = removeTaxon.getName().getFullTitleCache();
|
87 |
212 |
String ft2 = stayTaxon.getName().getFullTitleCache();
|
88 |
|
System.out.println("Remove: " + ft1);
|
89 |
|
System.out.println("Stay : " + ft2);
|
|
213 |
System.out.println("Remove " + getStatusStr(removeTaxon) + ft1);
|
|
214 |
System.out.println("Stay " + getStatusStr(stayTaxon) + ft2);
|
|
215 |
boolean isStandard = taxonInformation.taxonToUse == 1 && taxonInformation.nameToUse == 1;
|
90 |
216 |
if (!nc1.equals(nc2)){
|
91 |
217 |
return booleanAnswer("Name Cache differs!!! Do you really want to merge???");
|
92 |
218 |
}else if (!ft1.equals(ft2)){
|
93 |
|
return booleanAnswer("Full title cache differs! Do you really want to merge anyway");
|
|
219 |
return isStandard || booleanAnswer("Full title cache differs! Do you really want to merge anyway");
|
94 |
220 |
}else{
|
95 |
|
return booleanAnswer("Same title. Merge");
|
|
221 |
return isStandard || booleanAnswer("Same title. Merge");
|
96 |
222 |
}
|
97 |
223 |
}
|
98 |
224 |
|
99 |
|
private void removeTaxon(Taxon taxon) {
|
100 |
|
TaxonNode nodeToRemove = taxon.getTaxonNodes().iterator().next();
|
101 |
|
TaxonDeletionConfigurator config = new TaxonDeletionConfigurator();
|
102 |
|
DeleteResult result = app.getTaxonNodeService().deleteTaxonNode(nodeToRemove.getUuid(), config);
|
|
225 |
private String getStatusStr(TaxonBase<?> taxon) {
|
|
226 |
//TODO MAN and Taxon Synonyms
|
|
227 |
if (taxon.isInstanceOf(Synonym.class)){
|
|
228 |
return "Syn: ";
|
|
229 |
}else{
|
|
230 |
return "Acc: ";
|
|
231 |
}
|
|
232 |
}
|
|
233 |
|
|
234 |
private void removeTaxon(TaxonBase<?> taxonBase) {
|
|
235 |
DeleteResult result;
|
|
236 |
if (taxonBase.isInstanceOf(Taxon.class)){
|
|
237 |
Taxon taxonToRemove = CdmBase.deproxy(taxonBase, Taxon.class);
|
|
238 |
TaxonDeletionConfigurator config = new TaxonDeletionConfigurator();
|
|
239 |
if (isTaxonSynonym(taxonToRemove)){
|
|
240 |
result = app.getTaxonService().deleteTaxon(taxonToRemove.getUuid(), config, null);
|
|
241 |
}else{
|
|
242 |
TaxonNode nodeToRemove = taxonToRemove.getTaxonNodes().iterator().next();
|
|
243 |
result = app.getTaxonNodeService().deleteTaxonNode(nodeToRemove.getUuid(), config);
|
|
244 |
}
|
|
245 |
}else{
|
|
246 |
Synonym syn = CdmBase.deproxy(taxonBase, Synonym.class);
|
|
247 |
SynonymDeletionConfigurator config = new SynonymDeletionConfigurator();
|
|
248 |
result = app.getTaxonService().deleteSynonym(syn.getUuid(), config);
|
|
249 |
}
|
103 |
250 |
if (!result.isOk()){
|
104 |
251 |
System.out.println("Remove taxon was not successful.");
|
105 |
252 |
}
|
106 |
253 |
}
|
107 |
254 |
|
108 |
255 |
private boolean booleanAnswer(String message) {
|
109 |
|
String answer = CdmUtils.readInputLine(message + " (y/n)? ");
|
|
256 |
String answer = "";
|
|
257 |
while (!(answer.equalsIgnoreCase("y") || answer.equalsIgnoreCase("n"))){
|
|
258 |
answer = CdmUtils.readInputLine(message + " (y/n)? ");
|
|
259 |
}
|
110 |
260 |
return answer.equalsIgnoreCase("y");
|
111 |
261 |
}
|
112 |
262 |
|
113 |
|
private boolean moveTaxonInformation(Taxon removeTaxon, Taxon stayTaxon) {
|
|
263 |
private boolean moveTaxonInformation(TaxonInformation taxonInformation) {
|
114 |
264 |
try {
|
|
265 |
|
|
266 |
TaxonBase<?> removeTaxon = CdmBase.deproxy(taxonInformation.taxonToUse == 2 ? taxonInformation.taxon1: taxonInformation.taxon2);
|
|
267 |
TaxonBase<?> stayTaxon = CdmBase.deproxy(taxonInformation.taxonToUse == 2 ? taxonInformation.taxon2 : taxonInformation.taxon1);
|
|
268 |
|
|
269 |
//mergeTaxa;
|
|
270 |
mergeSources(removeTaxon, stayTaxon);
|
|
271 |
mergeAnnotations(removeTaxon, stayTaxon);
|
|
272 |
mergeMarkers(removeTaxon, stayTaxon);
|
|
273 |
//TODO for
|
|
274 |
mergeExtensions(removeTaxon, stayTaxon);
|
|
275 |
mergeCredits(removeTaxon, stayTaxon);
|
|
276 |
if (removeTaxon.isInstanceOf(Taxon.class)){
|
|
277 |
Taxon removeAccTaxon = CdmBase.deproxy(removeTaxon, Taxon.class);
|
|
278 |
|
|
279 |
Taxon stayAccTaxon = accTaxon(stayTaxon);
|
|
280 |
mergeDescriptions(removeAccTaxon, accTaxon(stayTaxon));
|
|
281 |
boolean isTaxonSynonym = isTaxonSynonym(removeAccTaxon);
|
|
282 |
mergeSynonyms(removeAccTaxon, stayAccTaxon, isTaxonSynonym);
|
|
283 |
mergeChildren(removeAccTaxon, stayAccTaxon, isTaxonSynonym);
|
|
284 |
//TODO taxon synonym relations
|
|
285 |
mergeTaxonRelations(removeAccTaxon, stayAccTaxon, isTaxonSynonym);
|
|
286 |
}
|
|
287 |
|
115 |
288 |
//mergeNames;
|
116 |
|
TaxonName removeName = CdmBase.deproxy(removeTaxon.getName());
|
117 |
|
TaxonName stayName = CdmBase.deproxy(stayTaxon.getName());
|
|
289 |
TaxonName removeName;
|
|
290 |
TaxonName stayName;
|
|
291 |
if (taxonInformation.nameToUse == taxonInformation.taxonToUse){
|
|
292 |
removeName = CdmBase.deproxy(removeTaxon.getName());
|
|
293 |
stayName = CdmBase.deproxy(stayTaxon.getName());
|
|
294 |
}else{
|
|
295 |
removeName = CdmBase.deproxy(stayTaxon.getName());
|
|
296 |
stayName = CdmBase.deproxy(removeTaxon.getName());
|
|
297 |
stayTaxon.setName(stayName);
|
|
298 |
}
|
|
299 |
//TODO unclear if name information should be merged at all
|
118 |
300 |
mergeSources(removeName, stayName);
|
119 |
301 |
mergeAnnotations(removeName, stayName);
|
120 |
302 |
mergeMarkers(removeName, stayName);
|
... | ... | |
124 |
306 |
mergeHybridRelationships(removeName, stayName);
|
125 |
307 |
mergeNameDescriptions(removeName, stayName);
|
126 |
308 |
|
127 |
|
//mergeTaxa;
|
128 |
|
mergeSources(removeTaxon, stayTaxon);
|
129 |
|
mergeAnnotations(removeTaxon, stayTaxon);
|
130 |
|
mergeMarkers(removeTaxon, stayTaxon);
|
131 |
|
mergeExtensions(removeTaxon, stayTaxon);
|
132 |
|
mergeCredits(removeTaxon, stayTaxon);
|
133 |
|
mergeDescriptions(removeTaxon, stayTaxon);
|
134 |
|
mergeSynonyms(removeTaxon, stayTaxon);
|
135 |
|
mergeChildren(removeTaxon, stayTaxon);
|
136 |
|
mergeTaxonRelations(removeTaxon, stayTaxon);
|
137 |
|
return booleanAnswer("Commit moved information");
|
|
309 |
if(taxonInformation.taxonToUse == 1 && taxonInformation.nameToUse == 1){
|
|
310 |
return true;
|
|
311 |
}else{
|
|
312 |
return booleanAnswer("Commit moved information");
|
|
313 |
}
|
138 |
314 |
} catch (CloneNotSupportedException e) {
|
139 |
315 |
e.printStackTrace();
|
140 |
316 |
return false;
|
141 |
317 |
}
|
142 |
318 |
}
|
143 |
319 |
|
144 |
|
private void mergeTaxonRelations(Taxon removeTaxon, Taxon stayTaxon) {
|
|
320 |
private boolean isTaxonSynonym(Taxon removeAccTaxon) {
|
|
321 |
for (TaxonRelationship rel: removeAccTaxon.getRelationsFromThisTaxon()){
|
|
322 |
boolean isPseudo = TaxonRelationshipType.pseudoTaxonUuids().contains(rel.getType().getUuid());
|
|
323 |
if (isPseudo){
|
|
324 |
return true;
|
|
325 |
}
|
|
326 |
}
|
|
327 |
return false;
|
|
328 |
}
|
|
329 |
|
|
330 |
private Taxon accTaxon(TaxonBase<?> stayTaxon) {
|
|
331 |
if (stayTaxon.isInstanceOf(Synonym.class)){
|
|
332 |
return CdmBase.deproxy(stayTaxon, Synonym.class).getAcceptedTaxon();
|
|
333 |
}else{
|
|
334 |
return CdmBase.deproxy(stayTaxon, Taxon.class);
|
|
335 |
}
|
|
336 |
}
|
|
337 |
|
|
338 |
private boolean mergeTaxonRelations(Taxon removeTaxon, Taxon stayTaxon, boolean isTaxonSynonym) {
|
|
339 |
if (isTaxonSynonym){
|
|
340 |
if (!removeTaxon.getRelationsToThisTaxon().isEmpty()){
|
|
341 |
logger.warn("taxon synonym has taxon relations to itself. This should not happen. Handle manually.");
|
|
342 |
return false;
|
|
343 |
}else{
|
|
344 |
return true;
|
|
345 |
}
|
|
346 |
}
|
145 |
347 |
for (TaxonRelationship rel : removeTaxon.getRelationsToThisTaxon()){
|
146 |
348 |
System.out.println("Move taxon relationship: " + rel.getType().getTitleCache() + ": " + rel.getFromTaxon().getTitleCache());
|
147 |
349 |
|
... | ... | |
156 |
358 |
if(!removeTaxon.getRelationsFromThisTaxon().isEmpty()){
|
157 |
359 |
logger.warn("Taxon-from-relations not yet implemented");
|
158 |
360 |
}
|
|
361 |
return true;
|
159 |
362 |
}
|
160 |
363 |
|
161 |
364 |
private void mergeNameDescriptions(TaxonName removeName, @SuppressWarnings("unused") TaxonName stayName) {
|
... | ... | |
179 |
382 |
}
|
180 |
383 |
}
|
181 |
384 |
|
182 |
|
private void mergeChildren(Taxon removeTaxon, Taxon stayTaxon) {
|
|
385 |
private boolean mergeChildren(Taxon removeTaxon, Taxon stayTaxon, boolean isTaxonSynonym) {
|
|
386 |
if (isTaxonSynonym){
|
|
387 |
if (!removeTaxon.getTaxonNodes().isEmpty()){
|
|
388 |
logger.warn("taxon synonym has taxon node itself. This should not happen. Handle manually.");
|
|
389 |
return false;
|
|
390 |
}else{
|
|
391 |
return true;
|
|
392 |
}
|
|
393 |
}
|
183 |
394 |
TaxonNode removeNode = removeTaxon.getTaxonNodes().iterator().next();
|
184 |
395 |
TaxonNode stayNode = stayTaxon.getTaxonNodes().iterator().next();
|
185 |
396 |
Set<UUID> removeNodeChildrenUuids = removeNode.getChildNodes()
|
... | ... | |
189 |
400 |
app.getTaxonNodeService().moveTaxonNodes(removeNodeChildrenUuids,
|
190 |
401 |
stayNode.getUuid(), 0, null);
|
191 |
402 |
System.out.println("Child nodes moved: " + removeNodeChildrenUuids.size());
|
192 |
|
|
193 |
403 |
}
|
|
404 |
return true;
|
194 |
405 |
}
|
195 |
406 |
|
196 |
|
private void mergeSynonyms(Taxon removeTaxon, Taxon stayTaxon) {
|
|
407 |
private boolean mergeSynonyms(Taxon removeTaxon, Taxon stayTaxon, boolean isTaxonSynonym) {
|
|
408 |
if (isTaxonSynonym){
|
|
409 |
if (!removeTaxon.getSynonyms().isEmpty()){
|
|
410 |
logger.warn("taxon synonym has synonyms itself. This should not happen. Handle manually.");
|
|
411 |
return false;
|
|
412 |
}else{
|
|
413 |
return true;
|
|
414 |
}
|
|
415 |
}
|
|
416 |
Set<Synonym> synonymsToAdd = new HashSet<>();
|
197 |
417 |
for (Synonym synonym : removeTaxon.getSynonyms()){
|
198 |
418 |
if (!synonymExists()){
|
199 |
419 |
//TODO homotypical group
|
200 |
|
stayTaxon.addSynonym(synonym, synonym.getType());
|
|
420 |
synonymsToAdd.add(synonym);
|
201 |
421 |
}else{
|
202 |
422 |
//TODO merge synonym names
|
203 |
423 |
}
|
204 |
424 |
}
|
|
425 |
for (Synonym synonym: synonymsToAdd){
|
|
426 |
stayTaxon.addSynonym(synonym, synonym.getType());
|
|
427 |
}
|
|
428 |
return true;
|
205 |
429 |
}
|
206 |
430 |
|
207 |
431 |
private boolean synonymExists() {
|
... | ... | |
228 |
452 |
|
229 |
453 |
private void mergeExtensions(IdentifiableEntity<?> removeEntity,
|
230 |
454 |
IdentifiableEntity<?> stayEntity) throws CloneNotSupportedException {
|
|
455 |
|
231 |
456 |
String className = removeEntity.getClass().getSimpleName();
|
232 |
457 |
for (Extension extension: removeEntity.getExtensions()){
|
233 |
|
System.out.println("Move "+className+" extension: " + extension.getType().getTitleCache() + ": " + extension.getValue());
|
234 |
|
stayEntity.addExtension((Extension)extension.clone());
|
|
458 |
if (!filterExtension(extension, removeEntity, stayEntity)){
|
|
459 |
System.out.println("Move "+className+" extension: " + extension.getType().getTitleCache() + ": " + extension.getValue());
|
|
460 |
|
|
461 |
IdentifiableEntity<?> thisStayEntity = selectStay(removeEntity, stayEntity, "Extension");
|
|
462 |
if (thisStayEntity != null){
|
|
463 |
thisStayEntity.addExtension((Extension)extension.clone());
|
|
464 |
}
|
|
465 |
}
|
|
466 |
}
|
|
467 |
}
|
|
468 |
|
|
469 |
private IdentifiableEntity<?> selectStay(IdentifiableEntity<?> removeEntity, IdentifiableEntity<?> stayEntity, String type) {
|
|
470 |
if(removeEntity.isInstanceOf(Taxon.class) && stayEntity.isInstanceOf(Synonym.class)){
|
|
471 |
String answer = "";
|
|
472 |
while(!(answer.matches("[sSaAcC]"))){
|
|
473 |
answer = CdmUtils.readInputLine(type + ": Stay is Synonym. Move information to [s]ynonym, to [a]ccepted or [c]ancel extension merge?: ");
|
|
474 |
}
|
|
475 |
if (answer.equalsIgnoreCase("c")){
|
|
476 |
return null;
|
|
477 |
}else if (answer.equalsIgnoreCase("a")){
|
|
478 |
return accTaxon(CdmBase.deproxy(stayEntity, Synonym.class));
|
|
479 |
}else{
|
|
480 |
return stayEntity;
|
|
481 |
}
|
235 |
482 |
}
|
|
483 |
return stayEntity;
|
|
484 |
}
|
|
485 |
|
|
486 |
private boolean filterExtension(Extension extension,
|
|
487 |
@SuppressWarnings("unused") IdentifiableEntity<?> removeEntity,
|
|
488 |
@SuppressWarnings("unused") IdentifiableEntity<?> stayEntity) {
|
|
489 |
if (extension.getType().getUuid().equals(ErmsTransformer.uuidExtDisplayName)){
|
|
490 |
//for merged taxa display name information is not relevant because name is formatted according to "stay" taxon.
|
|
491 |
return true;
|
|
492 |
}
|
|
493 |
return false;
|
236 |
494 |
}
|
237 |
495 |
|
238 |
496 |
private void mergeMarkers(IdentifiableEntity<?> removeEntity,
|
... | ... | |
241 |
499 |
for (Marker marker: removeEntity.getMarkers()){
|
242 |
500 |
if (!filterMarker(marker, removeEntity, stayEntity)){
|
243 |
501 |
System.out.println("Move "+className+" marker: " + marker.getMarkerType().getTitleCache() + ": " + marker.getValue());
|
244 |
|
stayEntity.addMarker((Marker)marker.clone());
|
|
502 |
IdentifiableEntity<?> thisStayEntity = selectStay(removeEntity, stayEntity, "Marker");
|
|
503 |
if (thisStayEntity != null){
|
|
504 |
thisStayEntity.addMarker((Marker)marker.clone());
|
|
505 |
}
|
245 |
506 |
}
|
246 |
507 |
}
|
247 |
508 |
}
|
... | ... | |
251 |
512 |
String className = removeEntity.getClass().getSimpleName();
|
252 |
513 |
for (Annotation annotation: removeEntity.getAnnotations()){
|
253 |
514 |
if (!filterAnnotation(annotation, removeEntity, stayEntity)){
|
254 |
|
System.out.println("Move "+className+" note: " + annotation.getAnnotationType().getTitleCache() + ": " + annotation.getText());
|
|
515 |
String type = annotation.getAnnotationType() == null? "no type" : annotation.getAnnotationType().getTitleCache();
|
|
516 |
System.out.println("Move "+className+" note: " + type + ": " + annotation.getText());
|
255 |
517 |
handleRemoveAnnotation(annotation, removeEntity, stayEntity);
|
256 |
518 |
stayEntity.addAnnotation((Annotation)annotation.clone());
|
257 |
519 |
}
|
... | ... | |
280 |
542 |
}
|
281 |
543 |
|
282 |
544 |
private boolean isLastActionDateAnnotation(Annotation annotation) {
|
283 |
|
return annotation.getAnnotationType().getUuid().equals(DbLastActionMapper.uuidAnnotationTypeLastActionDate)
|
284 |
|
&& !isBlank(annotation.getText());
|
|
545 |
return annotation.getAnnotationType()!= null
|
|
546 |
&& annotation.getAnnotationType().getUuid().equals(DbLastActionMapper.uuidAnnotationTypeLastActionDate)
|
|
547 |
&& !isBlank(annotation.getText());
|
285 |
548 |
}
|
286 |
549 |
|
287 |
550 |
private void handleRemoveAnnotation(Annotation annotation,
|
... | ... | |
293 |
556 |
stayEntity.removeMarker(noLastActionMarker.get());
|
294 |
557 |
System.out.println(" NoLastActionDate annotation removed from 'stay' " + stayEntity.getClass().getSimpleName());
|
295 |
558 |
}
|
296 |
|
};
|
|
559 |
}
|
297 |
560 |
}
|
298 |
561 |
|
299 |
562 |
private boolean isNoLastActionMarker(Marker marker) {
|
... | ... | |
306 |
569 |
return false;
|
307 |
570 |
}
|
308 |
571 |
|
309 |
|
private Taxon[] readTaxa() {
|
310 |
|
|
311 |
|
try {
|
312 |
|
Taxon taxon1 = readTaxon("Taxon to be removed");
|
313 |
|
Taxon taxon2 = readTaxon("Taxon to stay");
|
314 |
|
return new Taxon[]{taxon1, taxon2};
|
315 |
|
} catch (Exception e) {
|
316 |
|
System.out.println("Reading taxon not successful");
|
|
572 |
private TaxonBase<?>[] readTaxa() {
|
|
573 |
TaxonBase<?> taxon1 = readTaxon("Taxon to be removed");
|
|
574 |
TaxonBase<?> taxon2 = readTaxon("Taxon to stay");
|
|
575 |
if (taxon1 == null || taxon2 == null){
|
317 |
576 |
return null;
|
|
577 |
}else{
|
|
578 |
return new TaxonBase<?>[]{taxon1, taxon2};
|
318 |
579 |
}
|
319 |
580 |
}
|
320 |
581 |
|
321 |
|
private Taxon readTaxon(String message) {
|
322 |
|
String strTaxon = CdmUtils.readInputLine(message + ": ");
|
323 |
|
TaxonBase<?> taxon;
|
324 |
|
if (strTaxon.matches("\\d{1,10}")){
|
325 |
|
taxon = app.getTaxonService().find(Integer.valueOf(strTaxon));
|
326 |
|
}else if (strTaxon.matches(CdmRegEx.UUID_RE)){
|
327 |
|
taxon = app.getTaxonService().find(UUID.fromString(strTaxon));
|
328 |
|
}else{
|
329 |
|
throw new IllegalArgumentException("Input not recognized as id or uuid.");
|
|
582 |
private TaxonBase<?> readTaxon(String message) {
|
|
583 |
TaxonBase<?> taxon = null;
|
|
584 |
boolean quit = false;
|
|
585 |
while (taxon == null && quit == false){
|
|
586 |
String strTaxon = CdmUtils.readInputLine(message + ": ");
|
|
587 |
if (strTaxon.equalsIgnoreCase("q")){
|
|
588 |
quit = true;
|
|
589 |
}else{
|
|
590 |
taxon = taxonByString(strTaxon);
|
|
591 |
}
|
330 |
592 |
}
|
331 |
593 |
if (taxon == null){
|
332 |
|
throw new IllegalArgumentException("Input was not a valid taxon id.");
|
|
594 |
return null;
|
333 |
595 |
}else if (taxon.isInstanceOf(Synonym.class)){
|
334 |
|
throw new IllegalArgumentException("Input was synonym but accepted taxon required.");
|
|
596 |
return CdmBase.deproxy(taxon, Synonym.class);
|
335 |
597 |
}else{
|
336 |
598 |
return CdmBase.deproxy(taxon, Taxon.class);
|
337 |
599 |
}
|
338 |
600 |
}
|
339 |
601 |
|
|
602 |
/**
|
|
603 |
* Reads a taxon from database using it's id or uuid as String
|
|
604 |
*/
|
|
605 |
private TaxonBase<?> taxonByString(String strTaxon) {
|
|
606 |
TaxonBase<?> taxon = null;
|
|
607 |
if (strTaxon.matches("\\d{1,10}")){
|
|
608 |
taxon = app.getTaxonService().find(Integer.valueOf(strTaxon));
|
|
609 |
}else if (strTaxon.matches(CdmRegEx.UUID_RE)){
|
|
610 |
taxon = app.getTaxonService().find(UUID.fromString(strTaxon));
|
|
611 |
}
|
|
612 |
return taxon;
|
|
613 |
}
|
|
614 |
|
340 |
615 |
|
341 |
616 |
|
342 |
617 |
public static void main(String[] args) {
|
ref #1447 improve command line merger