View Javadoc

1   /**
2    * Copyright (c) 2011, University of Konstanz, Distributed Systems Group
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    * * Redistributions of source code must retain the above copyright
8    * notice, this list of conditions and the following disclaimer.
9    * * Redistributions in binary form must reproduce the above copyright
10   * notice, this list of conditions and the following disclaimer in the
11   * documentation and/or other materials provided with the distribution.
12   * * Neither the name of the University of Konstanz nor the
13   * names of its contributors may be used to endorse or promote products
14   * derived from this software without specific prior written permission.
15   * 
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   */
27  
28  package org.treetank.service.xml.diff;
29  
30  import static com.google.common.base.Preconditions.checkState;
31  
32  import java.util.Set;
33  
34  import org.treetank.api.ISession;
35  import org.treetank.exception.TTException;
36  
37  /**
38   * Wrapper for public access.
39   * 
40   * @author Johannes Lichtenberger, University of Konstanz
41   * 
42   */
43  public final class DiffFactory {
44      public static final String RESOURCENAME = "bla";
45  
46      /**
47       * Possible kinds of differences between two nodes.
48       */
49      public enum EDiff {
50          /** Nodes are the same. */
51          SAME,
52  
53          /**
54           * Nodes are the same (including subtrees), internally used for
55           * optimizations.
56           */
57          SAMEHASH,
58  
59          /** Node has been inserted. */
60          INSERTED,
61  
62          /** Node has been deleted. */
63          DELETED,
64  
65          /** Node has been updated. */
66          UPDATED
67      }
68  
69      /**
70       * Determines if an optimized diff calculation should be done, which is
71       * faster.
72       */
73      public enum EDiffOptimized {
74          /** Normal diff. */
75          NO,
76  
77          /** Optimized diff. */
78          HASHED
79      }
80  
81      /** Determines the kind of diff to invoke. */
82      private enum DiffKind {
83          /** Full diff. */
84          FULL {
85              @Override
86              void invoke(final Builder paramBuilder) throws TTException {
87                  final FullDiff diff = new FullDiff(paramBuilder);
88                  diff.diffMovement();
89              }
90          },
91  
92          /**
93           * Structural diff (doesn't recognize differences in namespace and
94           * attribute nodes.
95           */
96          STRUCTURAL {
97              @Override
98              void invoke(final Builder paramBuilder) throws TTException {
99                  final StructuralDiff diff = new StructuralDiff(paramBuilder);
100                 diff.diffMovement();
101             }
102         };
103 
104         /**
105          * Invoke diff.
106          * 
107          * @param paramBuilder
108          *            {@link Builder} reference
109          * @throws TTException
110          *             if anything while diffing goes wrong related to Treetank
111          */
112         abstract void invoke(final Builder paramBuilder) throws TTException;
113     }
114 
115     /** Builder to simplify static methods. */
116     public static final class Builder {
117 
118         /** {@link ISession} reference. */
119         final ISession mSession;
120 
121         /** Start key. */
122         final long mKey;
123 
124         /** New revision. */
125         final long mNewRev;
126 
127         /** Old revision. */
128         final long mOldRev;
129 
130         /** Depth of "root" node in new revision. */
131         transient int mNewDepth;
132 
133         /** Depth of "root" node in old revision. */
134         transient int mOldDepth;
135 
136         /** Diff kind. */
137         final EDiffOptimized mKind;
138 
139         /** {@link Set} of {@link IDiffObserver}s. */
140         final Set<IDiffObserver> mObservers;
141 
142         /**
143          * Constructor.
144          * 
145          * @param paramDb
146          *            {@link ISession} instance
147          * @param paramKey
148          *            key of start node
149          * @param paramNewRev
150          *            new revision to compare
151          * @param paramOldRev
152          *            old revision to compare
153          * @param paramDiffKind
154          *            kind of diff (optimized or not)
155          * @param paramObservers
156          *            {@link Set} of observers
157          */
158         public Builder(final ISession paramDb, final long paramKey, final long paramNewRev,
159             final long paramOldRev, final EDiffOptimized paramDiffKind,
160             final Set<IDiffObserver> paramObservers) {
161             mSession = paramDb;
162             mKey = paramKey;
163             mNewRev = paramNewRev;
164             mOldRev = paramOldRev;
165             mKind = paramDiffKind;
166             mObservers = paramObservers;
167         }
168 
169     }
170 
171     /**
172      * Private constructor.
173      */
174     private DiffFactory() {
175         // No instantiation allowed.
176         throw new AssertionError("No instantiation allowed!");
177     }
178 
179     /**
180      * Do a full diff.
181      * 
182      * @param paramBuilder
183      *            {@link Builder} reference
184      * @throws TTException
185      */
186     public static synchronized void invokeFullDiff(final Builder paramBuilder) throws TTException {
187         checkParams(paramBuilder);
188         DiffKind.FULL.invoke(paramBuilder);
189     }
190 
191     /**
192      * Do a structural diff.
193      * 
194      * @param paramBuilder
195      *            {@link Builder} reference
196      * @throws TTException
197      */
198     public static synchronized void invokeStructuralDiff(final Builder paramBuilder) throws TTException {
199         checkParams(paramBuilder);
200         DiffKind.STRUCTURAL.invoke(paramBuilder);
201     }
202 
203     /**
204      * Check parameters for validity and assign global static variables.
205      * 
206      * @param paramBuilder
207      *            {@link Builder} reference
208      */
209     private static void checkParams(final Builder paramBuilder) {
210         checkState(paramBuilder.mSession != null && paramBuilder.mKey >= 0 && paramBuilder.mNewRev >= 0
211             && paramBuilder.mOldRev >= 0 && paramBuilder.mObservers != null && paramBuilder.mKind != null,
212             "No valid arguments specified!");
213         checkState(
214             paramBuilder.mNewRev != paramBuilder.mOldRev && paramBuilder.mNewRev >= paramBuilder.mOldRev,
215             "Revision numbers must not be the same and the new revision must have a greater number than the old revision!");
216     }
217 }