Merge "Bug 7848: Allow neutron port create with security disabled."
[neutron.git] / northbound-api / src / main / java / org / opendaylight / neutron / northbound / api / AbstractNeutronNorthbound.java
index 7577ad7e8ec0771ed0473e08d7ff516df9d9a410..cad9f32bff528145225684678e54d441346c59f3 100644 (file)
@@ -8,16 +8,27 @@
 
 package org.opendaylight.neutron.northbound.api;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.ParameterizedType;
 import java.net.HttpURLConnection;
 import java.util.List;
 import javax.ws.rs.core.Response;
 import org.opendaylight.neutron.spi.INeutronCRUD;
 import org.opendaylight.neutron.spi.INeutronObject;
+import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class AbstractNeutronNorthbound<T extends INeutronObject<T>, NeutronRequest extends INeutronRequest<T>,
+public abstract class AbstractNeutronNorthbound<T extends INeutronObject<T>, R extends INeutronRequest<T>,
         I extends INeutronCRUD<T>> {
+    // T extends INeutronObject<T> as 0th type argument
+    private static final int NEUTRON_ARGUMENT_TYPE_INDEX = 0;
+    // NeutronRequest extends INeutronRequest<T> as 1st type argument
+    private static final int NEUTRON_REQUEST_TYPE_INDEX = 1;
+    // I extends INeutronCRUD<T> as 2nd type argument
+    private static final int NEUTRON_CRUD_TYPE_INDEX = 2;
+
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNeutronNorthbound.class);
 
     protected static final int HTTP_OK_BOTTOM = 200;
@@ -36,9 +47,40 @@ public abstract class AbstractNeutronNorthbound<T extends INeutronObject<T>, Neu
 
     protected abstract String getResourceName();
 
-    protected abstract NeutronRequest newNeutronRequest(T o);
+    private <K> Class<K> getActualTypeArgument(final int typeIndex) {
+        ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
+        @SuppressWarnings("unchecked")
+        Class<K> cls = (Class<K>) parameterizedType.getActualTypeArguments()[typeIndex];
+        return cls;
+    }
+
+    private R newNeutronRequest(T neutronObject) {
+        // return new R(neutronObject);
 
-    protected abstract I getNeutronCRUD();
+        // argumentClass = T.class
+        Class<T> argumentClass = getActualTypeArgument(NEUTRON_ARGUMENT_TYPE_INDEX);
+        // cls = NeturonRequest.class
+        Class<R> cls = getActualTypeArgument(NEUTRON_REQUEST_TYPE_INDEX);
+        try {
+            // ctor = R constructor
+            Constructor<R> ctor = cls.getDeclaredConstructor(argumentClass);
+            return ctor.newInstance(neutronObject);
+        } catch (NoSuchMethodException | InstantiationException
+                 | IllegalAccessException | InvocationTargetException e) {
+            // This case shouldn't happen
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    protected I getNeutronCRUD() {
+        // cls = I.class
+        Class<I> cls = getActualTypeArgument(NEUTRON_CRUD_TYPE_INDEX);
+        I neutronCrud = NeutronCRUDInterfaces.fetchINeutronCRUD(cls, (Object) this);
+        if (neutronCrud == null) {
+            throw new ServiceUnavailableException(serviceUnavailable());
+        }
+        return neutronCrud;
+    }
 
     protected Response show(String uuid,
             // return fields
@@ -57,7 +99,7 @@ public abstract class AbstractNeutronNorthbound<T extends INeutronObject<T>, Neu
         }
     }
 
-    protected Response create(final NeutronRequest input) {
+    protected Response create(final R input) {
         I neutronCRUD = getNeutronCRUD();
         if (input.isSingleton()) {
             T singleton = input.getSingleton();
@@ -79,7 +121,7 @@ public abstract class AbstractNeutronNorthbound<T extends INeutronObject<T>, Neu
     protected void updateDelta(String uuid, T delta, T original) {
     }
 
-    protected Response update(String uuid, final NeutronRequest input) {
+    protected Response update(String uuid, final R input) {
         I neutronCRUD = getNeutronCRUD();
         if (!input.isSingleton()) {
             throw new BadRequestException("Only singleton edit supported");
@@ -107,15 +149,7 @@ public abstract class AbstractNeutronNorthbound<T extends INeutronObject<T>, Neu
         /*
          * remove it and return 204 status
          */
-        final String resourceName = getResourceName();
-        boolean exist = false;
-        try {
-            exist = neutronCRUD.remove(uuid);
-        } catch (Exception e) {
-            LOGGER.debug("exception during remove {} {} {}", resourceName, uuid, e);
-            throw new InternalServerErrorException("Could not delete " + resourceName);
-        }
-        if (!exist) {
+        if (!neutronCRUD.remove(uuid)) {
             throw new ResourceNotFoundException(uuidNoExist());
         }