9c8655c4639973769518d126244d58ef078c7718
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / database / update / RelationSwapper.java
1 /**
2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.cdm.database.update;
10
11 import java.sql.SQLException;
12 import java.util.List;
13 import java.util.UUID;
14
15 import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
16
17 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
18 import eu.etaxonomy.cdm.database.ICdmDataSource;
19
20 /**
21 * Swaps a relationship. The related_from object becomes the related_to object
22 * and vice versa. Also the relationship type label and inverse label are swapped.
23 *
24 * @author a.mueller
25 * @since 07.11.2020
26 */
27 public class RelationSwapper extends AuditedSchemaUpdaterStepBase {
28
29 private static final Logger logger = LogManager.getLogger(RelationSwapper.class);
30
31 private static final int PLACEHOLDER = -987;
32
33 private String relTypeColumnName;
34 private UUID uuidRelationType;
35 private String newTitleCache;
36 private String newIdInVocabulary;
37
38 /**
39 * @param tableName the relations table name
40 * @param uuidRelationType
41 * @param newIdInVocabulary if not <code>null</code> the newIdInVocabulary is updated
42 * @return
43 */
44 public static final RelationSwapper NewInstance(List<ISchemaUpdaterStep> stepList, String stepName,
45 String tableName, UUID uuidRelationType, String relTypeColumnName,
46 String newTitleCache, String newIdInVocabulary, boolean includeAudit){
47 return new RelationSwapper(stepList, stepName, tableName, uuidRelationType,
48 relTypeColumnName, newTitleCache, newIdInVocabulary, includeAudit);
49 }
50
51 private RelationSwapper(List<ISchemaUpdaterStep> stepList, String stepName,
52 String tableName, UUID uuidRelationType, String relTypeColumnName,
53 String newTitleCache, String newIdInVocabulary, boolean includeAudit) {
54 super(stepList, stepName, tableName, includeAudit);
55 this.uuidRelationType = uuidRelationType;
56 this.relTypeColumnName = relTypeColumnName;
57 this.newTitleCache = newTitleCache;
58 this.newIdInVocabulary = newIdInVocabulary;
59 }
60
61 @Override
62 protected void invokeOnTable(String tableName, ICdmDataSource datasource, IProgressMonitor monitor,
63 CaseType caseType, SchemaUpdateResult result) {
64
65 try {
66 String defTermTable = this.isAuditing ? "DefinedTermBase_AUD": "DefinedTermBase ";
67 String mnTable = this.isAuditing ? "DefinedTermBase_Representation_AUD": "DefinedTermBase_Representation ";
68 String inverseMnTable = this.isAuditing ? "DefinedTermBase_InverseRepresentation_AUD": "DefinedTermBase_InverseRepresentation ";
69 String audParams = this.isAuditing ? ", REV, REVTYPE ": "";
70
71 //get relType id
72 String sql = " SELECT id FROM %s WHERE uuid = '%s'";
73 Integer termId = (Integer)datasource.getSingleValue(String.format(sql,
74 caseType.transformTo(defTermTable) , this.uuidRelationType));
75
76 if (termId == null || termId == 0){
77 String message = "RelationshipType term ("+uuidRelationType+") does not exist. Can't swap terms";
78 monitor.warning(message);
79 logger.warn(message);
80 result.addError(message, this, "invoke");
81 return;
82 }
83
84 //swap relatedFrom and relatedTo
85 sql = " UPDATE %s "
86 + " SET relatedFrom_id = relatedTo_id, relatedTo_id = relatedFrom_id "
87 + " WHERE %s = %d ";
88 sql = String.format(sql, caseType.transformTo(tableName), this.relTypeColumnName, termId);
89 datasource.executeUpdate(sql);
90
91 // insert inverse into not-inverse with placeholder term id
92 sql = " INSERT INTO %s (definedTermBase_id, representations_id %s) "
93 + " SELECT %d, inverseRepresentations_id %s"
94 + " FROM %s "
95 + " WHERE DefinedTermBase_id = %d ";
96 sql = String.format(sql, caseType.transformTo(mnTable),
97 audParams, PLACEHOLDER, audParams, caseType.transformTo(inverseMnTable), termId);
98 datasource.executeUpdate(sql);
99
100 // delete inverse terms
101 sql = " DELETE FROM %s WHERE definedTermBase_id = %d ";
102 sql = String.format(sql, caseType.transformTo(inverseMnTable), termId);
103 datasource.executeUpdate(sql);
104
105 // insert not-inverse into inverse with placeholder term id
106 sql = " INSERT INTO %s (definedTermBase_id, inverseRepresentations_id %s) "
107 + " SELECT definedTermBase_id, representations_id %s "
108 + " FROM %s "
109 + " WHERE DefinedTermBase_id = %d ";
110 sql = String.format(sql, caseType.transformTo(inverseMnTable),
111 audParams, audParams, caseType.transformTo(mnTable), termId);
112 datasource.executeUpdate(sql);
113
114 // delete inverse terms
115 sql = " DELETE FROM %s WHERE definedTermBase_id = %d ";
116 sql = String.format(sql, caseType.transformTo(mnTable), termId);
117 datasource.executeUpdate(sql);
118
119 // replace placeholder in former inverse terms
120 sql = " UPDATE %s SET definedTermBase_id = %d WHERE definedTermBase_id = %d ";
121 sql = String.format(sql, caseType.transformTo(mnTable), termId, PLACEHOLDER);
122 datasource.executeUpdate(sql);
123
124 //new titleCache
125 //NOTE: of course better the titleCache would be computed then set manually, but in most
126 //cases this should be ok for now
127 if (this.newTitleCache != null){
128 sql = " UPDATE %s SET titleCache = '%s' WHERE id = %d ";
129 sql = String.format(sql, caseType.transformTo(defTermTable), newTitleCache , termId);
130 datasource.executeUpdate(sql);
131 }
132
133 //new idInVoc
134 if (this.newIdInVocabulary != null){
135 sql = " UPDATE %s SET idInVocabulary = '%d' WHERE id = %d ";
136 sql = String.format(sql, caseType.transformTo(defTermTable), newIdInVocabulary , termId);
137 datasource.executeUpdate(sql);
138 }
139
140 //symbols
141 //not yet implemented
142
143 } catch (SQLException e) {
144 String message = e.getMessage();
145 monitor.warning(message, e);
146 logger.error(e);
147 result.addException(e, message, getStepName() + ", RelationSwapper.invokeOnTable");
148 return;
149 }
150
151 return;
152 }
153
154 }