Bug 3902 : Local variables to be declared final.
[neutron.git] / transcriber / src / main / java / org / opendaylight / neutron / transcriber / AbstractNeutronInterface.java
index 73bc5058afa03863ae7c35017789c8c7f9ce3002..c1374238cb563dab7061883c47fdffbec5c57f0f 100644 (file)
@@ -1,17 +1,34 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
 package org.opendaylight.neutron.transcriber;
 
 import java.lang.reflect.Method;
+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.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -21,7 +38,10 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.CheckedFuture;
 
-public abstract class AbstractNeutronInterface<T extends DataObject,S> implements AutoCloseable {
+import org.opendaylight.neutron.spi.INeutronCRUD;
+import org.opendaylight.neutron.spi.INeutronObject;
+
+public abstract class AbstractNeutronInterface<T extends DataObject, U extends ChildOf<? extends DataObject> & Augmentable<U>, S extends INeutronObject> implements AutoCloseable, INeutronCRUD<S> {
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNeutronInterface.class);
     private static final int DEDASHED_UUID_LENGTH = 32;
     private static final int DEDASHED_UUID_START = 0;
@@ -30,26 +50,33 @@ public abstract class AbstractNeutronInterface<T extends DataObject,S> implement
     private static final int DEDASHED_UUID_DIV3 = 16;
     private static final int DEDASHED_UUID_DIV4 = 20;
 
-    private DataBroker db;
+    private static final int RETRY_MAX = 2;
+
+    private final DataBroker db;
 
     AbstractNeutronInterface(ProviderContext providerContext) {
         this.db = providerContext.getSALService(DataBroker.class);
     }
 
     public DataBroker getDataBroker() {
+        Preconditions.checkNotNull(db);
         return db;
     }
 
     protected abstract InstanceIdentifier<T> createInstanceIdentifier(T item);
 
+    protected abstract InstanceIdentifier<U> createInstanceIdentifier();
+
     protected abstract T toMd(S neutronObject);
 
     protected abstract T toMd(String uuid);
 
-    protected <T extends org.opendaylight.yangtools.yang.binding.DataObject> T readMd(InstanceIdentifier<T> path) {
+    protected abstract S fromMd(T dataObject);
+
+    private <T extends DataObject> T readMd(InstanceIdentifier<T> path, ReadTransaction tx) {
+        Preconditions.checkNotNull(tx);
         T result = null;
-        final ReadOnlyTransaction transaction = getDataBroker().newReadOnlyTransaction();
-        CheckedFuture<Optional<T>, ReadFailedException> future = transaction.read(LogicalDatastoreType.CONFIGURATION, path);
+        final CheckedFuture<Optional<T>, ReadFailedException> future = tx.read(LogicalDatastoreType.CONFIGURATION, path);
         if (future != null) {
             Optional<T> optional;
             try {
@@ -57,46 +84,82 @@ public abstract class AbstractNeutronInterface<T extends DataObject,S> implement
                 if (optional.isPresent()) {
                     result = optional.get();
                 }
-            } catch (ReadFailedException e) {
+            } catch (final ReadFailedException e) {
                 LOGGER.warn("Failed to read {}", path, e);
             }
         }
-        transaction.close();
         return result;
     }
 
-    protected boolean addMd(S neutronObject) {
+    protected <T extends DataObject> T readMd(InstanceIdentifier<T> 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
-        return updateMd(neutronObject);
+        updateMd(neutronObject, tx);
     }
 
-    protected boolean updateMd(S neutronObject) {
-        WriteTransaction transaction = getDataBroker().newWriteOnlyTransaction();
-        T item = toMd(neutronObject);
-        InstanceIdentifier<T> iid = createInstanceIdentifier(item);
-        transaction.put(LogicalDatastoreType.CONFIGURATION, iid, item,true);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+    protected boolean addMd(S neutronObject) {
         try {
-            future.get();
+            final WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
+            addMd(neutronObject, tx);
+            return true;
         } catch (InterruptedException | ExecutionException e) {
-            LOGGER.warn("Transation failed ",e);
-            return false;
+            LOGGER.warn("Transaction failed", e);
         }
-        return true;
+        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();
+        future.get();   // Check if it's successfuly committed, otherwise exception will be thrown.
+    }
+
+    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) {
+                    LOGGER.warn("Got OptimisticLockFailedException - {} {}", neutronObject, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOGGER.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();
+        future.get();  // Check if it's successfuly committed, otherwise exception will be thrown.
     }
 
     protected boolean removeMd(T item) {
-        WriteTransaction transaction = getDataBroker().newWriteOnlyTransaction();
-        InstanceIdentifier<T> iid = createInstanceIdentifier(item);
-        transaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+        final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
         try {
-            future.get();
+            removeMd(item, tx);
+            return true;
         } catch (InterruptedException | ExecutionException e) {
-            LOGGER.warn("Transation failed ",e);
-            return false;
+            LOGGER.warn("Transaction failed", e);
         }
-        return true;
+        return false;
     }
 
     protected Uuid toUuid(String uuid) {
@@ -104,11 +167,11 @@ public abstract class AbstractNeutronInterface<T extends DataObject,S> implement
         Uuid result;
         try {
             result = new Uuid(uuid);
-        } catch(IllegalArgumentException e) {
+        } catch(final IllegalArgumentException e) {
             // OK... someone didn't follow RFC 4122... lets try this the hard way
-            String dedashed = uuid.replace("-", "");
+            final String dedashed = uuid.replace("-", "");
             if(dedashed.length() == DEDASHED_UUID_LENGTH) {
-                String redashed = dedashed.substring(DEDASHED_UUID_START, DEDASHED_UUID_DIV1)
+                final String redashed = dedashed.substring(DEDASHED_UUID_START, DEDASHED_UUID_DIV1)
                         + "-"
                         + dedashed.substring(DEDASHED_UUID_DIV1, DEDASHED_UUID_DIV2)
                         + "-"
@@ -128,22 +191,22 @@ public abstract class AbstractNeutronInterface<T extends DataObject,S> implement
     // this method uses reflection to update an object from it's delta.
 
     protected boolean overwrite(Object target, Object delta) {
-        Method[] methods = target.getClass().getMethods();
+        final Method[] methods = target.getClass().getMethods();
 
-        for(Method toMethod: methods){
+        for(final Method toMethod: methods){
             if(toMethod.getDeclaringClass().equals(target.getClass())
                     && toMethod.getName().startsWith("set")){
 
-                String toName = toMethod.getName();
-                String fromName = toName.replace("set", "get");
+                final String toName = toMethod.getName();
+                final String fromName = toName.replace("set", "get");
 
                 try {
-                    Method fromMethod = delta.getClass().getMethod(fromName);
-                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    final Method fromMethod = delta.getClass().getMethod(fromName);
+                    final Object value = fromMethod.invoke(delta, (Object[])null);
                     if(value != null){
                         toMethod.invoke(target, value);
                     }
-                } catch (Exception e) {
+                } catch (final Exception e) {
                     LOGGER.error("Error in overwrite", e);
                     return false;
                 }
@@ -158,4 +221,151 @@ public abstract class AbstractNeutronInterface<T extends DataObject,S> implement
 
     }
 
+    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<S>();
+        final U dataObjects = readMd(createInstanceIdentifier(), tx);
+        if (dataObjects != null) {
+            for (final T dataObject: getDataObjectList(dataObjects)) {
+                allNeutronObjects.add(fromMd(dataObject));
+            }
+        }
+        LOGGER.debug("Exiting _getAll, Found {} OpenStackFirewall", allNeutronObjects.size());
+        final List<S> ans = new ArrayList<S>();
+        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) {
+                    LOGGER.warn("Got OptimisticLockFailedException - {} {}", input, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOGGER.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) {
+                    LOGGER.warn("Got OptimisticLockFailedException - {} {}", uuid, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOGGER.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) {
+                    LOGGER.warn("Got OptimisticLockFailedException - {} {} {}", uuid, delta, retries);
+                    continue;
+                }
+                // TODO: rethrow exception. don't mask exception
+                LOGGER.error("Transaction failed", e);
+            }
+            break;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean inUse(String uuid) {
+        return false;
+    }
 }