CtClass[] paramTypes = method.getParameterTypes();
if (paramTypes != null) {
for (int i = 0; i < paramTypes.length; i++) {
- if (i > 0)
+ if (i > 0) {
builder.append(", ");
+ }
builder.append(paramTypes[i].getName()).append(" $")
.append(i + 1);
}
int value;
- static java.util.Map<java.lang.Integer, «enums.name»> valueMap;
+ private static final java.util.Map<java.lang.Integer, «enums.name»> VALUE_MAP;
static {
- valueMap = new java.util.HashMap<>();
+ final com.google.common.collect.ImmutableMap.Builder<java.lang.Integer, «enums.name»> b = com.google.common.collect.ImmutableMap.builder();
for («enums.name» enumItem : «enums.name».values())
{
- valueMap.put(enumItem.value, enumItem);
+ b.put(enumItem.value, enumItem);
}
+
+ VALUE_MAP = b.build();
}
private «enums.name»(int value) {
* @return corresponding «enums.name» item
*/
public static «enums.name» forValue(int valueArg) {
- return valueMap.get(valueArg);
+ return VALUE_MAP.get(valueArg);
}
}
'''
<artifactId>plexus-slf4j-logging</artifactId>
</dependency>
- <dependency>
- <groupId>org.sonatype.sisu</groupId>
- <artifactId>sisu-guava</artifactId>
- <version>0.11.1</version>
- <scope>runtime</scope>
- </dependency>
-
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
public abstract class AbstractRegistration implements AutoCloseable {
private static final AtomicIntegerFieldUpdater<AbstractRegistration> CLOSED_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(AbstractRegistration.class, "closed");
-
- @SuppressWarnings("unused") // updated by CLOSED_UPDATER
private volatile int closed = 0;
/**
* @return true if the registration was closed, false otherwise.
*/
protected final boolean isClosed() {
- return CLOSED_UPDATER.get(this) != 0;
+ return closed != 0;
}
@Override
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
- <version>3.0.5</version>
+ <version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
- <version>3.0.5</version>
+ <version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
</pluginManagement>
<plugins>
- <!--
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
- <version>1.0</version>
+ <!--
<executions>
<execution>
- <id>enforce</id>
+ <id>enforce-dependencies</id>
<configuration>
<rules>
<DependencyConvergence />
</goals>
</execution>
</executions>
+ -->
</plugin>
- -->
+
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
DataTreeState withRoot(final TreeNode newRoot) {
return new DataTreeState(newRoot, holder, schemaContext);
}
+
+ @Override
+ public String toString() {
+ final TreeNode r = root;
+ return Objects.toStringHelper(this).add("data", StoreUtils.toStringTree(r.getData())).toString();
+ }
}
\ No newline at end of file
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.util.Collections;
LOG.trace("Updated state from {} to {}", currentState, newState);
} while (!STATE_UPDATER.compareAndSet(this, currentState, newState));
}
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).add("object", super.toString()).add("state", state).toString();
+ }
}
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
}
@Override
- public void write(final YangInstanceIdentifier path, final NormalizedNode<?, ?> value) {
+ public void write(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
checkSealed();
- resolveModificationFor(path).write(value);
+ resolveModificationFor(path).write(data);
}
@Override
public void merge(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
checkSealed();
- mergeImpl(resolveModificationFor(path),data);
- }
-
- private void mergeImpl(final OperationWithModification op,final NormalizedNode<?,?> data) {
- if (data instanceof NormalizedNodeContainer<?,?,?>) {
- @SuppressWarnings({ "rawtypes", "unchecked" })
- NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
- for(NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
- PathArgument childId = child.getIdentifier();
- mergeImpl(op.forChild(childId), child);
- }
- }
- op.merge(data);
+ resolveModificationFor(path).merge(data);
}
@Override
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
import javax.annotation.Nonnull;
+import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
-import javax.annotation.concurrent.GuardedBy;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
/**
* Node Modification Node and Tree
*
* This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
* and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
*/
+@NotThreadSafe
final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<PathArgument>, NodeModification {
public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
private Optional<TreeNode> snapshotCache;
private NormalizedNode<?, ?> value;
- private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original, boolean isOrdered) {
+ private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original, final boolean isOrdered) {
this.identifier = identifier;
this.original = original;
* @return {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ModifiedNode} for specified child, with {@link #getOriginal()}
* containing child metadata if child was present in original data.
*/
- public ModifiedNode modifyChild(final PathArgument child, boolean isOrdered) {
+ public ModifiedNode modifyChild(final PathArgument child, final boolean isOrdered) {
clearSnapshot();
if (modificationType == ModificationType.UNMODIFIED) {
updateModificationType(ModificationType.SUBTREE_MODIFIED);
*
*/
public void delete() {
+ final ModificationType newType;
+
+ switch (modificationType) {
+ case DELETE:
+ case UNMODIFIED:
+ // We need to record this delete.
+ newType = ModificationType.DELETE;
+ break;
+ case MERGE:
+ case SUBTREE_MODIFIED:
+ case WRITE:
+ /*
+ * We are canceling a previous modification. This is a bit tricky,
+ * as the original write may have just introduced the data, or it
+ * may have modified it.
+ *
+ * As documented in BUG-2470, a delete of data introduced in this
+ * transaction needs to be turned into a no-op.
+ */
+ newType = original.isPresent() ? ModificationType.DELETE : ModificationType.UNMODIFIED;
+ break;
+ default:
+ throw new IllegalStateException("Unhandled deletion of node with " + modificationType);
+ }
+
clearSnapshot();
- updateModificationType(ModificationType.DELETE);
children.clear();
this.value = null;
+ updateModificationType(newType);
}
/**
this.value = data;
}
+ /**
+ * Seal the modification node and prune any children which has not been
+ * modified.
+ */
void seal() {
clearSnapshot();
- for (ModifiedNode child : children.values()) {
+
+ // Walk all child nodes and remove any children which have not
+ // been modified.
+ final Iterator<ModifiedNode> it = children.values().iterator();
+ while (it.hasNext()) {
+ final ModifiedNode child = it.next();
child.seal();
+
+ if (child.modificationType == ModificationType.UNMODIFIED) {
+ it.remove();
+ }
+ }
+
+ // A SUBTREE_MODIFIED node without any children is a no-op
+ if (modificationType == ModificationType.SUBTREE_MODIFIED && children.isEmpty()) {
+ updateModificationType(ModificationType.UNMODIFIED);
}
}
return Optional.fromNullable(snapshotCache);
}
- @GuardedBy("this")
private void updateModificationType(final ModificationType type) {
modificationType = type;
clearSnapshot();
+ modificationType + ", childModification=" + children + "]";
}
- public static ModifiedNode createUnmodified(final TreeNode metadataTree, boolean isOrdered) {
+ public static ModifiedNode createUnmodified(final TreeNode metadataTree, final boolean isOrdered) {
return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), isOrdered);
}
}
final MutableTreeNode newMeta = currentMeta.mutable();
newMeta.setSubtreeVersion(version);
+ /*
+ * The user has issued an empty merge operation. In this case we do not perform
+ * a data tree mutation, do not pass GO, and do not collect useless garbage.
+ */
+ final Iterable<ModifiedNode> children = modification.getChildren();
+ if (Iterables.isEmpty(children)) {
+ newMeta.setData(currentMeta.getData());
+ return newMeta.seal();
+ }
+
@SuppressWarnings("rawtypes")
NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
- return mutateChildren(newMeta, dataBuilder, version, modification.getChildren());
+ return mutateChildren(newMeta, dataBuilder, version, children);
}
@Override
import com.google.common.base.Optional;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
this.applyOperation = op;
}
- public OperationWithModification write(final NormalizedNode<?, ?> value) {
+ void write(final NormalizedNode<?, ?> value) {
modification.write(value);
applyOperation.verifyStructure(modification);
- return this;
}
- public OperationWithModification delete() {
+ private void mergeImpl(final NormalizedNode<?,?> data) {
+ if (data instanceof NormalizedNodeContainer<?,?,?>) {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
+ for (NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
+ PathArgument childId = child.getIdentifier();
+ forChild(childId).mergeImpl(child);
+ }
+ }
+
+ modification.merge(data);
+ }
+
+ void merge(final NormalizedNode<?, ?> data) {
+ mergeImpl(data);
+ applyOperation.verifyStructure(modification);
+ }
+
+ void delete() {
modification.delete();
- return this;
}
public ModifiedNode getModification() {
public static OperationWithModification from(final ModificationApplyOperation operation,
final ModifiedNode modification) {
return new OperationWithModification(operation, modification);
-
- }
-
- public void merge(final NormalizedNode<?, ?> data) {
- modification.merge(data);
- applyOperation.verifyStructure(modification);
-
}
- public OperationWithModification forChild(final PathArgument childId) {
+ private OperationWithModification forChild(final PathArgument childId) {
ModificationApplyOperation childOp = applyOperation.getChild(childId).get();
- boolean isOrdered = true;
+
+ final boolean isOrdered;
if (childOp instanceof SchemaAwareApplyOperation) {
isOrdered = ((SchemaAwareApplyOperation) childOp).isOrdered();
+ } else {
+ isOrdered = true;
}
+
ModifiedNode childMod = modification.modifyChild(childId, isOrdered);
return from(childOp,childMod);
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
+import java.util.List;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.List;
-
abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class);
return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
version)));
case MERGE:
- if(currentMeta.isPresent()) {
- return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(), version)));
+ final TreeNode result;
+
+ // This is a slight optimization: a merge on a non-existing node equals to a write
+ if (currentMeta.isPresent()) {
+ result = applyMerge(modification,currentMeta.get(), version);
+ } else {
+ result = applyWrite(modification, currentMeta, version);
}
- // intentional fall-through: if the node does not exist a merge is same as a write
+
+ return modification.storeSnapshot(Optional.of(result));
case WRITE:
return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, version)));
case UNMODIFIED:
}
private ModifyAction getOperation(NormalizedNode<?, ?> modificationNode) {
- if (!(modificationNode instanceof AttributesContainer))
+ if (!(modificationNode instanceof AttributesContainer)) {
return null;
+ }
String operationString = ((AttributesContainer) modificationNode).getAttributes().get(OPERATION_NAME);
Iterable<QName> nextPath = nextLevel(path);
foundNode = module.getDataChildByName(current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
if (foundNode == null) {
foundNode = getGroupingByName(module, current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
if (foundNode == null) {
foundNode = getRpcByName(module, current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
if (foundNode == null) {
foundNode = getNotificationByName(module, current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
- if (foundNode == null)
+ if (foundNode == null) {
LOG.debug("No node matching {} found in node {}", path, module);
+ }
return foundNode;
DataNodeContainer parentDataNodeContainer = (DataNodeContainer) parent;
foundNode = parentDataNodeContainer.getDataChildByName(current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
if (foundNode == null) {
foundNode = getGroupingByName(parentDataNodeContainer, current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
}
if (current.getLocalName().equals("input")) {
foundNode = parentRpcDefinition.getInput();
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
if (current.getLocalName().equals("output")) {
foundNode = parentRpcDefinition.getOutput();
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
if (foundNode == null) {
foundNode = getGroupingByName(parentRpcDefinition, current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
}
if (foundNode == null && parent instanceof ChoiceNode) {
foundNode = ((ChoiceNode) parent).getCaseNodeByName(current);
- if (foundNode != null && nextPath.iterator().hasNext())
+ if (foundNode != null && nextPath.iterator().hasNext()) {
foundNode = findNodeIn(foundNode, nextPath);
+ }
}
- if (foundNode == null)
+ if (foundNode == null) {
LOG.debug("No node matching {} found in node {}", path, parent);
+ }
return foundNode;
// AUGMENTATIONS
final Set<AugmentationSchema> augments = new HashSet<>();
for (AugmentationSchemaBuilder builder : augmentationBuilders) {
- if (!builder.isUnsupportedTarget())
+ if (!builder.isUnsupportedTarget()) {
augments.add(builder.build());
+ }
}
instance.augmentations = ImmutableSet.copyOf(augments);