[ONOS-5805] MEF SCA REST API app for CE App

    Migrating MEF SCA API translation app to onos-app-samples.

    - Originally developed mainly by Konstantinos Kanonakis <kanonakisk@gmail.com>

Change-Id: Ibf9f9e60c4dcd6375dd135a2f2c7714e3cd7d127
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/ApiDocRegistrator.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/ApiDocRegistrator.java
new file mode 100644
index 0000000..20ca056
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/ApiDocRegistrator.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016-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.mefscaapi;
+
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.rest.AbstractApiDocRegistrator;
+import org.onosproject.rest.ApiDocProvider;
+
+// Usually onos-maven-plugin generates swagger.json and generate equivalent.
+// But this app is generated "from" swagger, so equivalent is not auto-generated
+// by the plugin. Manually creating one.
+@Component(immediate = true)
+public class ApiDocRegistrator extends AbstractApiDocRegistrator {
+    public ApiDocRegistrator() {
+        // sync with pom.xml web.context
+        super(new ApiDocProvider("/onos/mef-sca-api",
+                                 "MEF SCA REST API",
+                                 ApiDocRegistrator.class.getClassLoader()));
+    }
+}
\ No newline at end of file
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/MefScaApiAppComponent.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/MefScaApiAppComponent.java
new file mode 100644
index 0000000..c9931ef
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/MefScaApiAppComponent.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.mefscaapi;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Skeletal ONOS application component.
+ */
+@Component(immediate = true)
+public class MefScaApiAppComponent {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Activate
+    protected void activate() {
+        log.info("Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        log.info("Stopped");
+    }
+
+}
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/MefScaApiWebApplication.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/MefScaApiWebApplication.java
new file mode 100644
index 0000000..57b3d01
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/MefScaApiWebApplication.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014-2015 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.mefscaapi;
+
+import org.onlab.rest.AbstractWebApplication;
+import org.onosproject.mefscaapi.api.JacksonJsonProvider;
+import org.onosproject.mefscaapi.api.SCAETHFDFrECApi;
+import org.onosproject.mefscaapi.api.SCAETHFPPUNINApi;
+import org.onosproject.mefscaapi.api.SCAETHFlowDomainApi;
+
+import java.util.Set;
+
+/**
+ * MEF SCA API web application.
+ */
+public class MefScaApiWebApplication extends AbstractWebApplication {
+    @Override
+    public Set<Class<?>> getClasses() {
+        return getClasses(SCAETHFDFrECApi.class, SCAETHFlowDomainApi.class, SCAETHFPPUNINApi.class,
+                          JacksonJsonProvider.class);
+    }
+}
+
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFDFrECApiServiceFactory.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFDFrECApiServiceFactory.java
new file mode 100644
index 0000000..7d24646
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFDFrECApiServiceFactory.java
@@ -0,0 +1,12 @@
+package org.onosproject.mefscaapi.api.factories;
+
+import org.onosproject.mefscaapi.api.SCAETHFDFrECApiService;
+import org.onosproject.mefscaapi.api.impl.ScaEthFdFrEcApiServiceImpl;
+
+public class SCAETHFDFrECApiServiceFactory {
+    private final static SCAETHFDFrECApiService service = new ScaEthFdFrEcApiServiceImpl();
+
+    public static SCAETHFDFrECApiService getSCAETHFDFrECApi() {
+        return service;
+    }
+}
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFPPUNINApiServiceFactory.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFPPUNINApiServiceFactory.java
new file mode 100644
index 0000000..7659458
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFPPUNINApiServiceFactory.java
@@ -0,0 +1,12 @@
+package org.onosproject.mefscaapi.api.factories;
+
+import org.onosproject.mefscaapi.api.SCAETHFPPUNINApiService;
+import org.onosproject.mefscaapi.api.impl.ScaEthFppUniNApiServiceImpl;
+
+public class SCAETHFPPUNINApiServiceFactory {
+    private final static SCAETHFPPUNINApiService service = new ScaEthFppUniNApiServiceImpl();
+
+    public static SCAETHFPPUNINApiService getSCAETHFPPUNINApi() {
+        return service;
+    }
+}
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFlowDomainApiServiceFactory.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFlowDomainApiServiceFactory.java
new file mode 100644
index 0000000..98b0545
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/factories/SCAETHFlowDomainApiServiceFactory.java
@@ -0,0 +1,12 @@
+package org.onosproject.mefscaapi.api.factories;
+
+import org.onosproject.mefscaapi.api.SCAETHFlowDomainApiService;
+import org.onosproject.mefscaapi.api.impl.ScaEthFlowDomainApiServiceImpl;
+
+public class SCAETHFlowDomainApiServiceFactory {
+    private final static SCAETHFlowDomainApiService service = new ScaEthFlowDomainApiServiceImpl();
+
+    public static SCAETHFlowDomainApiService getSCAETHFlowDomainApi() {
+        return service;
+    }
+}
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFdFrEcApiServiceImpl.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFdFrEcApiServiceImpl.java
new file mode 100755
index 0000000..8a3c8cc
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFdFrEcApiServiceImpl.java
@@ -0,0 +1,150 @@
+package org.onosproject.mefscaapi.api.impl;
+
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetManager;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetVirtualConnection;
+import org.onosproject.mefscaapi.api.ApiResponseMessage;
+import org.onosproject.mefscaapi.api.SCAETHFDFrECApiService;
+import org.onosproject.mefscaapi.api.model.SCAETHFDFrEC;
+import org.onosproject.mefscaapi.translate.ScaApiTranslator;
+import org.slf4j.Logger;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriBuilder;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class ScaEthFdFrEcApiServiceImpl extends SCAETHFDFrECApiService {
+
+    CarrierEthernetManager ceManager = AbstractShellCommand.get(CarrierEthernetManager.class);
+
+    private static final Logger log = getLogger(ScaEthFdFrEcApiServiceImpl.class);
+
+    private static final String CHECK_LOG = " Check ONOS log for details.";
+    private static final String NOT_TRANSLATED = "Could not translate EVC.";
+    private static final String NOT_EXISTS = "EVC does not exist.";
+    private static final String CREATED = "EVC was created successfully.";
+    private static final String UPDATED = "EVC was updated successfully.";
+    private static final String NOT_CREATED = "EVC could not be created.";
+    private static final String REMOVED = "EVC was removed successfully.";
+    private static final String NOT_REMOVED = "EVC could not be removed.";
+    private static final String REFCOUNT_NOT_ZERO = " RefCount is not zero.";
+    private static final String EVC_REL_URI = "SCA_ETH_FDFr_EC/";
+
+    @Override
+    public Response deleteSCAETHFDFrEC(String id, SecurityContext securityContext)
+            throws NotFoundException {
+
+        if (ceManager.getEvc(id) == null) {
+            return response(Response.Status.NOT_FOUND,
+                            responseMsg(ApiResponseMessage.ERROR, NOT_EXISTS));
+        } else {
+            // Remove the EVC
+            ceManager.removeEvc(id);
+            return response(Response.Status.OK,
+                            responseMsg(ApiResponseMessage.INFO, REMOVED));
+        }
+    }
+
+    @Override
+    public Response findSCAETHFDFrECById(String id, SecurityContext securityContext)
+            throws NotFoundException {
+
+        CarrierEthernetVirtualConnection evc = ceManager.getEvc(id);
+
+        if (evc == null) {
+            return response(Response.Status.NOT_FOUND,
+                            responseMsg(ApiResponseMessage.ERROR, NOT_EXISTS));
+        } else {
+            SCAETHFDFrEC scaEvc = ScaApiTranslator.fromCarrierEthernetVirtualConnection(evc);
+            if (scaEvc == null) {
+                return response(Response.Status.INTERNAL_SERVER_ERROR,
+                                responseMsg(ApiResponseMessage.ERROR, NOT_TRANSLATED));
+            } else {
+                return response(Response.Status.OK,
+                                scaEvc);
+            }
+        }
+    }
+
+    @Override
+    public Response findSCAETHFDFrECByState(String state, SecurityContext securityContext)
+            throws NotFoundException {
+
+        List<SCAETHFDFrEC> scaEvcList = new LinkedList<>();
+        // Browse through all CE FCs and translate them to NRP ones
+        for (CarrierEthernetVirtualConnection ceEvc : ceManager.evcMap().values()) {
+            SCAETHFDFrEC scaEvc =
+                    ScaApiTranslator.fromCarrierEthernetVirtualConnection(ceEvc);
+            // If no state is provided, return all EVCs
+            if (scaEvc != null &&
+                    (state == null || state.equalsIgnoreCase(scaEvc.getState().toString()))) {
+                scaEvcList.add(scaEvc);
+            }
+        }
+
+        // TODO: Indicate if some of the EVCs could not be translated?
+        return response(Response.Status.OK, scaEvcList);
+    }
+
+    @Override
+    public Response sCAETHFDFrECIdPatch(String id, String state, SecurityContext securityContext)
+            throws NotFoundException {
+        // do some magic!
+        return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
+    }
+
+    @Override
+    public Response sCAETHFDFrECPost(SCAETHFDFrEC scaEthFdFrEc, SecurityContext securityContext)
+            throws NotFoundException {
+
+        log.trace("input: {}", scaEthFdFrEc);
+
+        CarrierEthernetVirtualConnection evc =
+                ScaApiTranslator.toCarrierEthernetVirtualConnection(scaEthFdFrEc);
+
+        if (evc == null) {
+            return response(Response.Status.BAD_REQUEST,
+                            responseMsg(ApiResponseMessage.ERROR, NOT_TRANSLATED));
+        } else {
+            boolean serviceExisted =
+                    evc.id() != null && ceManager.evcMap().containsKey(evc.id());
+
+            ceManager.installEvc(evc);
+
+            if (evc.isActive()) {
+                String message = serviceExisted ? UPDATED : CREATED;
+                return response(EVC_REL_URI + evc.id(),
+                                responseMsg(ApiResponseMessage.INFO, message));
+            } else {
+                // TODO: Find out somehow the reason for the failure
+                return response(Response.Status.INTERNAL_SERVER_ERROR,
+                                responseMsg(ApiResponseMessage.ERROR, NOT_CREATED + CHECK_LOG));
+            }
+        }
+    }
+
+    private <T>  Response response(Response.Status status, T entity) {
+        return Response
+                .status(status)
+                .entity(entity)
+                .build();
+    }
+
+    private <T>  Response response(String uri, T entity) {
+        return Response
+                .created(UriBuilder.fromUri(uri).build())
+                .entity(entity)
+                .build();
+    }
+
+    private ApiResponseMessage responseMsg(int msgCode, String msg) {
+        return new ApiResponseMessage(msgCode, msg == null ? "" : msg);
+    }
+}
+
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFlowDomainApiServiceImpl.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFlowDomainApiServiceImpl.java
new file mode 100755
index 0000000..e2e7a5d
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFlowDomainApiServiceImpl.java
@@ -0,0 +1,24 @@
+package org.onosproject.mefscaapi.api.impl;
+
+import org.onosproject.mefscaapi.api.ApiResponseMessage;
+import org.onosproject.mefscaapi.api.NotFoundException;
+import org.onosproject.mefscaapi.api.SCAETHFlowDomainApiService;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+public class ScaEthFlowDomainApiServiceImpl extends SCAETHFlowDomainApiService {
+
+    @Override
+    public Response getSCAETHFlowDomain(SecurityContext securityContext) throws NotFoundException {
+        // do some magic!
+        return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
+    }
+
+    @Override
+    public Response getSCAETHFlowDomainById(String id, SecurityContext securityContext) throws NotFoundException {
+        // do some magic!
+        return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
+    }
+
+}
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFppUniNApiServiceImpl.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFppUniNApiServiceImpl.java
new file mode 100755
index 0000000..3090404
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/ScaEthFppUniNApiServiceImpl.java
@@ -0,0 +1,120 @@
+package org.onosproject.mefscaapi.api.impl;
+
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetManager;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetUni;
+import org.onosproject.mefscaapi.api.ApiResponseMessage;
+import org.onosproject.mefscaapi.api.NotFoundException;
+import org.onosproject.mefscaapi.api.SCAETHFPPUNINApiService;
+import org.onosproject.mefscaapi.api.model.SCAETHFPPUNIN;
+import org.onosproject.mefscaapi.api.model.SCAETHFlowPoint;
+import org.onosproject.mefscaapi.translate.ScaApiTranslator;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriBuilder;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ScaEthFppUniNApiServiceImpl extends SCAETHFPPUNINApiService {
+
+    CarrierEthernetManager ceManager = AbstractShellCommand.get(CarrierEthernetManager.class);
+
+    private static final String NOT_TRANSLATED = "Could not translate UNI.";
+    private static final String EXISTS = "UNI already exists.";
+    private static final String NOT_EXISTS = "UNI does not exist.";
+    private static final String CREATED = "UNI was created successfully.";
+    private static final String REMOVED = "UNI was removed successfully.";
+    private static final String NOT_REMOVED = "UNI could not be removed.";
+    private static final String REFCOUNT_NOT_ZERO = " RefCount is not zero.";
+    private static final String UNI_REL_URI = "SCA_ETH_FPP_UNI_N/";
+
+    @Override
+    public Response createSCAETHFPPUNIN(SCAETHFPPUNIN uni, SecurityContext securityContext) throws NotFoundException {
+
+        // Create SCA Flow Point and add provided SCA UNI to it
+        SCAETHFlowPoint scaFlowPoint = new SCAETHFlowPoint();
+        scaFlowPoint.setScaEthFppUniN(uni);
+
+        CarrierEthernetUni ceUni = ScaApiTranslator.toCarrierEthernetUni(scaFlowPoint, null);
+        if (ceUni == null) {
+            return response(Response.Status.BAD_REQUEST,
+                            responseMsg(ApiResponseMessage.ERROR, NOT_TRANSLATED));
+        } else if (ceManager.addGlobalUni(ceUni) == null) {
+            return response(Response.Status.FORBIDDEN,
+                            responseMsg(ApiResponseMessage.ERROR, EXISTS));
+        } else {
+            return response(UNI_REL_URI + ceUni.id(),
+                            responseMsg(ApiResponseMessage.INFO, CREATED));
+        }
+    }
+
+    @Override
+    public Response deleteSCAETHFPPUNIN(String uniID, SecurityContext securityContext) throws NotFoundException {
+
+        if (ceManager.getUniMap().get(uniID) == null) {
+            return response(Response.Status.NOT_FOUND,
+                            responseMsg(ApiResponseMessage.ERROR, NOT_EXISTS));
+        } else if (ceManager.removeGlobalUni(uniID) == null) {
+            return response(Response.Status.FORBIDDEN,
+                            responseMsg(ApiResponseMessage.ERROR, NOT_REMOVED + REFCOUNT_NOT_ZERO));
+        } else {
+            return response(Response.Status.OK,
+                            responseMsg(ApiResponseMessage.INFO, REMOVED));
+        }
+    }
+
+    @Override
+    public Response findSCAETHFPPUNIN(String fields, SecurityContext securityContext) throws NotFoundException {
+
+        List<SCAETHFPPUNIN> scaUniList = new LinkedList<>();
+
+        // Add all global UNIs if they are not there already
+        ceManager.getUnisFromTopo(false, false).forEach(uni -> ceManager.addGlobalUni(uni));
+
+        // Browse through all global CE UNIs and translate them to SCA ones
+        for (CarrierEthernetUni ceUni : ceManager.getUniMap().values()) {
+            // TODO: Match on provided fields
+            SCAETHFlowPoint scaFlowPoint = ScaApiTranslator.fromCarrierEthernetUni(ceUni);
+            if (scaFlowPoint != null) {
+                scaUniList.add(scaFlowPoint.getScaEthFppUniN());
+            }
+        }
+
+        // TODO: Indicate if some of the Flow Points could not be translated?
+        return response(Response.Status.OK, scaUniList);
+    }
+
+    @Override
+    public Response getSCAETHFPPUNIN(String uniID, String fields, SecurityContext securityContext)
+            throws NotFoundException {
+        // do some magic!
+        return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
+    }
+
+    @Override
+    public Response patchSCAETHFPPUNIN(String uniID, SCAETHFPPUNIN individual, SecurityContext securityContext)
+            throws NotFoundException {
+        // do some magic!
+        return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
+    }
+
+    private <T>  Response response(Response.Status status, T entity) {
+        return Response
+                .status(status)
+                .entity(entity)
+                .build();
+    }
+
+    private <T>  Response response(String uri, T entity) {
+        return Response
+                .created(UriBuilder.fromUri(uri).build())
+                .entity(entity)
+                .build();
+    }
+
+    private ApiResponseMessage responseMsg(int msgCode, String msg) {
+        return new ApiResponseMessage(msgCode, msg == null ? "" : msg);
+    }
+}
+
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/package-info.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/package-info.java
new file mode 100644
index 0000000..ba2296b
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/api/impl/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016-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.
+ */
+/**
+ * MEF SCA API implementations.
+ */
+package org.onosproject.mefscaapi.api.impl;
\ No newline at end of file
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/package-info.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/package-info.java
new file mode 100644
index 0000000..324b59d
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016-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.
+ */
+/**
+ * MEF SCA app.
+ */
+package org.onosproject.mefscaapi;
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/translate/ScaApiTranslator.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/translate/ScaApiTranslator.java
new file mode 100644
index 0000000..8c02670
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/translate/ScaApiTranslator.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2016 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.mefscaapi.translate;
+
+import org.onlab.util.Bandwidth;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetBandwidthProfile;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetConnection;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetUni;
+import org.onosproject.ecord.carrierethernet.app.CarrierEthernetVirtualConnection;
+import org.onlab.packet.VlanId;
+import org.onosproject.mefscaapi.api.model.SCAETHFDFrEC;
+import org.onosproject.mefscaapi.api.model.SCAETHFPPUNIN;
+import org.onosproject.mefscaapi.api.model.SCAETHFPPUNINTransportPort;
+import org.onosproject.mefscaapi.api.model.SCAETHFlowPoint;
+import org.onosproject.mefscaapi.api.model.SCAETHFlowPointClassOfServiceIdentifierIp;
+import org.onosproject.mefscaapi.api.model.SCAETHFlowPointIngressBandwidthProfilePerClassOfServiceIdentifier;
+import org.onosproject.mefscaapi.api.model.SCAETHFlowPointIngressBandwidthProfilePerEvc;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Methods for translating between SCA API swagger-generated JAVA classes and CE App classes.
+ */
+public final class ScaApiTranslator {
+
+    private static DeviceService deviceService = AbstractShellCommand.get(DeviceService.class);
+
+    private static final Logger log = getLogger(ScaApiTranslator.class);
+
+    // Not to be called
+    private ScaApiTranslator() {
+    }
+
+    public static CarrierEthernetVirtualConnection toCarrierEthernetVirtualConnection(SCAETHFDFrEC scaethfdFrEC) {
+
+        String evcId = scaethfdFrEC.getId();
+        String evcCfgId = scaethfdFrEC.getEvcCfgIdentifier();
+        CarrierEthernetVirtualConnection.Type evcType =
+                CarrierEthernetVirtualConnection.Type.valueOf(scaethfdFrEC.getEvcServiceType().name());
+        Integer maxNumUni = scaethfdFrEC.getEvcStatusMaxNumUni();
+        Set<CarrierEthernetUni> uniSet = new HashSet<>();
+
+        CarrierEthernetUni ceUni;
+        CarrierEthernetUni.Role ceUniRole = CarrierEthernetUni.Role.ROOT;
+        ListIterator<SCAETHFlowPoint> it = scaethfdFrEC.getSCAETHFlowPoints().listIterator();
+        while (it.hasNext()) {
+            if (evcType.equals(CarrierEthernetConnection.Type.ROOT_MULTIPOINT)) {
+                ceUniRole = (it.nextIndex() == 0) ? CarrierEthernetUni.Role.ROOT : CarrierEthernetUni.Role.LEAF;
+            }
+            SCAETHFlowPoint scaFlowPoint = it.next();
+            // Create new CE UNI
+            ceUni = toCarrierEthernetUni(scaFlowPoint, ceUniRole);
+            if (ceUni == null) {
+                return null;
+            }
+            uniSet.add(ceUni);
+        }
+
+        return CarrierEthernetVirtualConnection.builder()
+                .id(evcId)
+                .cfgId(evcCfgId)
+                .type(evcType)
+                .maxNumUni(maxNumUni)
+                .uniSet(uniSet)
+                .build();
+    }
+
+    public static SCAETHFDFrEC fromCarrierEthernetVirtualConnection(CarrierEthernetVirtualConnection ceService) {
+
+        SCAETHFDFrEC scaethfdFrEC = new SCAETHFDFrEC();
+
+        scaethfdFrEC.setId(ceService.id());
+        scaethfdFrEC.setEvcCfgIdentifier(ceService.cfgId());
+        scaethfdFrEC.setEvcServiceType(SCAETHFDFrEC.EvcServiceTypeEnum.valueOf(ceService.type().name()));
+        scaethfdFrEC.setEvcStatusMaxNumUni(ceService.maxNumUni());
+        scaethfdFrEC.setState(SCAETHFDFrEC.StateEnum.valueOf(ceService.state().name()));
+
+        List<SCAETHFlowPoint> scaFlowPointList = new ArrayList<>();
+        SCAETHFlowPoint scaFlowpoint;
+
+        Iterator<CarrierEthernetUni> it = ceService.uniSet().iterator();
+        while (it.hasNext()) {
+            CarrierEthernetUni ceUni = it.next();
+            // Create new SCA Flow Point from CE UNI (will also create an SCA UNI internally)
+            scaFlowpoint = fromCarrierEthernetUni(ceUni);
+            scaFlowPointList.add(scaFlowpoint);
+        }
+
+        scaethfdFrEC.setSCAETHFlowPoints(scaFlowPointList);
+
+        return scaethfdFrEC;
+    }
+
+    public static CarrierEthernetUni toCarrierEthernetUni(SCAETHFlowPoint scaFlowPoint,
+                                                   CarrierEthernetUni.Role ceUniRole) {
+
+        // TODO: Check for null
+
+        // Get SCA UNI from SCA Flow Point
+        SCAETHFPPUNIN scaUni = scaFlowPoint.getScaEthFppUniN();
+
+        // Get UNI id
+        String ceUniCfgId = scaUni.getInterfaceCfgIdentifier();
+
+        // Get CE UNI CE-VLAN id
+        VlanId ceVlanId = ((scaUni.getCeVlanId() == null) ? null :
+                VlanId.vlanId(Short.valueOf(scaUni.getCeVlanId())));
+
+        // TODO: Allow for both ingress and egress BW profiles
+        // Get CE UNI BW profile
+        CarrierEthernetBandwidthProfile ceBwp = getCeBwpFromScaFlowPoint(scaFlowPoint);
+
+        // Get CE UNI connect point
+        DeviceId deviceId = DeviceId.deviceId(scaUni.getTransportPort().getHostname());
+        if (deviceService.getDevice(deviceId) == null) {
+            log.error("Invalid deviceId {}", deviceId);
+            return null;
+        }
+        PortNumber portNumber = PortNumber.portNumber(scaUni.getTransportPort().getPort());
+        if (deviceService.getPort(deviceId, portNumber) == null) {
+            log.error("Invalid port {} for device {}", portNumber, deviceId);
+            return null;
+        }
+        ConnectPoint ceUniCp = new ConnectPoint(deviceId, portNumber);
+
+        // Create CE UNI
+        return CarrierEthernetUni.builder()
+                .cp(ceUniCp)
+                .cfgId(ceUniCfgId)
+                .role(ceUniRole)
+                .ceVlanId(ceVlanId)
+                .bwp(ceBwp)
+                .build();
+    }
+
+    public static SCAETHFlowPoint fromCarrierEthernetUni(CarrierEthernetUni ceUni) {
+
+        SCAETHFlowPoint scaFlowPoint = new SCAETHFlowPoint();
+        SCAETHFPPUNIN scaUni = new SCAETHFPPUNIN();
+
+        // Set SCA UNI Transport Port
+        SCAETHFPPUNINTransportPort scaPort = new SCAETHFPPUNINTransportPort();
+        scaPort.setHostname(ceUni.cp().deviceId().toString());
+        scaPort.setPort(ceUni.cp().port().toString());
+        scaPort.setVendor(deviceService.getDevice(ceUni.cp().deviceId()).manufacturer());
+        scaUni.setTransportPort(scaPort);
+        if (ceUni.ceVlanId() != null) {
+            scaUni.setCeVlanId(ceUni.ceVlanId().toString());
+        }
+
+        scaUni.setInterfaceCfgIdentifier(ceUni.cfgId());
+
+        // Add SCA UNI to SCA Flow Point
+        scaFlowPoint.setScaEthFppUniN(scaUni);
+
+        // TODO: Allow for both ingress and egress BW profiles
+        // FIXME: A CE UNI may have multiple bandwidth profiles
+
+        // Apply existing BW profile from CE UNI to SCA Flow Point (or UNI)
+        applyCeUniBwpToScaFlowPoint(ceUni, scaFlowPoint);
+
+        // TODO: Check if the UNI type needs to be specified
+
+        return scaFlowPoint;
+    }
+
+    private static CarrierEthernetBandwidthProfile getCeBwpFromScaFlowPoint(
+            SCAETHFlowPoint scaFlowPoint) {
+
+        SCAETHFPPUNIN scaUni = scaFlowPoint.getScaEthFppUniN();
+        SCAETHFlowPointIngressBandwidthProfilePerEvc scaBwp = null;
+        SCAETHFlowPointIngressBandwidthProfilePerClassOfServiceIdentifier scaCosBwp = null;
+        String ceBwpId = null;
+        String ceBwpCfgId;
+        CarrierEthernetBandwidthProfile.Type ceBwpType;
+
+        SCAETHFlowPointIngressBandwidthProfilePerEvc ifaceBwp =
+                scaUni.getInterfaceCfgIngressBwp();
+        SCAETHFlowPointIngressBandwidthProfilePerEvc evcBwp =
+                scaFlowPoint.getIngressBandwidthProfilePerEvc();
+        SCAETHFlowPointIngressBandwidthProfilePerClassOfServiceIdentifier cosBwp =
+                scaFlowPoint.getIngressBandwidthProfilePerClassOfServiceIdentifier();
+
+        // TODO: Complete the COS part
+
+        // FIXME: Perform following check
+        /*Preconditions.checkArgument(ifaceBwp == null && evcBwp == null && cosBwp == null ||
+                (ifaceBwp != null ^ evcBwp != null ^ cosBwp != null),
+                                    "Only up to one BW profile can be set per UNI");*/
+
+        if (evcBwp != null) {
+            scaBwp = evcBwp;
+            ceBwpCfgId = scaBwp.getBwpCfgIdentifier();
+            ceBwpType = CarrierEthernetBandwidthProfile.Type.EVC;
+        } else if (ifaceBwp != null) {
+            scaBwp = ifaceBwp;
+            // Use the UNI connect point id
+            ceBwpId = scaUni.getTransportPort().getHostname() + "/" + scaUni.getTransportPort().getPort();
+            ceBwpType = CarrierEthernetBandwidthProfile.Type.INTERFACE;
+            ceBwpCfgId = ifaceBwp.getBwpCfgIdentifier();
+            if (ceBwpCfgId == null) {
+                ceBwpCfgId = ceBwpId;
+            }
+        } else if (cosBwp != null) {
+            // FIXME: Complete and test the COS part
+            scaCosBwp = cosBwp;
+            SCAETHFlowPointClassOfServiceIdentifierIp scaCosIdIp =
+                    scaFlowPoint.getClassOfServiceIdentifierIp();
+            if (scaCosIdIp == null) {
+                log.error("CoS ID is required for COS BW profile");
+                return null;
+            }
+            ceBwpId = scaCosIdIp.getClassOfServiceName();
+            ceBwpCfgId = scaCosBwp.getBwpCfgIdentifier();
+            ceBwpType = CarrierEthernetBandwidthProfile.Type.COS;
+        } else {
+            return null;
+        }
+
+        CeBwpParams ceBwpParams = scaBwp != null ? new CeBwpParams(scaBwp) :
+                new CeBwpParams(scaCosBwp);
+
+        return CarrierEthernetBandwidthProfile.builder()
+                .id(ceBwpId)
+                .cfgId(ceBwpCfgId)
+                .type(ceBwpType)
+                .cir(ceBwpParams.cir())
+                .cbs(ceBwpParams.cbs())
+                .eir(ceBwpParams.eir())
+                .ebs(ceBwpParams.ebs())
+                .build();
+    }
+
+    private static class CeBwpParams {
+
+        private Bandwidth cir = Bandwidth.bps((long) 0);
+        private Bandwidth eir = Bandwidth.bps((long) 0);
+        private long cbs = (long) 0;
+        private long ebs = (long) 0;
+
+        CeBwpParams() {}
+
+        CeBwpParams(SCAETHFlowPointIngressBandwidthProfilePerEvc scaBwp) {
+            if (scaBwp.getBwpCfgCir() != null) {
+                cir = Bandwidth.bps((long) scaBwp.getBwpCfgCir());
+            }
+            if (scaBwp.getBwpCfgEir() != null) {
+                eir = Bandwidth.bps((long) scaBwp.getBwpCfgEir());
+            }
+            if (scaBwp.getBwpCfgCbs() != null) {
+                cbs = (long) scaBwp.getBwpCfgCbs();
+            }
+            if (scaBwp.getBwpCfgEbs() != null) {
+                ebs = (long) scaBwp.getBwpCfgEbs();
+            }
+        }
+
+        CeBwpParams(SCAETHFlowPointIngressBandwidthProfilePerClassOfServiceIdentifier scaBwp) {
+            if (scaBwp.getBwpCfgCir() != null) {
+                cir = Bandwidth.bps((long) scaBwp.getBwpCfgCir());
+            }
+            if (scaBwp.getBwpCfgEir() != null) {
+                eir = Bandwidth.bps((long) scaBwp.getBwpCfgEir());
+            }
+            if (scaBwp.getBwpCfgCbs() != null) {
+                cbs = (long) scaBwp.getBwpCfgCbs();
+            }
+            if (scaBwp.getBwpCfgEbs() != null) {
+                ebs = (long) scaBwp.getBwpCfgEbs();
+            }
+        }
+
+        public Bandwidth cir() {
+            return cir;
+        }
+
+        public Bandwidth eir() {
+            return eir;
+        }
+
+        public long cbs() {
+            return cbs;
+        }
+
+        public long ebs() {
+            return ebs;
+        }
+    }
+
+    private static SCAETHFlowPoint applyCeUniBwpToScaFlowPoint(
+            CarrierEthernetUni ceUni, SCAETHFlowPoint scaFlowPoint) {
+
+        CarrierEthernetBandwidthProfile ceBwp = ceUni.bwp();
+
+        SCAETHFlowPoint newScaFlowPoint = scaFlowPoint;
+        SCAETHFPPUNIN newScaUni = scaFlowPoint.getScaEthFppUniN();
+
+        if (ceBwp != null) {
+            // Prepare SCA bandwidth profile
+            SCAETHFlowPointIngressBandwidthProfilePerEvc scaBwp = new SCAETHFlowPointIngressBandwidthProfilePerEvc();
+
+            // TODO: Check for null?
+            scaBwp.setBwpCfgCir((int) ceBwp.cir().bps());
+            scaBwp.setBwpCfgCbs((int) ceBwp.cbs());
+            scaBwp.setBwpCfgEir((int) ceBwp.eir().bps());
+            scaBwp.setBwpCfgEbs((int) ceBwp.ebs());
+
+            // TODO: Add the CoS part when it's ready from the CE app side
+            if (ceBwp.type().equals(CarrierEthernetBandwidthProfile.Type.EVC)) {
+                newScaUni.setEvcId(ceBwp.id());
+                newScaFlowPoint.setIngressBandwidthProfilePerEvc(scaBwp);
+            } else if (ceBwp.type().equals(CarrierEthernetBandwidthProfile.Type.INTERFACE)) {
+                newScaUni.setInterfaceCfgIdentifier(ceUni.cfgId());
+                newScaUni.setInterfaceCfgIngressBwp(scaBwp);
+            } else {
+                log.error("Could not add BW profile for Flow Point {}", scaFlowPoint.toString());
+                return null;
+            }
+        }
+
+        newScaFlowPoint.setScaEthFppUniN(newScaUni);
+
+        return newScaFlowPoint;
+    }
+
+}
diff --git a/mef-sca-api/src/main/java/org/onosproject/mefscaapi/translate/package-info.java b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/translate/package-info.java
new file mode 100644
index 0000000..daeec94
--- /dev/null
+++ b/mef-sca-api/src/main/java/org/onosproject/mefscaapi/translate/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016-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.
+ */
+/**
+ * MEF SCA app utilities.
+ */
+package org.onosproject.mefscaapi.translate;