View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Chris Henson <chenson42@users.sourceforge.net>
5    *               Eric Long <erilong@users.sourceforge.net>
6    *
7    * This library is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU Lesser General Public
9    * License as published by the Free Software Foundation; either
10   * version 3 of the License, or (at your option) any later version.
11   *
12   * This library 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 GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this library; if not, see
19   * <http://www.gnu.org/licenses/>.
20   */
21  
22  package org.jumpmind.symmetric.model;
23  
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.Date;
27  import java.util.List;
28  import java.util.StringTokenizer;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.ddlutils.model.Column;
33  import org.apache.ddlutils.model.Table;
34  
35  /***
36   * Defines the trigger via which a table will be synchronized.
37   */
38  public class Trigger {
39  
40      static final Log logger = LogFactory.getLog(Trigger.class);
41  
42      private static final long serialVersionUID = 8947288471097851573L;
43  
44      private static final String DEFAULT_CONDITION = "1=1";
45  
46      private int triggerId;
47  
48      private String sourceTableName;
49  
50      private String targetTableName;
51  
52      private String sourceGroupId;
53  
54      private String channelId;
55  
56      private String targetGroupId;
57  
58      private String sourceSchemaName;
59  
60      private String sourceCatalogName;
61  
62      private String targetSchemaName;
63  
64      private boolean syncOnUpdate = true;
65  
66      private boolean syncOnInsert = true;
67  
68      private boolean syncOnDelete = true;
69  
70      private boolean syncOnIncomingBatch = false;
71      
72      private boolean syncColumnLevel = false;
73  
74      private String nameForInsertTrigger;
75  
76      private String nameForUpdateTrigger;
77  
78      private String nameForDeleteTrigger;
79  
80      private String syncOnUpdateCondition = DEFAULT_CONDITION;
81  
82      private String syncOnInsertCondition = DEFAULT_CONDITION;
83  
84      private String syncOnDeleteCondition = DEFAULT_CONDITION;
85  
86      private String excludedColumnNames = null;
87  
88      /***
89       * Allows the end user to limit the data loaded when doing the initial load.
90       * if null, will default to 'from tablename'
91       */
92      private String initialLoadSelect = DEFAULT_CONDITION;
93  
94      /***
95       * Default to selecting all. This can be changed to select based on joins
96       * between node parameters and data column values.
97       */
98      private String nodeSelect = "";
99  
100     /***
101      * This is a sql expression that creates a unique id which the sync process
102      * can use to 'group' events together and commit together.
103      */
104     private String txIdExpression = null;
105 
106     /***
107      * This is the order in which the definitions will be processed.
108      */
109     private int initialLoadOrder;
110 
111     private Date inactiveTime;
112 
113     private Date createdOn;
114 
115     private Date lastModifiedTime;
116 
117     private String updatedBy;
118 
119     public Trigger() {
120     }
121 
122     public Trigger(String tableName, boolean syncOnUpdate, boolean syncOnInsert, boolean syncOnDelete,
123             String configurationId, String channelId, String syncOnUpdateCondition, String syncOnInsertCondition,
124             String syncOnDeleteCondition) {
125         this.sourceTableName = tableName;
126         this.syncOnUpdate = syncOnUpdate;
127         this.syncOnInsert = syncOnInsert;
128         this.syncOnDelete = syncOnDelete;
129         this.sourceGroupId = configurationId;
130         this.channelId = channelId;
131         this.syncOnUpdateCondition = syncOnUpdateCondition;
132         this.syncOnInsertCondition = syncOnInsertCondition;
133         this.syncOnDeleteCondition = syncOnDeleteCondition;
134     }
135 
136     public Date getCreatedOn() {
137         return createdOn;
138     }
139 
140     public Date getLastModifiedTime() {
141         return lastModifiedTime;
142     }
143 
144     public String getUpdatedBy() {
145         return updatedBy;
146     }
147 
148     public void setCreatedOn(Date createdOn) {
149         this.createdOn = createdOn;
150     }
151 
152     public void setLastModifiedTime(Date lastModifiedOn) {
153         this.lastModifiedTime = lastModifiedOn;
154     }
155 
156     public void setUpdatedBy(String updatedBy) {
157         this.updatedBy = updatedBy;
158     }
159 
160     /***
161      * When dealing with columns, always use this method to order the columns so
162      * that the primary keys are first.
163      */
164     public Column[] orderColumnsForTable(Table table) {
165         List<String> excludedColumnNames = getExcludedColumnNamesAsList();
166         Column[] pks = table.getPrimaryKeyColumns();
167         Column[] cols = table.getColumns();
168         List<Column> orderedColumns = new ArrayList<Column>(cols.length);
169         for (int i = 0; i < pks.length; i++) {
170             orderedColumns.add(pks[i]);
171         }
172         for (int i = 0; i < cols.length; i++) {
173             Column col = cols[i];
174             if (!col.isPrimaryKey() && !excludedColumnNames.contains(col.getName().toLowerCase())) {
175                 orderedColumns.add(col);
176             }
177         }
178         return orderedColumns.toArray(new Column[orderedColumns.size()]);
179     }
180 
181     @SuppressWarnings("unchecked")
182     private List<String> getExcludedColumnNamesAsList() {
183         if (excludedColumnNames != null && excludedColumnNames.length() > 0) {
184             StringTokenizer tokenizer = new StringTokenizer(excludedColumnNames, ",");
185             List<String> columnNames = new ArrayList<String>(tokenizer.countTokens());
186             while (tokenizer.hasMoreTokens()) {
187                 columnNames.add(tokenizer.nextToken().toLowerCase());
188             }
189             return columnNames;
190         } else {
191             return Collections.EMPTY_LIST;
192         }
193     }
194 
195     public boolean hasChangedSinceLastTriggerBuild(Date lastTriggerBuildTime) {
196         return lastTriggerBuildTime == null || getLastModifiedTime() == null
197                 || lastTriggerBuildTime.before(getLastModifiedTime());
198     }
199 
200     public String getChannelId() {
201         return channelId;
202     }
203 
204     public void setChannelId(String channelId) {
205         this.channelId = channelId;
206     }
207 
208     public String getSourceGroupId() {
209         return sourceGroupId;
210     }
211 
212     public void setSourceGroupId(String domainName) {
213         this.sourceGroupId = domainName;
214     }
215 
216     public boolean isSyncOnDelete() {
217         return syncOnDelete;
218     }
219 
220     public void setSyncOnDelete(boolean syncOnDelete) {
221         this.syncOnDelete = syncOnDelete;
222     }
223 
224     public String getSyncOnDeleteCondition() {
225         return syncOnDeleteCondition;
226     }
227 
228     public void setSyncOnDeleteCondition(String syncOnDeleteCondition) {
229         this.syncOnDeleteCondition = syncOnDeleteCondition;
230     }
231 
232     public boolean isSyncOnInsert() {
233         return syncOnInsert;
234     }
235 
236     public void setSyncOnInsert(boolean syncOnInsert) {
237         this.syncOnInsert = syncOnInsert;
238     }
239 
240     public String getSyncOnInsertCondition() {
241         return syncOnInsertCondition;
242     }
243 
244     public void setSyncOnInsertCondition(String syncOnInsertCondition) {
245         this.syncOnInsertCondition = syncOnInsertCondition;
246     }
247 
248     public boolean isSyncOnUpdate() {
249         return syncOnUpdate;
250     }
251 
252     public void setSyncOnUpdate(boolean syncOnUpdate) {
253         this.syncOnUpdate = syncOnUpdate;
254     }
255 
256     public String getSyncOnUpdateCondition() {
257         return syncOnUpdateCondition;
258     }
259 
260     public void setSyncOnUpdateCondition(String syncOnUpdateCondition) {
261         this.syncOnUpdateCondition = syncOnUpdateCondition;
262     }
263 
264     public String getSourceTableName() {
265         return sourceTableName;
266     }
267 
268     public void setSourceTableName(String tableName) {
269         this.sourceTableName = tableName;
270     }
271 
272     public String getNodeSelect() {
273         return nodeSelect;
274     }
275 
276     public void setNodeSelect(String registrantSelect) {
277         this.nodeSelect = registrantSelect;
278     }
279 
280     public String getTxIdExpression() {
281         return txIdExpression;
282     }
283 
284     public void setTxIdExpression(String batchIdExpression) {
285         this.txIdExpression = batchIdExpression;
286     }
287 
288     public String getInitialLoadSelect() {
289         return initialLoadSelect;
290     }
291 
292     public void setInitialLoadSelect(String initialLoadExpression) {
293         this.initialLoadSelect = initialLoadExpression;
294     }
295 
296     public int getInitialLoadOrder() {
297         return initialLoadOrder;
298     }
299 
300     public void setInitialLoadOrder(int order) {
301         this.initialLoadOrder = order;
302     }
303 
304     public String getSourceSchemaName() {
305         return sourceSchemaName;
306     }
307 
308     public void setSourceSchemaName(String schemaName) {
309         this.sourceSchemaName = schemaName;
310     }
311 
312     public String getExcludedColumnNames() {
313         return excludedColumnNames;
314     }
315 
316     public void setExcludedColumnNames(String excludeColumnNames) {
317         this.excludedColumnNames = excludeColumnNames;
318     }
319 
320     public String getTargetGroupId() {
321         return targetGroupId;
322     }
323 
324     public void setTargetGroupId(String targetDomainName) {
325         this.targetGroupId = targetDomainName;
326     }
327 
328     public String getNameForDeleteTrigger() {
329         return nameForDeleteTrigger;
330     }
331 
332     public void setNameForDeleteTrigger(String nameForDeleteTrigger) {
333         this.nameForDeleteTrigger = nameForDeleteTrigger;
334     }
335 
336     public String getNameForInsertTrigger() {
337         return nameForInsertTrigger;
338     }
339 
340     public void setNameForInsertTrigger(String nameForInsertTrigger) {
341         this.nameForInsertTrigger = nameForInsertTrigger;
342     }
343 
344     public String getNameForUpdateTrigger() {
345         return nameForUpdateTrigger;
346     }
347 
348     public void setNameForUpdateTrigger(String nameForUpdateTrigger) {
349         this.nameForUpdateTrigger = nameForUpdateTrigger;
350     }
351 
352     public int getTriggerId() {
353         return triggerId;
354     }
355 
356     public void setTriggerId(int triggerId) {
357         this.triggerId = triggerId;
358     }
359 
360     public Date getInactiveTime() {
361         return inactiveTime;
362     }
363 
364     public void setInactiveTime(Date inactiveTime) {
365         this.inactiveTime = inactiveTime;
366     }
367 
368     public String getTargetSchemaName() {
369         return targetSchemaName;
370     }
371 
372     public void setTargetSchemaName(String targetSchemaName) {
373         this.targetSchemaName = targetSchemaName;
374     }
375 
376     public String getTargetTableName() {
377         return targetTableName;
378     }
379 
380     public void setTargetTableName(String targetTableName) {
381         this.targetTableName = targetTableName;
382     }
383 
384     public boolean isSyncOnIncomingBatch() {
385         return syncOnIncomingBatch;
386     }
387 
388     public void setSyncOnIncomingBatch(boolean syncOnIncomingBatch) {
389         this.syncOnIncomingBatch = syncOnIncomingBatch;
390     }
391 
392     public String getSourceCatalogName() {
393         return sourceCatalogName;
394     }
395 
396     public void setSourceCatalogName(String sourceCatalogName) {
397         this.sourceCatalogName = sourceCatalogName;
398     }
399 
400     public boolean isSyncColumnLevel() {
401         return syncColumnLevel;
402     }
403 
404     public void setSyncColumnLevel(boolean syncColumnLevel) {
405         this.syncColumnLevel = syncColumnLevel;
406     }
407     
408     public long getHashedValue() {
409         long hashedValue = triggerId;
410         if (null != sourceTableName) {
411             hashedValue += sourceTableName.hashCode();
412         }
413 
414         if (null != targetTableName ) {
415             hashedValue += targetTableName.hashCode();
416         }
417 
418         if (null != sourceGroupId) {
419             hashedValue += sourceGroupId.hashCode();
420         }
421 
422         if (null != channelId) {
423             hashedValue += channelId.hashCode();
424         }
425 
426         if (null != targetGroupId) {
427             hashedValue += targetGroupId.hashCode();
428         }
429 
430         if (null != sourceSchemaName) {
431             hashedValue += sourceSchemaName.hashCode();
432         }
433 
434         if (null != sourceCatalogName) {
435             hashedValue += sourceCatalogName.hashCode();
436         }
437 
438         if (null != targetSchemaName) {
439             hashedValue += targetSchemaName.hashCode();
440         }
441 
442         hashedValue += syncOnUpdate ? 1 : 0;
443         hashedValue += syncOnInsert ? 1 : 0;
444         hashedValue += syncOnDelete ? 1 : 0;
445         hashedValue += syncOnIncomingBatch ? 1 : 0;
446         hashedValue += syncColumnLevel ? 1 : 0;
447 
448         if (null != nameForInsertTrigger) {
449             hashedValue += nameForInsertTrigger.hashCode();
450         }
451 
452         if (null != nameForUpdateTrigger) {
453             hashedValue += nameForUpdateTrigger.hashCode();
454         }
455 
456         if (null != nameForDeleteTrigger) {
457             hashedValue += nameForDeleteTrigger.hashCode();
458         }
459 
460         if (null != syncOnUpdateCondition) {
461             hashedValue += syncOnUpdateCondition.hashCode();
462         }
463 
464         if (null != syncOnInsertCondition) {
465             hashedValue += syncOnInsertCondition.hashCode();
466         }
467 
468         if (null != syncOnDeleteCondition)  {
469             hashedValue += syncOnDeleteCondition.hashCode();
470         }
471 
472         if (null != excludedColumnNames)  {
473             hashedValue += excludedColumnNames.hashCode();
474         }
475         
476         return hashedValue;
477     }
478 
479 }