use of org.sirix.diff.DiffFactory.DiffType in project sirix by sirixdb.
the class AbstractDiff method optimizedDiff.
/**
* Optimized diff, which skips unnecessary comparsions.
*
* @param newRtx {@link XdmNodeReadTrx} on new revision
* @param oldRtx {@link XdmNodeReadTrx} on old revision
* @param depth {@link DepthCounter} container for current depths of both transaction cursors
* @param paramFireDiff determines if a diff should be fired
* @return kind of difference
*/
DiffType optimizedDiff(final XdmNodeReadTrx newRtx, final XdmNodeReadTrx oldRtx, final DepthCounter depth) {
assert newRtx != null;
assert oldRtx != null;
assert depth != null;
DiffType diff = DiffType.SAMEHASH;
// Check for modifications.
switch(newRtx.getKind()) {
case DOCUMENT:
case TEXT:
case ELEMENT:
if (newRtx.getNodeKey() != oldRtx.getNodeKey() || newRtx.getHash() != oldRtx.getHash()) {
// Check if nodes are the same (even if subtrees may vary).
if (checkNodes(newRtx, oldRtx)) {
diff = DiffType.SAME;
final DiffDepth diffDepth = new DiffDepth(depth.getNewDepth(), depth.getOldDepth());
fireDiff(diff, newRtx.getNodeKey(), oldRtx.getNodeKey(), diffDepth);
emitNonStructuralDiff(newRtx, oldRtx, diffDepth, diff);
} else {
diff = diffAlgorithm(newRtx, oldRtx, depth);
}
} else {
final DiffDepth diffDepth = new DiffDepth(depth.getNewDepth(), depth.getOldDepth());
fireDiff(diff, newRtx.getNodeKey(), oldRtx.getNodeKey(), diffDepth);
emitNonStructuralDiff(newRtx, oldRtx, diffDepth, diff);
}
break;
default:
}
return diff;
}
use of org.sirix.diff.DiffFactory.DiffType in project sirix by sirixdb.
the class AbstractDiff method diffAlgorithm.
/**
* Main algorithm to compute diffs between two nodes.
*
* @param newRtx {@link XdmNodeReadTrx} on new revision
* @param oldRtx {@link XdmNodeReadTrx} on old revision
* @param depth {@link DepthCounter} container for current depths of both transaction cursors
* @return kind of diff
*/
private DiffType diffAlgorithm(final XdmNodeReadTrx newRtx, final XdmNodeReadTrx oldRtx, final DepthCounter depth) {
assert newRtx != null;
assert oldRtx != null;
assert depth != null;
DiffType diff = null;
if (depth.getOldDepth() > depth.getNewDepth()) {
// Check if node has been
// deleted.
diff = DiffType.DELETED;
emitDiffs(diff);
} else if (checkUpdate(newRtx, oldRtx)) {
// Check if node has been updated.
diff = DiffType.UPDATED;
final DiffDepth diffDepth = new DiffDepth(depth.getNewDepth(), depth.getOldDepth());
fireDiff(diff, newRtx.getNodeKey(), oldRtx.getNodeKey(), diffDepth);
emitNonStructuralDiff(newRtx, oldRtx, diffDepth, diff);
} else if (checkReplace(newRtx, oldRtx)) {
// Check if node has been
// replaced.
diff = DiffType.REPLACED;
} else {
final long oldKey = oldRtx.getNodeKey();
final boolean movedOld = oldRtx.moveTo(newRtx.getNodeKey()).hasMoved();
oldRtx.moveTo(oldKey);
final long newKey = newRtx.getNodeKey();
final boolean movedNew = newRtx.moveTo(oldRtx.getNodeKey()).hasMoved();
newRtx.moveTo(newKey);
if (!movedOld) {
diff = DiffType.INSERTED;
} else if (!movedNew) {
diff = DiffType.DELETED;
} else {
// Determine if one of the right sibling matches.
EFoundEqualNode found = EFoundEqualNode.FALSE;
while (oldRtx.hasRightSibling() && oldRtx.moveToRightSibling().hasMoved() && found == EFoundEqualNode.FALSE) {
if (checkNodes(newRtx, oldRtx)) {
found = EFoundEqualNode.TRUE;
break;
}
}
oldRtx.moveTo(oldKey);
diff = found.kindOfDiff();
}
mDiff = diff;
emitDiffs(diff);
}
assert diff != null;
return diff;
}
use of org.sirix.diff.DiffFactory.DiffType in project sirix by sirixdb.
the class AbstractDiff method diff.
/**
* Diff of nodes.
*
* @param newRtx {@link XdmNodeReadTrx} on new revision
* @param oldRtx {@link XdmNodeReadTrx} on old revision
* @param depth {@link DepthCounter} container for current depths of both transaction cursors
* @param paramFireDiff determines if a diff should be fired
* @return kind of difference
*/
DiffType diff(final XdmNodeReadTrx newRtx, final XdmNodeReadTrx oldRtx, final DepthCounter depth) {
assert newRtx != null;
assert oldRtx != null;
assert depth != null;
DiffType diff = DiffType.SAME;
// Check for modifications.
switch(newRtx.getKind()) {
case DOCUMENT:
case TEXT:
case ELEMENT:
if (checkNodes(newRtx, oldRtx)) {
final DiffDepth diffDepth = new DiffDepth(depth.getNewDepth(), depth.getOldDepth());
fireDiff(diff, newRtx.getNodeKey(), oldRtx.getNodeKey(), diffDepth);
emitNonStructuralDiff(newRtx, oldRtx, diffDepth, diff);
} else {
diff = diffAlgorithm(newRtx, oldRtx, depth);
}
break;
default:
}
return diff;
}
use of org.sirix.diff.DiffFactory.DiffType in project sirix by sirixdb.
the class TraverseCompareTree method createSunburstItem.
@Override
public float createSunburstItem(final Item pItem, @Nonnegative final int pDepth, @Nonnegative final int pIndex) {
checkNotNull(pItem);
checkArgument(pDepth >= 0, "pDepth must be positive!");
checkArgument(pIndex >= 0, "pIndex must be >= 0!");
// Initialize variables.
final float angle = pItem.mAngle;
final float parExtension = pItem.mExtension;
final int indexToParent = pItem.mIndexToParent;
final int descendantCount = pItem.mDescendantCount;
final int parentDescCount = pItem.mParentDescendantCount;
final int modificationCount = pItem.mModificationCount;
long parentModificationCount = pItem.mParentModificationCount;
final boolean subtract = pItem.mSubtract;
final DiffTuple diffCont = pItem.mDiff;
final int origDepth = pItem.mOrigDepth;
final int nextDepth = pItem.mNextDepth;
final int depth = pDepth;
// Calculate extension.
float extension = 2 * PConstants.PI;
if (indexToParent > -1) {
if (mItems.get(indexToParent).getSubtract()) {
parentModificationCount -= FACTOR;
}
extension = (1f - mModWeight) * (parExtension * (float) descendantCount / ((float) parentDescCount - 1f)) + mModWeight * // modificationCount/parentModificationCount.
(parExtension * (float) modificationCount / ((float) parentModificationCount - 1f));
}
LOGWRAPPER.debug("ITEM: " + pIndex);
LOGWRAPPER.debug("modificationCount: " + modificationCount);
LOGWRAPPER.debug("parentModificationCount: " + parentModificationCount);
LOGWRAPPER.debug("descendantCount: " + descendantCount);
LOGWRAPPER.debug("parentDescCount: " + parentDescCount);
LOGWRAPPER.debug("indexToParent: " + indexToParent);
LOGWRAPPER.debug("extension: " + extension);
LOGWRAPPER.debug("depth: " + depth);
LOGWRAPPER.debug("next Depth: " + nextDepth);
LOGWRAPPER.debug("angle: " + angle);
if (mPrune == Pruning.ITEMSIZE && extension < TraverseModel.ANGLE_TO_PRUNE && modificationCount <= descendantCount) {
nodePruned();
} else {
// Add a sunburst item.
if (mPrune == Pruning.DIFF && diffCont.getDiff() == DiffType.SAMEHASH) {
mIsPruned = true;
} else {
mIsPruned = false;
}
final NodeReadTrx rtx = (diffCont.getDiff() == DiffType.DELETED || diffCont.getDiff() == DiffType.MOVEDFROM || diffCont.getDiff() == DiffType.REPLACEDOLD) ? mOldRtx : mNewRtx;
final EStructType structKind = nextDepth > depth ? EStructType.ISINNERNODE : EStructType.ISLEAFNODE;
// Set node relations.
String text = "";
NodeRelations relations = null;
final DiffType currDiff = diffCont.getDiff();
if (rtx.getKind() == Kind.TEXT) {
if (currDiff == DiffType.DELETED || currDiff == DiffType.MOVEDFROM || currDiff == DiffType.REPLACEDOLD) {
text = mOldRtx.getValue();
} else {
text = mNewRtx.getValue();
}
if (currDiff == DiffType.UPDATED || ((currDiff == DiffType.REPLACEDNEW || currDiff == DiffType.REPLACEDOLD) && mOldRtx.getKind() == mNewRtx.getKind())) {
final String oldValue = mOldRtx.getValue();
final String newValue = mNewRtx.getValue();
float similarity = 1;
// try {
// Integer.parseInt(oldValue);
// Integer.parseInt(newValue);
//
// // TODO: Implement similarity measure on numerical data (easy!).
// } catch (final NumberFormatException e) {
similarity = mLevenshtein.getSimilarity(oldValue, newValue);
// }
relations = new NodeRelations(origDepth, depth, structKind, similarity, 0, 1, indexToParent).setSubtract(subtract);
} else if (currDiff == DiffType.SAME || currDiff == DiffType.SAMEHASH) {
relations = new NodeRelations(origDepth, depth, structKind, 1, 0, 1, indexToParent).setSubtract(subtract);
} else {
relations = new NodeRelations(origDepth, depth, structKind, 0, 0, 1, indexToParent).setSubtract(subtract);
}
} else {
if (mMaxDescendantCount == 0) {
if (mPrune == Pruning.NO) {
try {
mMaxDescendantCount = mMaxDescendantCountFuture.get().getDescendants();
} catch (final InterruptedException | ExecutionException e) {
LOGWRAPPER.error(e.getMessage(), e);
}
} else {
mMaxDescendantCount = mAxis.getDescendantCount();
}
}
relations = new NodeRelations(origDepth, depth, structKind, descendantCount, 1, mMaxDescendantCount, indexToParent).setSubtract(subtract);
}
// Build item.
final SunburstItem.Builder builder = new SunburstItem.Builder(mParent, angle, extension, relations, mDb, mGUI).setNodeKey(rtx.getNodeKey()).setKind(rtx.getKind()).setDiff(diffCont.getDiff());
if (modificationCount > descendantCount) {
final int diffCounts = (modificationCount - descendantCount) / TraverseModel.FACTOR;
LOGWRAPPER.debug("modCount: " + diffCounts);
builder.setModifications(diffCounts);
}
if (text.isEmpty()) {
QNm name = null;
if (diffCont.getDiff() == DiffType.DELETED || diffCont.getDiff() == DiffType.MOVEDFROM || diffCont.getDiff() == DiffType.REPLACEDOLD) {
name = mOldRtx.getName();
builder.setAttributes(fillAttributes(mOldRtx));
builder.setNamespaces(fillNamespaces(mOldRtx));
builder.setOldKey(mOldRtx.getNodeKey());
LOGWRAPPER.debug("name: " + name.getLocalName());
builder.setOldQName(name);
} else {
name = mNewRtx.getName();
builder.setAttributes(fillAttributes(mNewRtx));
builder.setNamespaces(fillNamespaces(mNewRtx));
LOGWRAPPER.debug("name: " + name.getLocalName());
builder.setQName(name);
}
} else {
LOGWRAPPER.debug("text: " + text);
if (currDiff == DiffType.DELETED || currDiff == DiffType.MOVEDFROM || currDiff == DiffType.REPLACEDOLD) {
builder.setOldText(text);
builder.setOldKey(mOldRtx.getNodeKey());
} else {
builder.setText(text);
}
}
updated(diffCont.getDiff(), builder);
final SunburstItem item = builder.build();
if (item.getDiff() == DiffType.MOVEDFROM) {
LOGWRAPPER.debug("movedToIndex: " + diffCont.getIndex());
item.setIndexMovedTo(diffCont.getIndex() - mAxis.getPrunedNodes());
}
mItems.add(item);
// Set depth max.
mNewDepthMax = Math.max(depth, mNewDepthMax);
}
return extension;
}
use of org.sirix.diff.DiffFactory.DiffType in project sirix by sirixdb.
the class Modifications method countDiffs.
/**
* Count how many differences in the subtree exists and add descendant-or-self
* count.
*
* @return number of differences and descendants
* @throws SirixException
* if sirix can't close the transaction
*/
public Modification countDiffs() throws SirixException {
int index = mIndex;
final DiffTuple diffCont = mDiffs.get(index);
final DiffType diff = diffCont.getDiff();
final int rootDepth = (diff == DiffType.DELETED || diff == DiffType.MOVEDFROM || diff == DiffType.REPLACEDOLD) ? diffCont.getDepth().getOldDepth() : diffCont.getDepth().getNewDepth();
int diffCounts = 0;
int descendantCounts = 1;
boolean subtract = false;
diffCounts = incrDiffCounter(index, diffCounts);
index++;
if (diffCounts == 1 && index < mDiffs.size()) {
final DiffTuple cont = mDiffs.get(index);
final int depth = (cont.getDiff() == DiffType.DELETED || cont.getDiff() == DiffType.MOVEDFROM || cont.getDiff() == DiffType.REPLACEDOLD) ? cont.getDepth().getOldDepth() : cont.getDepth().getNewDepth();
if (depth == rootDepth + 1) {
// Current node is modified and has at least one child.
subtract = true;
}
}
boolean done = false;
while (!done && index < mDiffs.size()) {
final DiffTuple currDiffCont = mDiffs.get(index);
final DiffType currDiff = currDiffCont.getDiff();
final DiffDepth currDepth = currDiffCont.getDepth();
final int depth = (currDiff == DiffType.DELETED || currDiff == DiffType.MOVEDFROM || currDiff == DiffType.REPLACEDOLD) ? currDepth.getOldDepth() : currDepth.getNewDepth();
if (depth <= rootDepth) {
done = true;
}
if (!done) {
descendantCounts++;
if (currDiff != DiffType.SAME && currDiff != DiffType.SAMEHASH) {
diffCounts++;
}
index++;
}
}
// Add a factor to add some weighting to the diffCounts.
return new Modification(TraverseModel.FACTOR * diffCounts, descendantCounts, subtract);
}
Aggregations