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 }