[ONOS-6017] Implement DefaultMappingKey and DefaultMappingValue

Change-Id: Ie41242436323d9fa89400c2ab661fcc35518b9c8
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMapping.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMapping.java
index 5c98fee..a6836f8 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMapping.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMapping.java
@@ -127,8 +127,8 @@
         private MappingId id;
         private ApplicationId appId;
         private DeviceId deviceId;
-        private MappingKey key = new DefaultMappingKey();
-        private MappingValue value = new DefaultMappingValue();
+        private MappingKey key = DefaultMappingKey.builder().build();
+        private MappingValue value = DefaultMappingValue.builder().build();
 
         @Override
         public Mapping.Builder withId(long id) {
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java
index a7c3f7f..e18435b 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java
@@ -15,14 +15,95 @@
  */
 package org.onosproject.mapping;
 
+import com.google.common.base.MoreObjects;
 import org.onosproject.mapping.addresses.MappingAddress;
 
+import java.util.Objects;
+
 /**
  * Default mapping key implementation.
  */
-public class DefaultMappingKey implements MappingKey {
+public final class DefaultMappingKey implements MappingKey {
+
+    private final MappingAddress address;
+
+    /**
+     * Create a new mapping key from the specified mapping address.
+     *
+     * @param address a mapping address
+     */
+    private DefaultMappingKey(MappingAddress address) {
+        this.address = address;
+    }
+
     @Override
     public MappingAddress address() {
-        return null;
+        return address;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(address);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DefaultMappingKey) {
+            DefaultMappingKey that = (DefaultMappingKey) obj;
+            return Objects.equals(address, that.address);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("address", address)
+                .toString();
+    }
+
+    /**
+     * Returns a new mapping key builder.
+     *
+     * @return mapping key builder
+     */
+    public static MappingKey.Builder builder() {
+        return new Builder();
+    }
+
+    public static MappingKey.Builder builder(MappingKey key) {
+        return new Builder(key);
+    }
+
+    /**
+     * Builds a mapping key.
+     */
+    public static final class Builder implements MappingKey.Builder {
+
+        private MappingAddress address;
+
+        // creates a new builder
+        private Builder() {
+        }
+
+        // creates a new builder based off an existing mapping key
+        private Builder(MappingKey key) {
+            this.address = key.address();
+        }
+
+        @Override
+        public MappingKey.Builder withAddress(MappingAddress address) {
+            this.address = address;
+            return this;
+        }
+
+        @Override
+        public MappingKey build() {
+
+            return new DefaultMappingKey(address);
+        }
     }
 }
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingTreatment.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingTreatment.java
new file mode 100644
index 0000000..4b2ef12
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingTreatment.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.instructions.MappingInstruction;
+import org.onosproject.mapping.instructions.MappingInstructions;
+import org.onosproject.mapping.instructions.MulticastMappingInstruction;
+import org.onosproject.mapping.instructions.MulticastMappingInstruction.MulticastType;
+import org.onosproject.mapping.instructions.UnicastMappingInstruction;
+import org.onosproject.mapping.instructions.UnicastMappingInstruction.UnicastType;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of mapping treatment.
+ */
+public final class DefaultMappingTreatment implements MappingTreatment {
+
+    private final List<MappingInstruction> instructions;
+    private final MappingAddress address;
+
+    /**
+     * Create a new mapping treatment from the specified list of mapping instructions.
+     *
+     * @param instructions mapping instructions
+     */
+    private DefaultMappingTreatment(MappingAddress address,
+                                    List<MappingInstruction> instructions) {
+        this.address = address;
+        this.instructions = ImmutableList.copyOf(checkNotNull(instructions));
+    }
+
+    @Override
+    public MappingAddress address() {
+        return address;
+    }
+
+    @Override
+    public List<MappingInstruction> instructions() {
+        return ImmutableList.copyOf(instructions);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(address, instructions);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DefaultMappingTreatment) {
+            DefaultMappingTreatment that = (DefaultMappingTreatment) obj;
+            return Objects.equals(address, that.address) &&
+                    Objects.equals(instructions, that.instructions);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("address", address)
+                .add("mapping instructions", instructions)
+                .toString();
+    }
+
+    /**
+     * Returns a new mapping treatment builder.
+     *
+     * @return mapping treatment builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Returns a new mapping treatment builder primed to produce entities
+     * patterned after the supplied mapping treatment.
+     *
+     * @param treatment base mapping treatment
+     * @return mapping treatment builder
+     */
+    public static Builder builder(MappingTreatment treatment) {
+        return new Builder(treatment);
+    }
+
+    /**
+     * Builds a mapping treatment.
+     */
+    public static final class Builder implements MappingTreatment.Builder {
+
+        private List<MappingInstruction> instructions = Lists.newArrayList();
+        private MappingAddress address;
+        private Map<UnicastType, Integer> unicastTypeMap = Maps.newConcurrentMap();
+        private Map<MulticastType, Integer> multicastTypeMap = Maps.newConcurrentMap();
+
+        // creates a new builder
+        private Builder() {
+            initTypeMap();
+        }
+
+        // creates a new builder based off an existing mapping treatment
+        private Builder(MappingTreatment treatment) {
+            treatment.instructions().forEach(i -> instructions.add(i));
+            address = treatment.address();
+            initTypeMap();
+        }
+
+        /**
+         * Initializes type map.
+         */
+        private void initTypeMap() {
+            unicastTypeMap.put(UnicastType.WEIGHT, 0);
+            unicastTypeMap.put(UnicastType.PRIORITY, 0);
+            multicastTypeMap.put(MulticastType.WEIGHT, 0);
+            multicastTypeMap.put(MulticastType.PRIORITY, 0);
+        }
+
+        @Override
+        public Builder withAddress(MappingAddress address) {
+            this.address = address;
+            return this;
+        }
+
+        @Override
+        public Builder add(MappingInstruction instruction) {
+
+            switch (instruction.type()) {
+                case UNICAST:
+                    unicastTypeMap.compute(((UnicastMappingInstruction)
+                            instruction).subtype(), (k, v) -> v + 1);
+                    instructions.add(instruction);
+                    break;
+                case MULTICAST:
+                    multicastTypeMap.compute(((MulticastMappingInstruction)
+                            instruction).subtype(), (k, v) -> v + 1);
+                    instructions.add(instruction);
+                    break;
+                case EXTENSION:
+                    instructions.add(instruction);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown mapping " +
+                            "instruction type: " + instruction.type());
+            }
+
+            return this;
+        }
+
+        @Override
+        public Builder setUnicastWeight(int weight) {
+            return add(MappingInstructions.unicastWeight(weight));
+        }
+
+        @Override
+        public Builder setUnicastPriority(int priority) {
+            return add(MappingInstructions.unicastPriority(priority));
+        }
+
+        @Override
+        public Builder setMulticastWeight(int weight) {
+            return add(MappingInstructions.multicastWeight(weight));
+        }
+
+        @Override
+        public Builder setMulticastPriority(int priority) {
+            return add(MappingInstructions.multicastPriority(priority));
+        }
+
+        @Override
+        public Builder extension(ExtensionTreatment extension, DeviceId deviceId) {
+            return add(MappingInstructions.extension(extension, deviceId));
+        }
+
+        @Override
+        public MappingTreatment build() {
+
+            unicastTypeMap.forEach((k, v) -> checkArgument(v <= 1,
+                    "Should not specify more than one " + k.toString()));
+            multicastTypeMap.forEach((k, v) -> checkArgument(v <= 1,
+                    "Should not specify more than one " + k.toString()));
+
+            return new DefaultMappingTreatment(address, instructions);
+        }
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java
index d38b782..28f7119 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java
@@ -15,23 +15,137 @@
  */
 package org.onosproject.mapping;
 
-import org.onosproject.mapping.addresses.MappingAddress;
-import org.onosproject.mapping.instructions.MappingInstruction;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.onosproject.mapping.actions.MappingAction;
+import org.onosproject.mapping.actions.MappingActions;
 
 import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Default mapping value implementation.
  */
-public class DefaultMappingValue implements MappingValue {
+public final class DefaultMappingValue implements MappingValue {
 
-    @Override
-    public MappingAddress address() {
-        return null;
+    private final MappingAction action;
+    private final List<MappingTreatment> treatments;
+
+    /**
+     * Creates a new mapping value from the specified mapping action and a
+     * list of mapping treatments.
+     *
+     * @param action     mapping action
+     * @param treatments a collection of mapping treatment
+     */
+    private DefaultMappingValue(MappingAction action,
+                                List<MappingTreatment> treatments) {
+        this.action = action;
+        this.treatments = ImmutableList.copyOf(checkNotNull(treatments));
     }
 
     @Override
-    public List<MappingInstruction> instructions() {
-        return null;
+    public MappingAction action() {
+        return action;
+    }
+
+    @Override
+    public List<MappingTreatment> treatments() {
+        return ImmutableList.copyOf(treatments);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(action, treatments);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DefaultMappingValue) {
+            DefaultMappingValue that = (DefaultMappingValue) obj;
+            return Objects.equals(action, that.action) &&
+                    Objects.equals(treatments, that.treatments);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("action", action)
+                .add("treatments", treatments)
+                .toString();
+    }
+
+    /**
+     * Returns a new mapping value builder.
+     *
+     * @return mapping value builder
+     */
+    public static MappingValue.Builder builder() {
+        return new DefaultMappingValue.Builder();
+    }
+
+    /**
+     * Returns a new mapping value builder primed to produce entities
+     * patterned after the supplied mapping value.
+     *
+     * @param value base mapping value
+     * @return mapping value builder
+     */
+    public static MappingValue.Builder builder(MappingValue value) {
+        return new Builder(value);
+    }
+
+    /**
+     * Builds a mapping value.
+     */
+    public static final class Builder implements MappingValue.Builder {
+
+        private MappingAction action;
+        private List<MappingTreatment> treatments = Lists.newArrayList();
+
+        // creates a new builder
+        private Builder() {
+        }
+
+        // creates a new builder based off an existing mapping value
+        private Builder(MappingValue value) {
+            value.treatments().forEach(t -> treatments.add(t));
+            action = value.action();
+        }
+
+        @Override
+        public Builder withAction(MappingAction action) {
+            this.action = action;
+            return this;
+        }
+
+        @Override
+        public Builder add(MappingTreatment treatment) {
+            treatments.add(treatment);
+            return this;
+        }
+
+        @Override
+        public MappingValue build() {
+
+            // if no action has been specified, we simply assign noAction
+            if (action == null) {
+                action = MappingActions.noAction();
+            }
+
+            // FIXME: we will check the number of treatment later
+            // checkArgument(treatments.size() >= 1,
+            //        "Must specify more than one mapping treatment");
+
+            return new DefaultMappingValue(action, treatments);
+        }
     }
 }
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingTreatment.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingTreatment.java
new file mode 100644
index 0000000..9116267
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingTreatment.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping;
+
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.instructions.MappingInstruction;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+
+import java.util.List;
+
+/**
+ * Abstraction of mapping treatment.
+ */
+public interface MappingTreatment {
+
+    /**
+     * Obtains a mapping address.
+     *
+     * @return a mapping address
+     */
+    MappingAddress address();
+
+    /**
+     * Obtains a collection of mapping instructions.
+     *
+     * @return a collection of mapping instructions
+     */
+    List<MappingInstruction> instructions();
+
+    interface Builder {
+
+        /**
+         * Specifies a mapping address.
+         *
+         * @param address mapping address
+         * @return a mapping treatment builder
+         */
+        Builder withAddress(MappingAddress address);
+
+        /**
+         * Specifies a collection of mapping instructions.
+         *
+         * @param instruction a mapping instruction
+         * @return a mapping treatment builder
+         */
+        Builder add(MappingInstruction instruction);
+
+        /**
+         * Adds an unicast weight instruction.
+         *
+         * @param weight unicast weight value
+         * @return a mapping treatment builder
+         */
+        Builder setUnicastWeight(int weight);
+
+        /**
+         * Adds an unicast priority instruction.
+         *
+         * @param priority unicast priority value
+         * @return a mapping treatment builder
+         */
+        Builder setUnicastPriority(int priority);
+
+        /**
+         * Adds a multicast weight instruction.
+         *
+         * @param weight multicast weight value
+         * @return a mapping treatment builder
+         */
+        Builder setMulticastWeight(int weight);
+
+        /**
+         * Adds a multicast priority instruction.
+         *
+         * @param priority multicast priority value
+         * @return a mapping treatment builder
+         */
+        Builder setMulticastPriority(int priority);
+
+        /**
+         * uses an extension treatment.
+         *
+         * @param extension extension treatment
+         * @param deviceId  device identifier
+         * @return a treatment builder
+         */
+        Builder extension(ExtensionTreatment extension, DeviceId deviceId);
+
+        /**
+         * Builds an immutable mapping treatment.
+         *
+         * @return a mapping treatment
+         */
+        MappingTreatment build();
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java
index 07f4594..69741d8 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java
@@ -15,8 +15,7 @@
  */
 package org.onosproject.mapping;
 
-import org.onosproject.mapping.addresses.MappingAddress;
-import org.onosproject.mapping.instructions.MappingInstruction;
+import org.onosproject.mapping.actions.MappingAction;
 
 import java.util.List;
 
@@ -26,36 +25,36 @@
 public interface MappingValue {
 
     /**
-     * Obtains a mapping address.
+     * Obtains a mapping action.
      *
-     * @return a mapping address
+     * @return a mapping action
      */
-    MappingAddress address();
+    MappingAction action();
 
     /**
      * Obtains a collection of mapping instructions.
      *
      * @return a collection of mapping instructions
      */
-    List<MappingInstruction> instructions();
+    List<MappingTreatment> treatments();
 
     interface Builder {
 
         /**
-         * Specifies the mapping address.
+         * Specifies a mapping action.
          *
-         * @param address mapping address
+         * @param action mapping action
          * @return a mapping value builder
          */
-        Builder withAddress(MappingAddress address);
+        Builder withAction(MappingAction action);
 
         /**
-         * Specifies a collection of mapping instructions.
+         * Specifies a collection of mapping treatment.
          *
-         * @param instructions a collection of mapping instructions
+         * @param treatment a mapping treatment
          * @return a mapping value builder
          */
-        Builder withInstructions(List<MappingInstruction> instructions);
+        Builder add(MappingTreatment treatment);
 
         /**
          * Builds an immutable mapping value.
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/DropMappingAction.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/DropMappingAction.java
new file mode 100644
index 0000000..c38b57a
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/DropMappingAction.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping.actions;
+
+import java.util.Objects;
+
+/**
+ * Represents a Drop Action mapping.
+ */
+public final class DropMappingAction implements MappingAction {
+
+    /**
+     * Default constructor of DropMappingAction.
+     */
+    DropMappingAction() {
+    }
+
+    @Override
+    public Type type() {
+        return Type.DROP;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DropMappingAction) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/ForwardMappingAction.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/ForwardMappingAction.java
new file mode 100644
index 0000000..93a7150
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/ForwardMappingAction.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping.actions;
+
+import java.util.Objects;
+
+/**
+ * Represents a Forward Action mapping.
+ */
+public final class ForwardMappingAction implements MappingAction {
+
+    /**
+     * Default constructor of ForwardMappingAction.
+     */
+    ForwardMappingAction() {
+    }
+
+    @Override
+    public Type type() {
+        return Type.FORWARD;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ForwardMappingAction) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/MappingAction.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/MappingAction.java
new file mode 100644
index 0000000..16047f6
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/MappingAction.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping.actions;
+
+/**
+ * Presentation of a single mapping action.
+ */
+public interface MappingAction {
+
+    /**
+     * Represents the type of mapping action.
+     */
+    enum Type {
+
+        /**
+         * Signifies that the traffic requires no action.
+         */
+        NO_ACTION,
+
+        /**
+         * Signifies that the traffic requires native forwarding.
+         */
+        NATIVE_FORWARD,
+
+        /**
+         * Signifies that the traffic requires forwarding with mapping information.
+         */
+        FORWARD,
+
+        /**
+         * Signifies that the traffic should be dropped.
+         */
+        DROP
+    }
+
+    /**
+     * Returns the type of mapping action.
+     *
+     * @return type of mapping action
+     */
+    Type type();
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/MappingActions.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/MappingActions.java
new file mode 100644
index 0000000..676d65b
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/MappingActions.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping.actions;
+
+/**
+ * Factory class for creating various mapping actions.
+ */
+public final class MappingActions {
+
+    /**
+     * Prevents instantiation from external.
+     */
+    private MappingActions() {}
+
+    /**
+     * Creates a drop mapping action.
+     *
+     * @return a drop mapping action
+     */
+    public static DropMappingAction drop() {
+        return new DropMappingAction();
+    }
+
+    /**
+     * Creates a forward mapping action.
+     *
+     * @return a forward mapping action
+     */
+    public static ForwardMappingAction forward() {
+        return new ForwardMappingAction();
+    }
+
+    /**
+     * Creates a native forward mapping action.
+     *
+     * @return a native forward mapping action
+     */
+    public static NativeForwardMappingAction nativeForward() {
+        return new NativeForwardMappingAction();
+    }
+
+    /**
+     * Creates a no action.
+     *
+     * @return a no action
+     */
+    public static NoMappingAction noAction() {
+        return new NoMappingAction();
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/NativeForwardMappingAction.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/NativeForwardMappingAction.java
new file mode 100644
index 0000000..a2a9a21
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/NativeForwardMappingAction.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping.actions;
+
+import java.util.Objects;
+
+/**
+ * Represents a Native Forward Action mapping.
+ */
+public final class NativeForwardMappingAction implements MappingAction {
+
+    /**
+     * Default constructor of NativeForwardMappingAction.
+     */
+    NativeForwardMappingAction() {
+    }
+
+    @Override
+    public Type type() {
+        return Type.NATIVE_FORWARD;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NativeForwardMappingAction) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/NoMappingAction.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/NoMappingAction.java
new file mode 100644
index 0000000..b4eb75c
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/NoMappingAction.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping.actions;
+
+import java.util.Objects;
+
+/**
+ * Represents a No Action mapping.
+ */
+public final class NoMappingAction implements MappingAction {
+
+    /**
+     * Default constructor of NoMappingAction.
+     */
+    NoMappingAction() {
+    }
+
+    @Override
+    public Type type() {
+        return Type.NO_ACTION;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NoMappingAction) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/package-info.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/package-info.java
new file mode 100644
index 0000000..0c5bec5
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/actions/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Mapping action package.
+ */
+package org.onosproject.mapping.actions;
\ No newline at end of file
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/ActionMappingInstruction.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/ActionMappingInstruction.java
deleted file mode 100644
index 9a17f9d..0000000
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/ActionMappingInstruction.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.mapping.instructions;
-
-import java.util.Objects;
-
-/**
- * Abstraction of an action mapping instruction.
- */
-public abstract class ActionMappingInstruction implements MappingInstruction {
-
-    /**
-     * Represents the type of mapping action.
-     */
-    public enum ActionType {
-
-        /**
-         * Signifies that the traffic requires no action.
-         */
-        NO_ACTION,
-
-        /**
-         * Signifies that the traffic requires native forwarding.
-         */
-        NATIVE_FORWARD,
-
-        /**
-         * Signifies that the traffic requires forwarding with mapping information.
-         */
-        FORWARD,
-
-        /**
-         * Signifies that the traffic should be dropped.
-         */
-        DROP
-    }
-
-    public abstract ActionType subtype();
-
-    @Override
-    public final Type type() {
-        return Type.ACTION;
-    }
-
-    /**
-     * Represents a No Action mapping instruction.
-     */
-    public static final class NoActionMappingInstruction
-                                            extends ActionMappingInstruction {
-
-        NoActionMappingInstruction() {
-        }
-
-        @Override
-        public ActionType subtype() {
-            return ActionType.NO_ACTION;
-        }
-
-        @Override
-        public String toString() {
-            return subtype().toString();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(type(), subtype());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof NoActionMappingInstruction) {
-                return true;
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Represents a Native Forward mapping instruction.
-     */
-    public static final class NativeForwardMappingInstruction
-                                            extends ActionMappingInstruction {
-
-        NativeForwardMappingInstruction() {
-        }
-
-        @Override
-        public ActionType subtype() {
-            return ActionType.NATIVE_FORWARD;
-        }
-
-        @Override
-        public String toString() {
-            return subtype().toString();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(type(), subtype());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof NativeForwardMappingInstruction) {
-                return true;
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Represents a Forward mapping instruction.
-     */
-    public static final class ForwardMappingInstruction
-                                            extends ActionMappingInstruction {
-
-        ForwardMappingInstruction() {
-        }
-
-        @Override
-        public ActionType subtype() {
-            return ActionType.FORWARD;
-        }
-
-        @Override
-        public String toString() {
-            return subtype().toString();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(type(), subtype());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof ForwardMappingInstruction) {
-                return true;
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Represents a Drop mapping instruction.
-     */
-    public static final class DropMappingInstruction
-                                            extends ActionMappingInstruction {
-
-        DropMappingInstruction() {
-        }
-
-        @Override
-        public ActionType subtype() {
-            return ActionType.DROP;
-        }
-
-        @Override
-        public String toString() {
-            return subtype().toString();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(type(), subtype());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof DropMappingInstruction) {
-                return true;
-            }
-            return false;
-        }
-    }
-}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstruction.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstruction.java
index 81faf05..fc3e340 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstruction.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstruction.java
@@ -36,20 +36,15 @@
         MULTICAST,
 
         /**
-         * Signifies that the traffic should be treated with a certain action.
-         */
-        ACTION,
-
-        /**
          * Signifies that an extension instruction will be used.
          */
         EXTENSION
     }
 
     /**
-     * Returns the type of instruction.
+     * Returns the type of mapping instruction.
      *
-     * @return type of instruction
+     * @return type of mapping instruction
      */
     Type type();
 }
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstructions.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstructions.java
index 0360b44..63e65af 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstructions.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/instructions/MappingInstructions.java
@@ -81,42 +81,6 @@
     }
 
     /**
-     * Creates no action mapping instruction.
-     *
-     * @return an action mapping instruction
-     */
-    public static ActionMappingInstruction noAction() {
-        return new ActionMappingInstruction.NoActionMappingInstruction();
-    }
-
-    /**
-     * Creates native forward mapping instruction.
-     *
-     * @return an action mapping instruction
-     */
-    public static ActionMappingInstruction nativeForwardAction() {
-        return new ActionMappingInstruction.NativeForwardMappingInstruction();
-    }
-
-    /**
-     * Creates forward mapping instruction.
-     *
-     * @return an action mapping instruction
-     */
-    public static ActionMappingInstruction forwardAction() {
-        return new ActionMappingInstruction.ForwardMappingInstruction();
-    }
-
-    /**
-     * Creates drop mapping instruction.
-     *
-     * @return an action mapping instruction
-     */
-    public static ActionMappingInstruction dropAction() {
-        return new ActionMappingInstruction.DropMappingInstruction();
-    }
-
-    /**
      * Creates an extension mapping instruction.
      *
      * @param extension extension mapping instruction
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingEntryTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingEntryTest.java
index d9b1ff8..47aadbe 100644
--- a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingEntryTest.java
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingEntryTest.java
@@ -27,8 +27,10 @@
  */
 public class DefaultMappingEntryTest {
 
-    private static final MappingKey MAPPING_KEY = new DefaultMappingKey();
-    private static final MappingValue MAPPING_VALUE = new DefaultMappingValue();
+    private static final MappingKey MAPPING_KEY =
+                         new MappingTestMocks.MockMappingKey();
+    private static final MappingValue MAPPING_VALUE =
+                         new MappingTestMocks.MockMappingValue();
 
     /**
      * Creates a new mapping entry from an unique value.
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingKeyTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingKeyTest.java
new file mode 100644
index 0000000..35d464b
--- /dev/null
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingKeyTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddresses;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for the default mapping key class.
+ */
+public class DefaultMappingKeyTest {
+
+    private static final String IP_ADDRESS_1 = "1.2.3.4/24";
+    private static final String IP_ADDRESS_2 = "5.6.7.8/24";
+
+    /**
+     * Checks that the DefaultMappingKey class is immutable.
+     */
+    @Test
+    public void testImmutability() {
+        assertThatClassIsImmutable(DefaultMappingKey.class);
+    }
+
+    /**
+     * Tests equals() method.
+     */
+    @Test
+    public void testEquals() {
+        IpPrefix ip1 = IpPrefix.valueOf(IP_ADDRESS_1);
+        MappingAddress address1 = MappingAddresses.ipv4MappingAddress(ip1);
+
+        MappingKey key1 = DefaultMappingKey.builder()
+                                .withAddress(address1)
+                                .build();
+        MappingKey sameAsKey1 = DefaultMappingKey.builder()
+                                .withAddress(address1)
+                                .build();
+
+        IpPrefix ip2 = IpPrefix.valueOf(IP_ADDRESS_2);
+        MappingAddress address2 = MappingAddresses.ipv4MappingAddress(ip2);
+
+        MappingKey key2 = DefaultMappingKey.builder()
+                                .withAddress(address2)
+                                .build();
+
+        new EqualsTester()
+                .addEqualityGroup(key1, sameAsKey1)
+                .addEqualityGroup(key2)
+                .testEquals();
+    }
+}
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingTest.java
index 6a87d8b..d2df07b 100644
--- a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingTest.java
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingTest.java
@@ -38,8 +38,8 @@
 
         Mapping.Builder builder1 = new DefaultMapping.Builder();
         DeviceId deviceId1 = DeviceId.deviceId("lisp:10.1.1.1");
-        MappingKey mappingKey1 = new DefaultMappingKey();
-        MappingValue mappingValue1 = new DefaultMappingValue();
+        MappingKey mappingKey1 = new MappingTestMocks.MockMappingKey();
+        MappingValue mappingValue1 = new MappingTestMocks.MockMappingValue();
 
         mapping1 = builder1
                         .withId(1)
@@ -62,8 +62,8 @@
 
         mapping2 = builder3
                         .withId(2)
-                        .withKey(new DefaultMappingKey())
-                        .withValue(new DefaultMappingValue())
+                        .withKey(new MappingTestMocks.MockMappingKey())
+                        .withValue(new MappingTestMocks.MockMappingValue())
                         .forDevice(deviceId2)
                         .build();
     }
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingTreatmentTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingTreatmentTest.java
new file mode 100644
index 0000000..e3faaa7
--- /dev/null
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingTreatmentTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddresses;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for the default mapping treatment class.
+ */
+public class DefaultMappingTreatmentTest {
+
+    private static final String IP_ADDRESS_1 = "1.2.3.4/24";
+    private static final String IP_ADDRESS_2 = "5.6.7.8/24";
+
+    /**
+     * Checks that the DefaultMappingTreatment class is immutable.
+     */
+    @Test
+    public void testImmutability() {
+        assertThatClassIsImmutable(DefaultMappingTreatment.class);
+    }
+
+    /**
+     * Tests method defined on the Builder.
+     */
+    @Test
+    public void testBuilderMethods() {
+        IpPrefix ip = IpPrefix.valueOf(IP_ADDRESS_1);
+        MappingAddress address = MappingAddresses.ipv4MappingAddress(ip);
+
+        MappingTreatment.Builder builder =
+                DefaultMappingTreatment.builder()
+                        .withAddress(address)
+                        .setUnicastPriority(10)
+                        .setUnicastWeight(10);
+        MappingTreatment treatment = builder.build();
+        assertThat(treatment.instructions(), hasSize(2));
+    }
+
+    /**
+     * Tests illegal unicast type instruction construction.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalUnicastTypeConstruction() {
+        IpPrefix ip = IpPrefix.valueOf(IP_ADDRESS_1);
+        MappingAddress address = MappingAddresses.ipv4MappingAddress(ip);
+
+        DefaultMappingTreatment.builder()
+                .withAddress(address)
+                .setUnicastPriority(10)
+                .setUnicastWeight(10)
+                .setUnicastPriority(20)
+                .build();
+    }
+
+    /**
+     * Tests illegal multicast type instruction construction.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalMulticastTypeConstruction() {
+        IpPrefix ip = IpPrefix.valueOf(IP_ADDRESS_1);
+        MappingAddress address = MappingAddresses.ipv4MappingAddress(ip);
+
+        DefaultMappingTreatment.builder()
+                .withAddress(address)
+                .setMulticastPriority(10)
+                .setMulticastWeight(10)
+                .setMulticastPriority(20)
+                .build();
+    }
+
+    /**
+     * Tests equals() method.
+     */
+    @Test
+    public void testEquals() {
+        IpPrefix ip1 = IpPrefix.valueOf(IP_ADDRESS_1);
+        MappingAddress address1 = MappingAddresses.ipv4MappingAddress(ip1);
+
+        MappingTreatment treatment1 = DefaultMappingTreatment.builder()
+                                    .withAddress(address1)
+                                    .setUnicastPriority(10)
+                                    .setUnicastWeight(10)
+                                    .build();
+
+        MappingTreatment sameAsTreatment1 = DefaultMappingTreatment.builder()
+                                    .withAddress(address1)
+                                    .setUnicastPriority(10)
+                                    .setUnicastWeight(10)
+                                    .build();
+
+        IpPrefix ip2 = IpPrefix.valueOf(IP_ADDRESS_2);
+        MappingAddress address2 = MappingAddresses.ipv4MappingAddress(ip2);
+
+        MappingTreatment treatment2 = DefaultMappingTreatment.builder()
+                                    .withAddress(address2)
+                                    .setMulticastPriority(20)
+                                    .setMulticastWeight(20)
+                                    .build();
+
+        new EqualsTester()
+                .addEqualityGroup(treatment1, sameAsTreatment1)
+                .addEqualityGroup(treatment2)
+                .testEquals();
+    }
+}
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingValueTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingValueTest.java
new file mode 100644
index 0000000..6c857d6
--- /dev/null
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/DefaultMappingValueTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.mapping.actions.MappingAction;
+import org.onosproject.mapping.actions.MappingActions;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddresses;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for the default mapping value class.
+ */
+public class DefaultMappingValueTest {
+
+    private static final String IP_ADDRESS_1 = "1.2.3.4/24";
+    private static final String IP_ADDRESS_2 = "5.6.7.8/24";
+    private final IpPrefix ip1 = IpPrefix.valueOf(IP_ADDRESS_1);
+    private final IpPrefix ip2 = IpPrefix.valueOf(IP_ADDRESS_2);
+    private final MappingAddress ma1 = MappingAddresses.ipv4MappingAddress(ip1);
+    private final MappingAddress ma2 = MappingAddresses.ipv4MappingAddress(ip2);
+
+    /**
+     * Checks that the DefaultMappingValue class is immutable.
+     */
+    @Test
+    public void testImmutability() {
+        assertThatClassIsImmutable(DefaultMappingValue.class);
+    }
+
+    /**
+     * Tests methods defined on the Builder.
+     */
+    @Test
+    public void testBuilderMethods() {
+        MappingAction action = MappingActions.noAction();
+        MappingTreatment treatment = DefaultMappingTreatment.builder()
+                                        .withAddress(ma1)
+                                        .setUnicastPriority(10)
+                                        .setUnicastWeight(10)
+                                        .build();
+
+        MappingValue value = DefaultMappingValue.builder()
+                                        .withAction(action)
+                                        .add(treatment)
+                                        .build();
+
+        assertThat(value.action(), is(action));
+        assertThat(value.treatments(), hasSize(1));
+    }
+
+    /**
+     * Tests equals() method.
+     */
+    @Test
+    public void testEquals() {
+        MappingTreatment treatment1 = DefaultMappingTreatment.builder()
+                                                .withAddress(ma1)
+                                                .setUnicastPriority(10)
+                                                .setUnicastWeight(10)
+                                                .build();
+
+        MappingTreatment treatment2 = DefaultMappingTreatment.builder()
+                                                .withAddress(ma2)
+                                                .setUnicastPriority(20)
+                                                .setUnicastWeight(20)
+                                                .build();
+
+        MappingAction noAction = MappingActions.noAction();
+        MappingAction forward = MappingActions.forward();
+
+        MappingValue value1 = DefaultMappingValue.builder()
+                                        .withAction(noAction)
+                                        .add(treatment1)
+                                        .build();
+
+        MappingValue sameAsValue1 = DefaultMappingValue.builder()
+                                        .withAction(noAction)
+                                        .add(treatment1)
+                                        .build();
+
+        MappingValue value2 = DefaultMappingValue.builder()
+                                        .withAction(forward)
+                                        .add(treatment2)
+                                        .build();
+
+        new EqualsTester()
+                .addEqualityGroup(value1, sameAsValue1)
+                .addEqualityGroup(value2)
+                .testEquals();
+    }
+}
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/MappingEventTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/MappingEventTest.java
index 35a33db..2da8863 100644
--- a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/MappingEventTest.java
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/MappingEventTest.java
@@ -28,6 +28,9 @@
  */
 public class MappingEventTest extends AbstractEventTest {
 
+    private static final String DEVICE_ID_1 = "lisp:10.1.1.1";
+    private static final String DEVICE_ID_2 = "lisp:10.1.1.2";
+
     private MappingEvent event1;
     private MappingEvent sameAsEvent1;
     private MappingEvent event2;
@@ -45,16 +48,16 @@
 
         return builder
                 .withId(mid)
-                .withKey(new DefaultMappingKey())
-                .withValue(new DefaultMappingValue())
+                .withKey(new MappingTestMocks.MockMappingKey())
+                .withValue(new MappingTestMocks.MockMappingValue())
                 .forDevice(deviceId)
                 .build();
     }
 
     @Before
     public void setup() {
-        final Mapping mapping1 = mockMapping(1, "lisp:10.1.1.1");
-        final Mapping mapping2 = mockMapping(2, "lisp:10.1.1.2");
+        final Mapping mapping1 = mockMapping(1, DEVICE_ID_1);
+        final Mapping mapping2 = mockMapping(2, DEVICE_ID_2);
 
         event1 = new MappingEvent(MappingEvent.Type.MAPPING_ADDED, mapping1);
         sameAsEvent1 = new MappingEvent(MappingEvent.Type.MAPPING_ADDED, mapping1);
@@ -79,7 +82,7 @@
     @Test
     public void testConstructor() {
         final long time = System.currentTimeMillis();
-        final Mapping mapping = mockMapping(1, "lisp:10.1.1.1");
+        final Mapping mapping = mockMapping(1, DEVICE_ID_1);
         final MappingEvent event = new MappingEvent(MappingEvent.Type.MAPPING_UPDATED, mapping);
         validateEvent(event, MappingEvent.Type.MAPPING_UPDATED, mapping, time,
                 time + TimeUnit.SECONDS.toMillis(30));
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/MappingTestMocks.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/MappingTestMocks.java
new file mode 100644
index 0000000..364a9b0
--- /dev/null
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/MappingTestMocks.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping;
+
+import org.onlab.packet.IpPrefix;
+import org.onosproject.mapping.actions.MappingAction;
+import org.onosproject.mapping.actions.MappingActions;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddresses;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Commons mocks used by the mapping management tasks.
+ */
+public class MappingTestMocks {
+
+    private static final String IP = "1.2.3.4/24";
+
+    /**
+     * Mock mapping key class used for satisfying API requirements.
+     */
+    public static class MockMappingKey implements MappingKey {
+
+        @Override
+        public MappingAddress address() {
+            IpPrefix ip = IpPrefix.valueOf(IP);
+            return MappingAddresses.ipv4MappingAddress(ip);
+        }
+    }
+
+    /**
+     * Mock mapping value class used for satisfying API requirements.
+     */
+    public static class MockMappingValue implements MappingValue {
+
+        @Override
+        public MappingAction action() {
+            return MappingActions.noAction();
+        }
+
+        @Override
+        public List<MappingTreatment> treatments() {
+            return Collections.emptyList();
+        }
+    }
+}
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/actions/MappingActionsTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/actions/MappingActionsTest.java
new file mode 100644
index 0000000..68a989f
--- /dev/null
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/actions/MappingActionsTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mapping.actions;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onlab.junit.UtilityClassChecker.assertThatClassIsUtility;
+
+/**
+ * Unit tests for various mapping action implementation classes.
+ */
+public class MappingActionsTest {
+
+    /**
+     * Checks that a MappingAction object has the proper type, and then converts
+     * it to the proper type.
+     *
+     * @param action MappingAction object to convert
+     * @param type   Enumerated type value for the MappingAction class
+     * @param clazz  Desired MappingAction class
+     * @param <T>    The type the caller wants returned
+     * @return converted object
+     */
+    @SuppressWarnings("unchecked")
+    private <T> T checkAndConvert(MappingAction action, MappingAction.Type type, Class clazz) {
+        assertThat(action, is(notNullValue()));
+        assertThat(action.type(), is(equalTo(type)));
+        assertThat(action, instanceOf(clazz));
+        return (T) action;
+    }
+
+    /**
+     * Checks that the MappingActions class is a valid utility class.
+     */
+    @Test
+    public void testMappingActionsUtility() {
+        assertThatClassIsUtility(MappingActions.class);
+    }
+
+    /**
+     * Checks that the mapping action implementations are immutable.
+     */
+    @Test
+    public void testMappingActionsImmutability() {
+        assertThatClassIsImmutable(NoMappingAction.class);
+        assertThatClassIsImmutable(ForwardMappingAction.class);
+        assertThatClassIsImmutable(NativeForwardMappingAction.class);
+        assertThatClassIsImmutable(DropMappingAction.class);
+    }
+
+    /**
+     * Tests the noAction method.
+     */
+    @Test
+    public void testNoActionMethod() {
+        MappingAction mappingAction = MappingActions.noAction();
+        checkAndConvert(mappingAction,
+                        MappingAction.Type.NO_ACTION,
+                        NoMappingAction.class);
+    }
+
+    /**
+     * Tests the forward method.
+     */
+    @Test
+    public void testForwardMethod() {
+        MappingAction mappingAction = MappingActions.forward();
+        checkAndConvert(mappingAction,
+                        MappingAction.Type.FORWARD,
+                        ForwardMappingAction.class);
+    }
+
+    /**
+     * Tests the native forward method.
+     */
+    @Test
+    public void testNativeForwardMethod() {
+        MappingAction mappingAction = MappingActions.nativeForward();
+        checkAndConvert(mappingAction,
+                        MappingAction.Type.NATIVE_FORWARD,
+                        NativeForwardMappingAction.class);
+    }
+
+    /**
+     * Tests the drop method.
+     */
+    @Test
+    public void testDropMethod() {
+        MappingAction mappingAction = MappingActions.drop();
+        checkAndConvert(mappingAction,
+                        MappingAction.Type.DROP,
+                        DropMappingAction.class);
+    }
+}
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/instructions/MappingInstructionsTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/instructions/MappingInstructionsTest.java
index e11022c..59bb3bf 100644
--- a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/instructions/MappingInstructionsTest.java
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/instructions/MappingInstructionsTest.java
@@ -87,146 +87,12 @@
      */
     @Test
     public void testImmutabilityOfMappingInstructions() {
-        assertThatClassIsImmutable(ActionMappingInstruction.NoActionMappingInstruction.class);
-        assertThatClassIsImmutable(ActionMappingInstruction.NativeForwardMappingInstruction.class);
-        assertThatClassIsImmutable(ActionMappingInstruction.ForwardMappingInstruction.class);
-        assertThatClassIsImmutable(ActionMappingInstruction.DropMappingInstruction.class);
         assertThatClassIsImmutable(MulticastMappingInstruction.WeightMappingInstruction.class);
         assertThatClassIsImmutable(MulticastMappingInstruction.PriorityMappingInstruction.class);
         assertThatClassIsImmutable(UnicastMappingInstruction.WeightMappingInstruction.class);
         assertThatClassIsImmutable(UnicastMappingInstruction.PriorityMappingInstruction.class);
     }
 
-    private final ActionMappingInstruction noAction1 = MappingInstructions.noAction();
-    private final ActionMappingInstruction noAction2 = MappingInstructions.noAction();
-
-    /**
-     * Tests the noAction method.
-     */
-    @Test
-    public void testNoActionMethod() {
-        ActionMappingInstruction instruction = MappingInstructions.noAction();
-        checkAndConvert(instruction,
-                        ActionMappingInstruction.Type.ACTION,
-                        ActionMappingInstruction.NoActionMappingInstruction.class);
-    }
-
-    /**
-     * Tests the equals() method of the NoActionMappingInstruction class.
-     */
-    @Test
-    public void testNoActionMappingInstructionEquals() {
-        new EqualsTester()
-                .addEqualityGroup(noAction1, noAction2)
-                .testEquals();
-    }
-
-    /**
-     * Tests the hashCode() method of the NoActionMappingInstruction class.
-     */
-    @Test
-    public void testNoActionMappingInstructionHashCode() {
-        assertThat(noAction1.hashCode(), is(equalTo(noAction2.hashCode())));
-    }
-
-    private final ActionMappingInstruction fwdAction1 = MappingInstructions.forwardAction();
-    private final ActionMappingInstruction fwdAction2 = MappingInstructions.forwardAction();
-
-    /**
-     * Tests the forwardAction method.
-     */
-    @Test
-    public void testForwardActionMethod() {
-        ActionMappingInstruction instruction = MappingInstructions.forwardAction();
-        checkAndConvert(instruction,
-                        ActionMappingInstruction.Type.ACTION,
-                        ActionMappingInstruction.ForwardMappingInstruction.class);
-    }
-
-    /**
-     * Tests the equals() method of the ForwardActionMappingInstruction class.
-     */
-    @Test
-    public void testForwardActionMappingInstructionEquals() {
-        new EqualsTester()
-                .addEqualityGroup(fwdAction1, fwdAction2)
-                .testEquals();
-    }
-
-    /**
-     * Tests the hashCode() method of the ForwardActionMappingInstruction class.
-     */
-    @Test
-    public void testForwardActionMappingInstructionHashCode() {
-        assertThat(fwdAction1.hashCode(), is(equalTo(fwdAction2.hashCode())));
-    }
-
-    private final ActionMappingInstruction nativeFwdAction1 =
-                                            MappingInstructions.nativeForwardAction();
-    private final ActionMappingInstruction nativeFwdAction2 =
-                                            MappingInstructions.nativeForwardAction();
-
-    /**
-     * Tests the nativeForwardAction method.
-     */
-    @Test
-    public void testNativeForwardActionMethod() {
-        ActionMappingInstruction instruction = MappingInstructions.nativeForwardAction();
-        checkAndConvert(instruction,
-                        ActionMappingInstruction.Type.ACTION,
-                        ActionMappingInstruction.NativeForwardMappingInstruction.class);
-    }
-
-    /**
-     * Tests the equals() method of the NativeForwardActionMappingInstruction class.
-     */
-    @Test
-    public void testNativeForwardActionMappingInstructionEquals() {
-        new EqualsTester()
-                .addEqualityGroup(nativeFwdAction1, nativeFwdAction2)
-                .testEquals();
-    }
-
-    /**
-     * Tests the hashCode() method of the NativeForwardActionMappingInstruction class.
-     */
-    @Test
-    public void testNativeForwardActionMappingInstructionHashCode() {
-        assertThat(nativeFwdAction1.hashCode(), is(equalTo(nativeFwdAction2.hashCode())));
-    }
-
-    private final ActionMappingInstruction dropAction1 = MappingInstructions.dropAction();
-    private final ActionMappingInstruction dropAction2 = MappingInstructions.dropAction();
-
-    /**
-     * Tests the dropAction method.
-     */
-    @Test
-    public void testDropActionMethod() {
-        ActionMappingInstruction instruction = MappingInstructions.dropAction();
-        checkAndConvert(instruction,
-                        ActionMappingInstruction.Type.ACTION,
-                        ActionMappingInstruction.DropMappingInstruction.class);
-    }
-
-    /**
-     * Tests the equals() method of the DropActionMappingInstruction class.
-     */
-    @Test
-    public void testDropActionMappingInstructionEquals() {
-        new EqualsTester()
-                .addEqualityGroup(dropAction1, dropAction2)
-                .testEquals();
-    }
-
-    /**
-     * Tests the hashCode() method of the DropActionMappingInstruction class.
-     */
-    @Test
-    public void testDropActionMappingInstructionHashCode() {
-        assertThat(dropAction1.hashCode(), is(equalTo(dropAction2.hashCode())));
-    }
-
     private final UnicastMappingInstruction uniWeight1 =
                                     MappingInstructions.unicastWeight(1);
     private final UnicastMappingInstruction sameAsUniWeight1 =