From 9c1b0747a9441c7fb0c5d601d98b3a4ecd859c12 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 25 Aug 2015 10:18:13 +0200 Subject: [PATCH] BUG-4158: Introduce Modifiable/UnmodifiableMapPhase Our code frequently uses an access pattern, where we create a modifiable map, then turn it into an unmodifiable one and then we want to create a modifiable map containing all the mappings in the unmodifiable one (and then turn it again into unodifiable). This patch introduces interfaces which mark the modifiable/unmodifiable phases of such mapping. They also define the interface contract implementation must follow to be usable with this usabe pattern. Change-Id: I08b3077739a3df89e57c54a6937744f2394701bc Signed-off-by: Robert Varga --- .../yangtools/util/ModifiableMapPhase.java | 34 +++++++++++++++++++ .../yangtools/util/UnmodifiableMapPhase.java | 29 ++++++++++++++++ ...ractImmutableDataContainerNodeBuilder.java | 10 +++++- 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 common/util/src/main/java/org/opendaylight/yangtools/util/ModifiableMapPhase.java create mode 100644 common/util/src/main/java/org/opendaylight/yangtools/util/UnmodifiableMapPhase.java diff --git a/common/util/src/main/java/org/opendaylight/yangtools/util/ModifiableMapPhase.java b/common/util/src/main/java/org/opendaylight/yangtools/util/ModifiableMapPhase.java new file mode 100644 index 0000000000..fb9079671b --- /dev/null +++ b/common/util/src/main/java/org/opendaylight/yangtools/util/ModifiableMapPhase.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.util; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import javax.annotation.Nonnull; + +/** + * A {@link Map} which can be modified and supports efficient conversion to an unmodifiable map. This interface is the + * logical counterpart to {@link UnmodifiableMapPhase}, but it does not require implementations of {@link #toUnmodifiableMap()} + * to return an implementation of that interface. The reason for that empty and singleton mappings are efficiently + * represented as {@link ImmutableMap}, which does not implement {@link UnmodifiableMapPhase}. + * + * @param the type of keys maintained by this map + * @param the type of mapped values + */ +@Beta +public interface ModifiableMapPhase extends Map { + /** + * Return an isolated unmodifiable version of this map. Returned object must not allow removal, addition or changing + * of mappings. Its mappings must match the mappings currently present in this map, but must not be affected by any + * subsequent changes to this map. + * + * @return An unmodifiable version of this map. + */ + @Nonnull Map toUnmodifiableMap(); +} diff --git a/common/util/src/main/java/org/opendaylight/yangtools/util/UnmodifiableMapPhase.java b/common/util/src/main/java/org/opendaylight/yangtools/util/UnmodifiableMapPhase.java new file mode 100644 index 0000000000..2d8396d254 --- /dev/null +++ b/common/util/src/main/java/org/opendaylight/yangtools/util/UnmodifiableMapPhase.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.util; + +import com.google.common.annotations.Beta; +import java.util.Map; +import javax.annotation.Nonnull; + +/** + * A {@link Map} which cannot be modified and supports efficient conversion to a {@link ModifiableMapPhase}. + * + * @param the type of keys maintained by this map + * @param the type of mapped values + */ +@Beta +public interface UnmodifiableMapPhase extends Map { + /** + * Return an isolated modifiable version of this map. Its mappings must match the mappings present in this map. Any + * modification of the returned map must not be affect the contents of this map. + * + * @return An modifiable version of this map. + */ + @Nonnull ModifiableMapPhase toModifiableMap(); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java index 615aea0fcb..a83b908b91 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java @@ -11,6 +11,8 @@ import com.google.common.collect.Maps; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import org.opendaylight.yangtools.util.ModifiableMapPhase; +import org.opendaylight.yangtools.util.UnmodifiableMapPhase; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; @@ -69,13 +71,19 @@ abstract class AbstractImmutableDataContainerNodeBuilder> buildValue() { + if (value instanceof ModifiableMapPhase) { + return ((ModifiableMapPhase>)value).toUnmodifiableMap(); + } + dirty = true; return value; } private void checkDirty() { if (dirty) { - if (value instanceof CloneableMap) { + if (value instanceof UnmodifiableMapPhase) { + value = ((UnmodifiableMapPhase>) value).toModifiableMap(); + } else if (value instanceof CloneableMap) { value = ((CloneableMap>) value).createMutableClone(); } else { value = new HashMap<>(value); -- 2.36.6