/** * Factory method for creating new child state builders. Subclasses may * override this method to control the behavior of child state builders. * @return new builder */ protected MemoryNodeBuilder createChildBuilder(String name) { return new MemoryNodeBuilder(this, name); }
@Override public boolean propertyAdded(@NotNull PropertyState after) { builder.setProperty(after); return true; }
@NotNull @Override public NodeBuilder child(@NotNull String name) { if (hasChildNode(name)) { return getChildNode(name); } else { return setChildNode(name); } }
/** * Annotate this builder with its source path if this builder has not * been transiently added. The source path is written to a property with * the name {@link MoveDetector#SOURCE_PATH}. * <p> * The source path of a builder is its current path if its current * source path annotation is empty and none of its parents has a source * path annotation set. Otherwise it is the source path of the first parent * (or self) that has its source path annotation set appended with the relative * path from that parent to this builder. * <p> * This builder has been transiently added when there exists no * base node at its source path. */ protected final void annotateSourcePath() { String sourcePath = getSourcePath(); if (!isTransientlyAdded(sourcePath)) { setProperty(MoveDetector.SOURCE_PATH, sourcePath); } }
@Override public boolean isNew() { return exists() && !getBaseState().exists(); }
private static NodeState createBC(final boolean exists) { final NodeState C = new MemoryNodeBuilder(EmptyNodeState.EMPTY_NODE) .setProperty("c", "cValue") .getNodeState();
private void updated() throws IOException { if (modCount % UPDATE_LIMIT == 0) { RecordId newBaseId = writer.writeNode(builder.getNodeState(), null); SegmentNodeState newBase = new SegmentNodeState(reader, writer, blobStore, newBaseId); builder = new MemoryNodeBuilder(newBase); } modCount++; }
checkNotNull(newParent); checkValidName(newName); if (isRoot() || !exists() || newParent.hasChildNode(newName)) { return false; } else { if (newParent.exists()) { annotateSourcePath(); NodeState nodeState = getNodeState(); newParent.setChildNode(newName, nodeState); remove(); return true; } else {
@NotNull @Override public NodeBuilder setChildNode(@NotNull String name) { return setChildNode(name, EMPTY_NODE); }
@Test public void setTest() { Assume.assumeTrue(EMPTY_NODE.builder() instanceof MemoryNodeBuilder); MemoryNodeBuilder rootBuilder = (MemoryNodeBuilder) EMPTY_NODE.builder(); assertFalse(base.equals(rootBuilder.getNodeState())); rootBuilder.set(base); assertTrue(base.equals(rootBuilder.getNodeState())); MemoryNodeBuilder xBuilder = (MemoryNodeBuilder) rootBuilder.getChildNode("x"); NodeState yState = base.getChildNode("y"); assertFalse(yState.equals(xBuilder.getNodeState())); xBuilder.set(yState); assertTrue(yState.equals(xBuilder.getNodeState())); }
@Nonnull @Override public NodeBuilder setChildNode(@Nonnull String name, @Nonnull NodeState state) { checkState(exists(), "This builder does not exist: " + this.name); head().getMutableNodeState().setChildNode(name, checkNotNull(state)); MemoryNodeBuilder builder = createChildBuilder(name); updated(); return builder; }
private static String getSourcePathAnnotation(MemoryNodeBuilder builder) { PropertyState base = builder.getBaseState().getProperty(MoveDetector.SOURCE_PATH); PropertyState head = builder.getNodeState().getProperty(MoveDetector.SOURCE_PATH); if (Objects.equal(base, head)) { // Both null: no source path annotation // Both non null but equals: source path annotation is from a previous commit return null; } else { return head.getValue(Type.STRING); } }
@Nullable SegmentNodeState diff(@NotNull NodeState before, @NotNull NodeState after) throws IOException { boolean success = after.compareAgainstBaseState(before, this); if (exception != null) { throw new IOException(exception); } else if (success) { NodeState nodeState = builder.getNodeState(); checkState(modCount == 0 || !(nodeState instanceof SegmentNodeState)); RecordId nodeId = writer.writeNode(nodeState, getStableIdBytes(after)); reporter.reportNode(this::getPath); return new SegmentNodeState(reader, writer, blobStore, nodeId); } else { return null; } }
@Override public boolean childNodeDeleted(String name, NodeState before) { try { updated(); builder.getChildNode(name).remove(); return true; } catch (IOException e) { exception = e; return false; } }
/** * This implementation is equal resetting the builder to the root of the store and returning * the resulting node state from the builder. * @param builder the builder to reset * @return the node state resulting from the reset. * @throws IllegalArgumentException if the builder is not acquired from a root state of * this store */ @Override public NodeState reset(@NotNull NodeBuilder builder) { checkArgument(builder instanceof MemoryNodeBuilder); NodeState head = getRoot(); ((MemoryNodeBuilder) builder).reset(head); return head; }
@Override public boolean isNew(String name) { return hasProperty(name) && !getBaseState().hasProperty(name); }
/** * This implementation is equal to first rebasing the builder and then applying it to a * new branch and immediately merging it back. * @param builder the builder whose changes to apply * @param commitHook the commit hook to apply while merging changes * @return the node state resulting from the merge. * @throws CommitFailedException * @throws IllegalArgumentException if the builder is not acquired from a root state of * this store */ @Override public synchronized NodeState merge( @Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook, @Nonnull CommitInfo info) throws CommitFailedException { checkArgument(builder instanceof MemoryNodeBuilder); MemoryNodeBuilder mnb = (MemoryNodeBuilder) builder; checkArgument(mnb.isRoot()); checkNotNull(commitHook); rebase(builder); NodeStoreBranch branch = new MemoryNodeStoreBranch(this, getRoot()); branch.setRoot(builder.getNodeState()); NodeState merged = branch.merge(commitHook, info); mnb.reset(merged); return merged; }
private boolean isTransientlyAdded(String path) { NodeState node = rootBuilder.getBaseState(); for (String name : PathUtils.elements(path)) { node = node.getChildNode(name); } return !node.exists(); }