sort out signature of extraceField method
[neutron.git] / transcriber / src / main / java / org / opendaylight / neutron / transcriber / AbstractNeutronInterface.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.neutron.transcriber;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.CheckedFuture;
14 import java.lang.reflect.Method;
15 import java.util.ArrayList;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.concurrent.ExecutionException;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
23 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
27 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
28 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
29 import org.opendaylight.neutron.spi.INeutronCRUD;
30 import org.opendaylight.neutron.spi.INeutronObject;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
32 import org.opendaylight.yangtools.yang.binding.Augmentable;
33 import org.opendaylight.yangtools.yang.binding.ChildOf;
34 import org.opendaylight.yangtools.yang.binding.DataObject;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public abstract class AbstractNeutronInterface<T extends DataObject,
40         U extends ChildOf<? extends DataObject> & Augmentable<U>, S extends INeutronObject<S>>
41         implements AutoCloseable, INeutronCRUD<S> {
42     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNeutronInterface.class);
43     private static final int DEDASHED_UUID_LENGTH = 32;
44     private static final int DEDASHED_UUID_START = 0;
45     private static final int DEDASHED_UUID_DIV1 = 8;
46     private static final int DEDASHED_UUID_DIV2 = 12;
47     private static final int DEDASHED_UUID_DIV3 = 16;
48     private static final int DEDASHED_UUID_DIV4 = 20;
49
50     private static final int RETRY_MAX = 2;
51
52     private final DataBroker db;
53
54     AbstractNeutronInterface(DataBroker db) {
55         this.db = Preconditions.checkNotNull(db);
56     }
57
58     public DataBroker getDataBroker() {
59         Preconditions.checkNotNull(db);
60         return db;
61     }
62
63     protected abstract InstanceIdentifier<T> createInstanceIdentifier(T item);
64
65     protected abstract InstanceIdentifier<U> createInstanceIdentifier();
66
67     protected abstract T toMd(S neutronObject);
68
69     protected abstract T toMd(String uuid);
70
71     protected abstract S fromMd(T dataObject);
72
73     private <T extends DataObject> T readMd(InstanceIdentifier<T> path, ReadTransaction tx) {
74         Preconditions.checkNotNull(tx);
75         T result = null;
76         final CheckedFuture<Optional<T>,
77                 ReadFailedException> future = tx.read(LogicalDatastoreType.CONFIGURATION, path);
78         if (future != null) {
79             Optional<T> optional;
80             try {
81                 optional = future.checkedGet();
82                 if (optional.isPresent()) {
83                     result = optional.get();
84                 }
85             } catch (final ReadFailedException e) {
86                 LOGGER.warn("Failed to read {}", path, e);
87             }
88         }
89         return result;
90     }
91
92     protected <T extends DataObject> T readMd(InstanceIdentifier<T> path) {
93         try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
94             return readMd(path, tx);
95         }
96     }
97
98     private void addMd(S neutronObject, WriteTransaction tx) throws InterruptedException, ExecutionException {
99         // TODO think about adding existence logic
100         updateMd(neutronObject, tx);
101     }
102
103     protected boolean addMd(S neutronObject) {
104         try {
105             final WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
106             addMd(neutronObject, tx);
107             return true;
108         } catch (InterruptedException | ExecutionException e) {
109             LOGGER.warn("Transaction failed", e);
110         }
111         return false;
112     }
113
114     private void updateMd(S neutronObject, WriteTransaction tx) throws InterruptedException, ExecutionException {
115         Preconditions.checkNotNull(tx);
116
117         final T item = toMd(neutronObject);
118         final InstanceIdentifier<T> iid = createInstanceIdentifier(item);
119         tx.put(LogicalDatastoreType.CONFIGURATION, iid, item, true);
120         final CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
121         future.get(); // Check if it's successfuly committed, otherwise exception will be thrown.
122     }
123
124     protected boolean updateMd(S neutronObject) {
125         int retries = RETRY_MAX;
126         while (retries-- >= 0) {
127             try {
128                 final WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
129                 updateMd(neutronObject, tx);
130                 return true;
131             } catch (InterruptedException | ExecutionException e) {
132                 if (e.getCause() instanceof OptimisticLockFailedException) {
133                     LOGGER.warn("Got OptimisticLockFailedException - {} {}", neutronObject, retries);
134                     continue;
135                 }
136                 // TODO: rethrow exception. don't mask exception
137                 LOGGER.error("Transaction failed", e);
138             }
139             break;
140         }
141         return false;
142     }
143
144     private void removeMd(T item, WriteTransaction tx) throws InterruptedException, ExecutionException {
145         Preconditions.checkNotNull(tx);
146         final InstanceIdentifier<T> iid = createInstanceIdentifier(item);
147         tx.delete(LogicalDatastoreType.CONFIGURATION, iid);
148         final CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
149         future.get(); // Check if it's successfuly committed, otherwise exception will be thrown.
150     }
151
152     protected boolean removeMd(T item) {
153         final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
154         try {
155             removeMd(item, tx);
156             return true;
157         } catch (InterruptedException | ExecutionException e) {
158             LOGGER.warn("Transaction failed", e);
159         }
160         return false;
161     }
162
163     protected Uuid toUuid(String uuid) {
164         Preconditions.checkNotNull(uuid);
165         Uuid result;
166         try {
167             result = new Uuid(uuid);
168         } catch (final IllegalArgumentException e) {
169             // OK... someone didn't follow RFC 4122... lets try this the hard way
170             final String dedashed = uuid.replace("-", "");
171             if (dedashed.length() == DEDASHED_UUID_LENGTH) {
172                 final String redashed = dedashed.substring(DEDASHED_UUID_START, DEDASHED_UUID_DIV1) + "-"
173                         + dedashed.substring(DEDASHED_UUID_DIV1, DEDASHED_UUID_DIV2) + "-"
174                         + dedashed.substring(DEDASHED_UUID_DIV2, DEDASHED_UUID_DIV3) + "-"
175                         + dedashed.substring(DEDASHED_UUID_DIV3, DEDASHED_UUID_DIV4) + "-"
176                         + dedashed.substring(DEDASHED_UUID_DIV4, DEDASHED_UUID_LENGTH);
177                 result = new Uuid(redashed);
178             } else {
179                 throw e;
180             }
181         }
182         return result;
183     }
184
185     // this method uses reflection to update an object from it's delta.
186
187     protected boolean overwrite(Object target, Object delta) {
188         final Method[] methods = target.getClass().getMethods();
189
190         for (final Method toMethod : methods) {
191             if (toMethod.getDeclaringClass().equals(target.getClass()) && toMethod.getName().startsWith("set")) {
192
193                 final String toName = toMethod.getName();
194                 final String fromName = toName.replace("set", "get");
195
196                 try {
197                     final Method fromMethod = delta.getClass().getMethod(fromName);
198                     final Object value = fromMethod.invoke(delta, (Object[]) null);
199                     if (value != null) {
200                         toMethod.invoke(target, value);
201                     }
202                 } catch (final Exception e) {
203                     LOGGER.error("Error in overwrite", e);
204                     return false;
205                 }
206             }
207         }
208         return true;
209     }
210
211     @Override
212     public void close() throws Exception {
213         // TODO Auto-generated method stub
214
215     }
216
217     private boolean exists(String uuid, ReadTransaction tx) {
218         Preconditions.checkNotNull(tx);
219         final T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), tx);
220         return dataObject != null;
221     }
222
223     @Override
224     public boolean exists(String uuid) {
225         try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
226             return exists(uuid, tx);
227         }
228     }
229
230     private S get(String uuid, ReadTransaction tx) {
231         Preconditions.checkNotNull(tx);
232         final T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), tx);
233         if (dataObject == null) {
234             return null;
235         }
236         return fromMd(dataObject);
237     }
238
239     @Override
240     public S get(String uuid) {
241         try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
242             return get(uuid, tx);
243         }
244     }
245
246     protected abstract List<T> getDataObjectList(U dataObjects);
247
248     private List<S> getAll(ReadTransaction tx) {
249         Preconditions.checkNotNull(tx);
250         final Set<S> allNeutronObjects = new HashSet<S>();
251         final U dataObjects = readMd(createInstanceIdentifier(), tx);
252         if (dataObjects != null) {
253             for (final T dataObject : getDataObjectList(dataObjects)) {
254                 allNeutronObjects.add(fromMd(dataObject));
255             }
256         }
257         LOGGER.debug("Exiting _getAll, Found {} OpenStackFirewall", allNeutronObjects.size());
258         final List<S> ans = new ArrayList<S>();
259         ans.addAll(allNeutronObjects);
260         return ans;
261     }
262
263     @Override
264     public List<S> getAll() {
265         try (ReadOnlyTransaction tx = getDataBroker().newReadOnlyTransaction()) {
266             return getAll(tx);
267         }
268     }
269
270     private boolean add(S input, ReadWriteTransaction tx) throws InterruptedException, ExecutionException {
271         Preconditions.checkNotNull(tx);
272         if (exists(input.getID(), tx)) {
273             tx.cancel();
274             return false;
275         }
276         addMd(input, tx);
277         return true;
278     }
279
280     @Override
281     public boolean add(S input) {
282         int retries = RETRY_MAX;
283         while (retries-- >= 0) {
284             final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
285             try {
286                 return add(input, tx);
287             } catch (InterruptedException | ExecutionException e) {
288                 if (e.getCause() instanceof OptimisticLockFailedException) {
289                     LOGGER.warn("Got OptimisticLockFailedException - {} {}", input, retries);
290                     continue;
291                 }
292                 // TODO: rethrow exception. don't mask exception
293                 LOGGER.error("Transaction failed", e);
294             }
295             break;
296         }
297         return false;
298     }
299
300     private boolean remove(String uuid, ReadWriteTransaction tx) throws InterruptedException, ExecutionException {
301         Preconditions.checkNotNull(tx);
302         if (!exists(uuid, tx)) {
303             tx.cancel();
304             return false;
305         }
306         removeMd(toMd(uuid), tx);
307         return true;
308     }
309
310     @Override
311     public boolean remove(String uuid) {
312         int retries = RETRY_MAX;
313         while (retries-- >= 0) {
314             final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
315             try {
316                 return remove(uuid, tx);
317             } catch (InterruptedException | ExecutionException e) {
318                 if (e.getCause() instanceof OptimisticLockFailedException) {
319                     LOGGER.warn("Got OptimisticLockFailedException - {} {}", uuid, retries);
320                     continue;
321                 }
322                 // TODO: rethrow exception. don't mask exception
323                 LOGGER.error("Transaction failed", e);
324             }
325             break;
326         }
327         return false;
328     }
329
330     private boolean update(String uuid, S delta, ReadWriteTransaction tx)
331             throws InterruptedException, ExecutionException {
332         Preconditions.checkNotNull(tx);
333         if (!exists(uuid, tx)) {
334             tx.cancel();
335             return false;
336         }
337         updateMd(delta, tx);
338         return true;
339     }
340
341     @Override
342     public boolean update(String uuid, S delta) {
343         int retries = RETRY_MAX;
344         while (retries-- >= 0) {
345             final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
346             try {
347                 return update(uuid, delta, tx);
348             } catch (InterruptedException | ExecutionException e) {
349                 if (e.getCause() instanceof OptimisticLockFailedException) {
350                     LOGGER.warn("Got OptimisticLockFailedException - {} {} {}", uuid, delta, retries);
351                     continue;
352                 }
353                 // TODO: rethrow exception. don't mask exception
354                 LOGGER.error("Transaction failed", e);
355             }
356             break;
357         }
358         return false;
359     }
360
361     @Override
362     public boolean inUse(String uuid) {
363         return false;
364     }
365 }