transcriber: parameterize Neutron type in AbstractNeutronInterface 92/59992/3
authorIsaku Yamahata <isaku.yamahata@intel.com>
Thu, 6 Jul 2017 01:08:29 +0000 (18:08 -0700)
committerIsaku Yamahata <isaku.yamahata@intel.com>
Wed, 12 Jul 2017 06:08:44 +0000 (23:08 -0700)
Make generic parameter of Neutron of AbstractNeutronInterface for Tap-aaS.
flow classifier of Tap-aaS is child of tap service in yang model,
not Neutron. In order to make base class usable for Tap-aaS, make parent
class of mode generic parameter.

Change-Id: Iba24657e14280a7b91200442c0a8abbea5d72912
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractNeutronInterface.java
transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractTranscriberInterface.java [new file with mode: 0644]

index 4202b579bc2ee60b286ac3a714827c47408360e9..fc352c14c654d02ea03de6f6e6655cae1660edad 100644 (file)
@@ -8,34 +8,9 @@
 
 package org.opendaylight.neutron.transcriber;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.neutron.spi.INeutronAdminAttributes;
-import org.opendaylight.neutron.spi.INeutronBaseAttributes;
-import org.opendaylight.neutron.spi.INeutronCRUD;
 import org.opendaylight.neutron.spi.INeutronObject;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.attrs.rev150712.AdminAttributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.attrs.rev150712.BaseAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
@@ -43,460 +18,21 @@ import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-public abstract class AbstractNeutronInterface<T extends DataObject & Identifiable<K> & ChildOf<? super U>,
-        U extends ChildOf<? super Neutron> & Augmentable<U>, K extends Identifier<T>, S extends INeutronObject<S>>
-        implements AutoCloseable, INeutronCRUD<S> {
-    // T extends DataObject & Identifiable<K> & ChildOf<? super U> as 0th type argument
-    private static final int MD_LIST_CLASS_TYPE_INDEX = 0;
-    // U extends ChildOf<? super Neutron> & Augmentable<U> as 1st type argument
-    private static final int MD_CONTAINER_CLASS_TYPE_INDEX = 1;
-    // S extends INeutronObject<S> as 3rd type argument
-    private static final int NEUTRON_OBJECT_TYPE_INDEX = 3;
 
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractNeutronInterface.class);
-    private static final int DEDASHED_UUID_LENGTH = 32;
-    private static final int DEDASHED_UUID_START = 0;
-    private static final int DEDASHED_UUID_DIV1 = 8;
-    private static final int DEDASHED_UUID_DIV2 = 12;
-    private static final int DEDASHED_UUID_DIV3 = 16;
-    private static final int DEDASHED_UUID_DIV4 = 20;
-
-    private static final int RETRY_MAX = 2;
-
-    private final DataBroker db;
-
-    private final Class<U> mdContainerClass;
-    private final Class<T> mdListClass;
-
-    // Unfortunately odl yangtools doesn't model yang model "uses" as
-    // class/interface hierarchy. So we need to resort to use reflection
-    // to call setter method.
-    private final Class<? extends Builder<T>> builderClass;
-    private final Method setUuid;
-    private final Method setTenantId;
-    private final Method setProjectId;
-    private final Method setName;
-    private final Method setAdminStateUp;
-    private final Method setStatus;
-    private final Method setRevisionNumber;
-
-    AbstractNeutronInterface(Class<? extends Builder<T>> builderClass, DataBroker db) {
-        this.db = Preconditions.checkNotNull(db);
-        this.builderClass = builderClass;
-
-        ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
-        Type[] types = parameterizedType.getActualTypeArguments();
-        @SuppressWarnings("unchecked")
-        Class<T> localMdListClass = (Class<T>) types[MD_LIST_CLASS_TYPE_INDEX];
-        mdListClass = localMdListClass;
-        @SuppressWarnings("unchecked")
-        Class<U> localMdContainerClass = (Class<U>) types[MD_CONTAINER_CLASS_TYPE_INDEX];
-        mdContainerClass = localMdContainerClass;
-        @SuppressWarnings("unchecked")
-        Class<S> neutronObjectClass = (Class<S>) types[NEUTRON_OBJECT_TYPE_INDEX];
-        try {
-            setUuid = builderClass.getDeclaredMethod("setUuid", Uuid.class);
-            setTenantId = builderClass.getDeclaredMethod("setTenantId", Uuid.class);
-            if (INeutronBaseAttributes.class.isAssignableFrom(neutronObjectClass)) {
-                setName = builderClass.getDeclaredMethod("setName", String.class);
-                setProjectId = builderClass.getDeclaredMethod("setProjectId", String.class);
-                setRevisionNumber = builderClass.getDeclaredMethod("setRevisionNumber", Long.class);
-            } else {
-                setName = null;
-                setProjectId = null;
-                setRevisionNumber = null;
-            }
-
-            if (INeutronAdminAttributes.class.isAssignableFrom(neutronObjectClass)) {
-                setAdminStateUp = builderClass.getDeclaredMethod("setAdminStateUp", Boolean.class);
-                setStatus = builderClass.getDeclaredMethod("setStatus", String.class);
-            } else {
-                setAdminStateUp = null;
-                setStatus = null;
-            }
-        } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    public DataBroker getDataBroker() {
-        Preconditions.checkNotNull(db);
-        return db;
-    }
-
-    private InstanceIdentifier<T> createInstanceIdentifier(T item) {
-        return InstanceIdentifier.create(Neutron.class).child(mdContainerClass).child(mdListClass, item.getKey());
-    }
-
-    private InstanceIdentifier<U> createInstanceIdentifier() {
-        return InstanceIdentifier.create(Neutron.class).child(mdContainerClass);
-    }
-
-    protected <S1 extends INeutronBaseAttributes<S1>, M extends BaseAttributes, B extends Builder<M>>
-        void toMdIds(INeutronObject<S1> neutronObject, B builder) {
-        try {
-            if (neutronObject.getID() != null) {
-                setUuid.invoke(builder, toUuid(neutronObject.getID()));
-            } else {
-                LOG.warn("Attempting to write neutron object {} without UUID", builderClass.getSimpleName());
-            }
-            if (neutronObject.getTenantID() != null && !neutronObject.getTenantID().isEmpty()) {
-                setTenantId.invoke(builder, toUuid(neutronObject.getTenantID()));
-            }
-            if (neutronObject.getProjectID() != null) {
-                setProjectId.invoke(builder, neutronObject.getTenantID());
-            }
-        } catch (IllegalAccessException | InvocationTargetException e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    protected <S1 extends INeutronBaseAttributes<S1>>
-        void fromMdIds(BaseAttributes baseAttributes, INeutronObject<S1> answer) {
-        if (baseAttributes.getUuid() != null) {
-            answer.setID(baseAttributes.getUuid().getValue());
-        }
-        if (baseAttributes.getTenantId() != null) {
-            answer.setTenantID(baseAttributes.getTenantId());
-        }
-        if (baseAttributes.getProjectId() != null) {
-            answer.setProjectID(baseAttributes.getProjectId());
-        }
-    }
-
-    protected <S1 extends INeutronBaseAttributes<S1>, M extends BaseAttributes, B extends Builder<M>>
-        void toMdBaseAttributes(S1 neutronObject, B builder) {
-        toMdIds(neutronObject, builder);
-        try {
-            if (neutronObject.getName() != null) {
-                setName.invoke(builder, neutronObject.getName());
-            }
-            if (neutronObject.getRevisionNumber() != null) {
-                setRevisionNumber.invoke(builder, neutronObject.getRevisionNumber());
-            }
-        } catch (IllegalAccessException | InvocationTargetException e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    protected <S1 extends INeutronBaseAttributes<S1>>
-        void fromMdBaseAttributes(BaseAttributes baseAttributes, S1 answer) {
-        fromMdIds(baseAttributes, answer);
-        if (baseAttributes.getName() != null) {
-            answer.setName(baseAttributes.getName());
-        }
-        if (baseAttributes.getRevisionNumber() != null) {
-            answer.setRevisionNumber(baseAttributes.getRevisionNumber());
-        }
-    }
-
-    protected <S1 extends INeutronAdminAttributes<S1>, M extends BaseAttributes & AdminAttributes, B extends Builder<M>>
-        void toMdAdminAttributes(S1 neutronObject, B builder) {
-        toMdBaseAttributes(neutronObject, builder);
-        try {
-            if (neutronObject.getAdminStateUp() != null) {
-                setAdminStateUp.invoke(builder, neutronObject.getAdminStateUp());
-            }
-            if (neutronObject.getStatus() != null) {
-                setStatus.invoke(builder, neutronObject.getStatus());
-            }
-        } catch (IllegalAccessException | InvocationTargetException e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    protected <M extends BaseAttributes & AdminAttributes, S1 extends INeutronAdminAttributes<S1>>
-        void fromMdAdminAttributes(M attr, S1 answer) {
-        fromMdBaseAttributes(attr, answer);
-        if (attr.isAdminStateUp() != null) {
-            answer.setAdminStateUp(attr.isAdminStateUp());
-        }
-        if (attr.getStatus() != null) {
-            answer.setStatus(attr.getStatus());
-        }
-    }
-
-    protected abstract T toMd(S neutronObject);
-
-    protected T toMd(String uuid) {
-        Builder<T> builder;
-        try {
-            builder = builderClass.newInstance();
-            setUuid.invoke(builder, toUuid(uuid));
-        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
-            // should not happen.
-            throw new IllegalArgumentException(e);
-        }
-        return builder.build();
-    }
-
-    protected abstract S fromMd(T dataObject);
-
-    private <W extends DataObject> W readMd(InstanceIdentifier<W> path, ReadTransaction tx) {
-        Preconditions.checkNotNull(tx);
-        W result = null;
-        final CheckedFuture<Optional<W>,
-                ReadFailedException> future = tx.read(LogicalDatastoreType.CONFIGURATION, path);
-        if (future != null) {
-            Optional<W> optional;
-            try {
-                optional = future.checkedGet();
-                if (optional.isPresent()) {
-                    result = optional.get();
-                }
-            } catch (final ReadFailedException e) {
-                LOG.warn("Failed to read {}", path, e);
-            }
-        }
-        return result;
-    }
-
-    protected <W extends DataObject> W readMd(InstanceIdentifier<W> path) {
-        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
-            return readMd(path, tx);
-        }
-    }
-
-    private void addMd(S neutronObject, WriteTransaction tx) throws InterruptedException, ExecutionException {
-        // TODO think about adding existence logic
-        updateMd(neutronObject, tx);
-    }
-
-    protected boolean addMd(S neutronObject) {
-        try {
-            final WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
-            addMd(neutronObject, tx);
-            return true;
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.warn("Transaction failed", e);
-        }
-        return false;
-    }
-
-    private void updateMd(S neutronObject, WriteTransaction tx) throws InterruptedException, ExecutionException {
-        Preconditions.checkNotNull(tx);
-
-        final T item = toMd(neutronObject);
-        final InstanceIdentifier<T> iid = createInstanceIdentifier(item);
-        tx.put(LogicalDatastoreType.CONFIGURATION, iid, item, true);
-        final CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
-        // Check if it's successfully committed, otherwise exception will be thrown.
-        future.get();
-    }
-
-    protected boolean updateMd(S neutronObject) {
-        int retries = RETRY_MAX;
-        while (retries-- >= 0) {
-            try {
-                final WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
-                updateMd(neutronObject, tx);
-                return true;
-            } catch (InterruptedException | ExecutionException e) {
-                if (e.getCause() instanceof OptimisticLockFailedException) {
-                    LOG.warn("Got OptimisticLockFailedException - {} {}", neutronObject, retries);
-                    continue;
-                }
-                // TODO: rethrow exception. don't mask exception
-                LOG.error("Transaction failed", e);
-            }
-            break;
-        }
-        return false;
-    }
-
-    private void removeMd(T item, WriteTransaction tx) throws InterruptedException, ExecutionException {
-        Preconditions.checkNotNull(tx);
-        final InstanceIdentifier<T> iid = createInstanceIdentifier(item);
-        tx.delete(LogicalDatastoreType.CONFIGURATION, iid);
-        final CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
-        // Check if it's successfully committed, otherwise exception will be thrown.
-        future.get();
-    }
-
-    protected boolean removeMd(T item) {
-        final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
-        try {
-            removeMd(item, tx);
-            return true;
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.warn("Transaction failed", e);
-        }
-        return false;
-    }
-
-    protected Uuid toUuid(String uuid) {
-        Preconditions.checkNotNull(uuid);
-        Uuid result;
-        try {
-            result = new Uuid(uuid);
-        } catch (final IllegalArgumentException e) {
-            // OK... someone didn't follow RFC 4122... lets try this the hard way
-            final String dedashed = uuid.replace("-", "");
-            if (dedashed.length() == DEDASHED_UUID_LENGTH) {
-                final String redashed = dedashed.substring(DEDASHED_UUID_START, DEDASHED_UUID_DIV1) + "-"
-                        + dedashed.substring(DEDASHED_UUID_DIV1, DEDASHED_UUID_DIV2) + "-"
-                        + dedashed.substring(DEDASHED_UUID_DIV2, DEDASHED_UUID_DIV3) + "-"
-                        + dedashed.substring(DEDASHED_UUID_DIV3, DEDASHED_UUID_DIV4) + "-"
-                        + dedashed.substring(DEDASHED_UUID_DIV4, DEDASHED_UUID_LENGTH);
-                result = new Uuid(redashed);
-            } else {
-                throw e;
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public void close() throws Exception {
-        // TODO Auto-generated method stub
-
-    }
-
-    private boolean exists(String uuid, ReadTransaction tx) {
-        Preconditions.checkNotNull(tx);
-        final T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), tx);
-        return dataObject != null;
-    }
-
-    @Override
-    public boolean exists(String uuid) {
-        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
-            return exists(uuid, tx);
-        }
-    }
-
-    private S get(String uuid, ReadTransaction tx) {
-        Preconditions.checkNotNull(tx);
-        final T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), tx);
-        if (dataObject == null) {
-            return null;
-        }
-        return fromMd(dataObject);
-    }
+public abstract class AbstractNeutronInterface<
+        T extends DataObject & Identifiable<K> & ChildOf<? super U>,
+        U extends ChildOf<? super Neutron> & Augmentable<U>,
+        K extends Identifier<T>,
+        S extends INeutronObject<S>>
+        extends AbstractTranscriberInterface<T, U, K, S, Neutron> {
 
     @Override
-    public S get(String uuid) {
-        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
-            return get(uuid, tx);
-        }
+    protected Class<Neutron> getMdParentClass(final Type[] types) {
+        return Neutron.class;
     }
 
-    protected abstract List<T> getDataObjectList(U dataObjects);
-
-    private List<S> getAll(ReadTransaction tx) {
-        Preconditions.checkNotNull(tx);
-        final Set<S> allNeutronObjects = new HashSet<>();
-        final U dataObjects = readMd(createInstanceIdentifier(), tx);
-        if (dataObjects != null) {
-            for (final T dataObject : getDataObjectList(dataObjects)) {
-                allNeutronObjects.add(fromMd(dataObject));
-            }
-        }
-        LOG.debug("Exiting _getAll, Found {} OpenStackFirewall", allNeutronObjects.size());
-        final List<S> ans = new ArrayList<>();
-        ans.addAll(allNeutronObjects);
-        return ans;
-    }
-
-    @Override
-    public List<S> getAll() {
-        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
-            return getAll(tx);
-        }
-    }
-
-    private boolean add(S input, ReadWriteTransaction tx) throws InterruptedException, ExecutionException {
-        Preconditions.checkNotNull(tx);
-        if (exists(input.getID(), tx)) {
-            tx.cancel();
-            return false;
-        }
-        addMd(input, tx);
-        return true;
-    }
-
-    @Override
-    public boolean add(S input) {
-        int retries = RETRY_MAX;
-        while (retries-- >= 0) {
-            final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
-            try {
-                return add(input, tx);
-            } catch (InterruptedException | ExecutionException e) {
-                if (e.getCause() instanceof OptimisticLockFailedException) {
-                    LOG.warn("Got OptimisticLockFailedException - {} {}", input, retries);
-                    continue;
-                }
-                // TODO: rethrow exception. don't mask exception
-                LOG.error("Transaction failed", e);
-            }
-            break;
-        }
-        return false;
-    }
-
-    private boolean remove(String uuid, ReadWriteTransaction tx) throws InterruptedException, ExecutionException {
-        Preconditions.checkNotNull(tx);
-        if (!exists(uuid, tx)) {
-            tx.cancel();
-            return false;
-        }
-        removeMd(toMd(uuid), tx);
-        return true;
-    }
-
-    @Override
-    public boolean remove(String uuid) {
-        int retries = RETRY_MAX;
-        while (retries-- >= 0) {
-            final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
-            try {
-                return remove(uuid, tx);
-            } catch (InterruptedException | ExecutionException e) {
-                if (e.getCause() instanceof OptimisticLockFailedException) {
-                    LOG.warn("Got OptimisticLockFailedException - {} {}", uuid, retries);
-                    continue;
-                }
-                // TODO: rethrow exception. don't mask exception
-                LOG.error("Transaction failed", e);
-            }
-            break;
-        }
-        return false;
-    }
-
-    private boolean update(String uuid, S delta, ReadWriteTransaction tx)
-            throws InterruptedException, ExecutionException {
-        Preconditions.checkNotNull(tx);
-        if (!exists(uuid, tx)) {
-            tx.cancel();
-            return false;
-        }
-        updateMd(delta, tx);
-        return true;
-    }
-
-    @Override
-    public boolean update(String uuid, S delta) {
-        int retries = RETRY_MAX;
-        while (retries-- >= 0) {
-            final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
-            try {
-                return update(uuid, delta, tx);
-            } catch (InterruptedException | ExecutionException e) {
-                if (e.getCause() instanceof OptimisticLockFailedException) {
-                    LOG.warn("Got OptimisticLockFailedException - {} {} {}", uuid, delta, retries);
-                    continue;
-                }
-                // TODO: rethrow exception. don't mask exception
-                LOG.error("Transaction failed", e);
-            }
-            break;
-        }
-        return false;
+    protected AbstractNeutronInterface(Class<? extends Builder<T>> builderClass, DataBroker db) {
+        super(builderClass, db);
     }
 }
diff --git a/transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractTranscriberInterface.java b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractTranscriberInterface.java
new file mode 100644 (file)
index 0000000..5060996
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.neutron.transcriber;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.neutron.spi.INeutronAdminAttributes;
+import org.opendaylight.neutron.spi.INeutronBaseAttributes;
+import org.opendaylight.neutron.spi.INeutronCRUD;
+import org.opendaylight.neutron.spi.INeutronObject;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.attrs.rev150712.AdminAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.attrs.rev150712.BaseAttributes;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class of Transcriber converts data from/to neutron spi to/from md-sal yang model.
+ *
+ * <pre>
+ * {@code
+ * V -> U -> T
+ *        K: key
+ *
+ *
+ * T(MD-SAL model) <-> S (neutron spi): Neutron northbound
+ *                  -> fromMd()
+ *                 <-  toMd()
+ * }
+ * </pre>
+ *
+ * <p>
+ * Example
+ * T: Port
+ * U: Ports
+ * K: PortKey
+ * S: NeutronPort
+ * V: Neutron
+ *
+ * <p>
+ * @param <T> Target yang model
+ * @param <U> parent of T
+ * @param <K> key type to indentify T
+ * @param <S> Neutron-spi class
+ * @param <V> parent of U
+ *
+ *
+ */
+public abstract class AbstractTranscriberInterface<
+        T extends DataObject & Identifiable<K> & ChildOf<? super U>,
+        U extends ChildOf<? super V> & Augmentable<U>,
+        K extends Identifier<T>, S extends INeutronObject<S>,
+        V extends DataObject>
+        implements AutoCloseable, INeutronCRUD<S> {
+    // T extends DataObject & Identifiable<K> & ChildOf<? super U> as 0th type argument
+    private static final int MD_LIST_CLASS_TYPE_INDEX = 0;
+    // U extends ChildOf<? super Neutron> & Augmentable<U> as 1st type argument
+    private static final int MD_CONTAINER_CLASS_TYPE_INDEX = 1;
+    // V extends DataObject as 4th type argument
+    private static final int MD_PARENT_CLASS_TYPE_INDEX = 4;
+    // S extends INeutronObject<S> as 3rd type argument
+    private static final int NEUTRON_OBJECT_TYPE_INDEX = 3;
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractTranscriberInterface.class);
+    private static final int DEDASHED_UUID_LENGTH = 32;
+    private static final int DEDASHED_UUID_START = 0;
+    private static final int DEDASHED_UUID_DIV1 = 8;
+    private static final int DEDASHED_UUID_DIV2 = 12;
+    private static final int DEDASHED_UUID_DIV3 = 16;
+    private static final int DEDASHED_UUID_DIV4 = 20;
+
+    private static final int RETRY_MAX = 2;
+
+    private final DataBroker db;
+
+    private final Class<V> mdParentClass;
+    private final Class<U> mdContainerClass;
+    private final Class<T> mdListClass;
+
+    // Unfortunately odl yangtools doesn't model yang model "uses" as
+    // class/interface hierarchy. So we need to resort to use reflection
+    // to call setter method.
+    private final Class<? extends Builder<T>> builderClass;
+    private final Method setUuid;
+    private final Method setTenantId;
+    private final Method setProjectId;
+    private final Method setName;
+    private final Method setAdminStateUp;
+    private final Method setStatus;
+    private final Method setRevisionNumber;
+
+    protected Class<V> getMdParentClass(final Type[] types) {
+        @SuppressWarnings("unchecked")
+        Class<V> localMdParentClass = (Class<V>) types[MD_PARENT_CLASS_TYPE_INDEX];
+        return localMdParentClass;
+    }
+
+    protected AbstractTranscriberInterface(Class<? extends Builder<T>> builderClass, DataBroker db) {
+        this.db = Preconditions.checkNotNull(db);
+        this.builderClass = builderClass;
+
+        ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
+        Type[] types = parameterizedType.getActualTypeArguments();
+        @SuppressWarnings("unchecked")
+        Class<T> localMdListClass = (Class<T>) types[MD_LIST_CLASS_TYPE_INDEX];
+        mdListClass = localMdListClass;
+        @SuppressWarnings("unchecked")
+        Class<U> localMdContainerClass = (Class<U>) types[MD_CONTAINER_CLASS_TYPE_INDEX];
+        mdContainerClass = localMdContainerClass;
+        mdParentClass = getMdParentClass(types);
+        @SuppressWarnings("unchecked")
+        Class<S> neutronObjectClass = (Class<S>) types[NEUTRON_OBJECT_TYPE_INDEX];
+        try {
+            setUuid = builderClass.getDeclaredMethod("setUuid", Uuid.class);
+            setTenantId = builderClass.getDeclaredMethod("setTenantId", Uuid.class);
+            if (INeutronBaseAttributes.class.isAssignableFrom(neutronObjectClass)) {
+                setName = builderClass.getDeclaredMethod("setName", String.class);
+                setProjectId = builderClass.getDeclaredMethod("setProjectId", String.class);
+                setRevisionNumber = builderClass.getDeclaredMethod("setRevisionNumber", Long.class);
+            } else {
+                setName = null;
+                setProjectId = null;
+                setRevisionNumber = null;
+            }
+
+            if (INeutronAdminAttributes.class.isAssignableFrom(neutronObjectClass)) {
+                setAdminStateUp = builderClass.getDeclaredMethod("setAdminStateUp", Boolean.class);
+                setStatus = builderClass.getDeclaredMethod("setStatus", String.class);
+            } else {
+                setAdminStateUp = null;
+                setStatus = null;
+            }
+        } catch (NoSuchMethodException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    public DataBroker getDataBroker() {
+        Preconditions.checkNotNull(db);
+        return db;
+    }
+
+    private InstanceIdentifier<T> createInstanceIdentifier(T item) {
+        return InstanceIdentifier.create(mdParentClass).child(mdContainerClass).child(mdListClass, item.getKey());
+    }
+
+    private InstanceIdentifier<U> createInstanceIdentifier() {
+        return InstanceIdentifier.create(mdParentClass).child(mdContainerClass);
+    }
+
+    protected <S1 extends INeutronBaseAttributes<S1>, M extends BaseAttributes, B extends Builder<M>>
+        void toMdIds(INeutronObject<S1> neutronObject, B builder) {
+        try {
+            if (neutronObject.getID() != null) {
+                setUuid.invoke(builder, toUuid(neutronObject.getID()));
+            } else {
+                LOG.warn("Attempting to write neutron object {} without UUID", builderClass.getSimpleName());
+            }
+            if (neutronObject.getTenantID() != null && !neutronObject.getTenantID().isEmpty()) {
+                setTenantId.invoke(builder, toUuid(neutronObject.getTenantID()));
+            }
+            if (neutronObject.getProjectID() != null) {
+                setProjectId.invoke(builder, neutronObject.getTenantID());
+            }
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    protected <S1 extends INeutronBaseAttributes<S1>>
+        void fromMdIds(BaseAttributes baseAttributes, INeutronObject<S1> answer) {
+        if (baseAttributes.getUuid() != null) {
+            answer.setID(baseAttributes.getUuid().getValue());
+        }
+        if (baseAttributes.getTenantId() != null) {
+            answer.setTenantID(baseAttributes.getTenantId());
+        }
+        if (baseAttributes.getProjectId() != null) {
+            answer.setProjectID(baseAttributes.getProjectId());
+        }
+    }
+
+    protected <S1 extends INeutronBaseAttributes<S1>, M extends BaseAttributes, B extends Builder<M>>
+        void toMdBaseAttributes(S1 neutronObject, B builder) {
+        toMdIds(neutronObject, builder);
+        try {
+            if (neutronObject.getName() != null) {
+                setName.invoke(builder, neutronObject.getName());
+            }
+            if (neutronObject.getRevisionNumber() != null) {
+                setRevisionNumber.invoke(builder, neutronObject.getRevisionNumber());
+            }
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    protected <S1 extends INeutronBaseAttributes<S1>>
+        void fromMdBaseAttributes(BaseAttributes baseAttributes, S1 answer) {
+        fromMdIds(baseAttributes, answer);
+        if (baseAttributes.getName() != null) {
+            answer.setName(baseAttributes.getName());
+        }
+        if (baseAttributes.getRevisionNumber() != null) {
+            answer.setRevisionNumber(baseAttributes.getRevisionNumber());
+        }
+    }
+
+    protected <S1 extends INeutronAdminAttributes<S1>, M extends BaseAttributes & AdminAttributes, B extends Builder<M>>
+        void toMdAdminAttributes(S1 neutronObject, B builder) {
+        toMdBaseAttributes(neutronObject, builder);
+        try {
+            if (neutronObject.getAdminStateUp() != null) {
+                setAdminStateUp.invoke(builder, neutronObject.getAdminStateUp());
+            }
+            if (neutronObject.getStatus() != null) {
+                setStatus.invoke(builder, neutronObject.getStatus());
+            }
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    protected <M extends BaseAttributes & AdminAttributes, S1 extends INeutronAdminAttributes<S1>>
+        void fromMdAdminAttributes(M attr, S1 answer) {
+        fromMdBaseAttributes(attr, answer);
+        if (attr.isAdminStateUp() != null) {
+            answer.setAdminStateUp(attr.isAdminStateUp());
+        }
+        if (attr.getStatus() != null) {
+            answer.setStatus(attr.getStatus());
+        }
+    }
+
+    protected abstract T toMd(S neutronObject);
+
+    protected T toMd(String uuid) {
+        Builder<T> builder;
+        try {
+            builder = builderClass.newInstance();
+            setUuid.invoke(builder, toUuid(uuid));
+        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+            // should not happen.
+            throw new IllegalArgumentException(e);
+        }
+        return builder.build();
+    }
+
+    protected abstract S fromMd(T dataObject);
+
+    private <W extends DataObject> W readMd(InstanceIdentifier<W> path, ReadTransaction tx) {
+        Preconditions.checkNotNull(tx);
+        W result = null;
+        final CheckedFuture<Optional<W>,
+                ReadFailedException> future = tx.read(LogicalDatastoreType.CONFIGURATION, path);
+        if (future != null) {
+            Optional<W> optional;
+            try {
+                optional = future.checkedGet();
+                if (optional.isPresent()) {
+                    result = optional.get();
+                }
+            } catch (final ReadFailedException e) {
+                LOG.warn("Failed to read {}", path, e);
+            }
+        }
+        return result;
+    }
+
+    protected <W extends DataObject> W readMd(InstanceIdentifier<W> path) {
+        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
+            return readMd(path, tx);
+        }
+    }
+
+    private void addMd(S neutronObject, WriteTransaction tx) throws InterruptedException, ExecutionException {
+        // TODO think about adding existence logic
+        updateMd(neutronObject, tx);
+    }
+
+    protected boolean addMd(S neutronObject) {
+        try {
+            final WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
+            addMd(neutronObject, tx);
+            return true;
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Transaction failed", e);
+        }
+        return false;
+    }
+
+    private void updateMd(S neutronObject, WriteTransaction tx) throws InterruptedException, ExecutionException {
+        Preconditions.checkNotNull(tx);
+
+        final T item = toMd(neutronObject);
+        final InstanceIdentifier<T> iid = createInstanceIdentifier(item);
+        tx.put(LogicalDatastoreType.CONFIGURATION, iid, item, true);
+        final CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
+        // Check if it's successfully committed, otherwise exception will be thrown.
+        future.get();
+    }
+
+    protected boolean updateMd(S neutronObject) {
+        int retries = RETRY_MAX;
+        while (retries-- >= 0) {
+            try {
+                final WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
+                updateMd(neutronObject, tx);
+                return true;
+            } catch (InterruptedException | ExecutionException e) {
+                if (e.getCause() instanceof OptimisticLockFailedException) {
+                    LOG.warn("Got OptimisticLockFailedException - {} {}", neutronObject, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOG.error("Transaction failed", e);
+            }
+            break;
+        }
+        return false;
+    }
+
+    private void removeMd(T item, WriteTransaction tx) throws InterruptedException, ExecutionException {
+        Preconditions.checkNotNull(tx);
+        final InstanceIdentifier<T> iid = createInstanceIdentifier(item);
+        tx.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        final CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
+        // Check if it's successfully committed, otherwise exception will be thrown.
+        future.get();
+    }
+
+    protected boolean removeMd(T item) {
+        final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+        try {
+            removeMd(item, tx);
+            return true;
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Transaction failed", e);
+        }
+        return false;
+    }
+
+    protected Uuid toUuid(String uuid) {
+        Preconditions.checkNotNull(uuid);
+        Uuid result;
+        try {
+            result = new Uuid(uuid);
+        } catch (final IllegalArgumentException e) {
+            // OK... someone didn't follow RFC 4122... lets try this the hard way
+            final String dedashed = uuid.replace("-", "");
+            if (dedashed.length() == DEDASHED_UUID_LENGTH) {
+                final String redashed = dedashed.substring(DEDASHED_UUID_START, DEDASHED_UUID_DIV1) + "-"
+                        + dedashed.substring(DEDASHED_UUID_DIV1, DEDASHED_UUID_DIV2) + "-"
+                        + dedashed.substring(DEDASHED_UUID_DIV2, DEDASHED_UUID_DIV3) + "-"
+                        + dedashed.substring(DEDASHED_UUID_DIV3, DEDASHED_UUID_DIV4) + "-"
+                        + dedashed.substring(DEDASHED_UUID_DIV4, DEDASHED_UUID_LENGTH);
+                result = new Uuid(redashed);
+            } else {
+                throw e;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void close() throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    private boolean exists(String uuid, ReadTransaction tx) {
+        Preconditions.checkNotNull(tx);
+        final T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), tx);
+        return dataObject != null;
+    }
+
+    @Override
+    public boolean exists(String uuid) {
+        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
+            return exists(uuid, tx);
+        }
+    }
+
+    private S get(String uuid, ReadTransaction tx) {
+        Preconditions.checkNotNull(tx);
+        final T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), tx);
+        if (dataObject == null) {
+            return null;
+        }
+        return fromMd(dataObject);
+    }
+
+    @Override
+    public S get(String uuid) {
+        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
+            return get(uuid, tx);
+        }
+    }
+
+    protected abstract List<T> getDataObjectList(U dataObjects);
+
+    private List<S> getAll(ReadTransaction tx) {
+        Preconditions.checkNotNull(tx);
+        final Set<S> allNeutronObjects = new HashSet<>();
+        final U dataObjects = readMd(createInstanceIdentifier(), tx);
+        if (dataObjects != null) {
+            for (final T dataObject : getDataObjectList(dataObjects)) {
+                allNeutronObjects.add(fromMd(dataObject));
+            }
+        }
+        LOG.debug("Exiting _getAll, Found {} OpenStackFirewall", allNeutronObjects.size());
+        final List<S> ans = new ArrayList<>();
+        ans.addAll(allNeutronObjects);
+        return ans;
+    }
+
+    @Override
+    public List<S> getAll() {
+        try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
+            return getAll(tx);
+        }
+    }
+
+    private boolean add(S input, ReadWriteTransaction tx) throws InterruptedException, ExecutionException {
+        Preconditions.checkNotNull(tx);
+        if (exists(input.getID(), tx)) {
+            tx.cancel();
+            return false;
+        }
+        addMd(input, tx);
+        return true;
+    }
+
+    @Override
+    public boolean add(S input) {
+        int retries = RETRY_MAX;
+        while (retries-- >= 0) {
+            final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+            try {
+                return add(input, tx);
+            } catch (InterruptedException | ExecutionException e) {
+                if (e.getCause() instanceof OptimisticLockFailedException) {
+                    LOG.warn("Got OptimisticLockFailedException - {} {}", input, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOG.error("Transaction failed", e);
+            }
+            break;
+        }
+        return false;
+    }
+
+    private boolean remove(String uuid, ReadWriteTransaction tx) throws InterruptedException, ExecutionException {
+        Preconditions.checkNotNull(tx);
+        if (!exists(uuid, tx)) {
+            tx.cancel();
+            return false;
+        }
+        removeMd(toMd(uuid), tx);
+        return true;
+    }
+
+    @Override
+    public boolean remove(String uuid) {
+        int retries = RETRY_MAX;
+        while (retries-- >= 0) {
+            final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+            try {
+                return remove(uuid, tx);
+            } catch (InterruptedException | ExecutionException e) {
+                if (e.getCause() instanceof OptimisticLockFailedException) {
+                    LOG.warn("Got OptimisticLockFailedException - {} {}", uuid, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOG.error("Transaction failed", e);
+            }
+            break;
+        }
+        return false;
+    }
+
+    private boolean update(String uuid, S delta, ReadWriteTransaction tx)
+            throws InterruptedException, ExecutionException {
+        Preconditions.checkNotNull(tx);
+        if (!exists(uuid, tx)) {
+            tx.cancel();
+            return false;
+        }
+        updateMd(delta, tx);
+        return true;
+    }
+
+    @Override
+    public boolean update(String uuid, S delta) {
+        int retries = RETRY_MAX;
+        while (retries-- >= 0) {
+            final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+            try {
+                return update(uuid, delta, tx);
+            } catch (InterruptedException | ExecutionException e) {
+                if (e.getCause() instanceof OptimisticLockFailedException) {
+                    LOG.warn("Got OptimisticLockFailedException - {} {} {}", uuid, delta, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOG.error("Transaction failed", e);
+            }
+            break;
+        }
+        return false;
+    }
+}