HONEYCOMB-431: add validation support to Writers
[honeycomb.git] / infra / translate-impl / src / main / java / io / fd / honeycomb / translate / impl / write / GenericWriter.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.translate.impl.write;
18
19 import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
20 import io.fd.honeycomb.translate.util.write.AbstractGenericWriter;
21 import io.fd.honeycomb.translate.write.Validator;
22 import io.fd.honeycomb.translate.write.WriteContext;
23 import io.fd.honeycomb.translate.write.WriteFailedException;
24 import javax.annotation.Nonnull;
25 import org.opendaylight.yangtools.yang.binding.DataObject;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Generic writer with customizable behavior thanks to injected customizer.
32  */
33 public final class GenericWriter<D extends DataObject> extends AbstractGenericWriter<D> {
34
35     private static final Logger LOG = LoggerFactory.getLogger(GenericWriter.class);
36     private static final String UPDATE_M = "updateCurrentAttributes";
37     private final WriterCustomizer<D> customizer;
38
39     public GenericWriter(@Nonnull final InstanceIdentifier<D> type,
40                          @Nonnull final WriterCustomizer<D> customizer) {
41         super(type, isUpdateSupported(customizer));
42         this.customizer = customizer;
43     }
44
45     public GenericWriter(@Nonnull final InstanceIdentifier<D> type,
46                          @Nonnull final WriterCustomizer<D> customizer,
47                          @Nonnull final Validator<D> validator) {
48         super(type, isUpdateSupported(customizer), validator);
49         this.customizer = customizer;
50     }
51
52     static boolean isUpdateSupported(final @Nonnull WriterCustomizer<?> customizer) {
53         try {
54             // if customizer overrides updateCurrentAttributes method, it will be used, otherwise updates will be broken into individual
55             // delete + create pairs
56             final Class<? extends WriterCustomizer> customizerClass = customizer.getClass();
57             final Class<?> updateDeclaringClass = customizerClass
58                     .getMethod(UPDATE_M, InstanceIdentifier.class, DataObject.class, DataObject.class, WriteContext.class)
59                     .getDeclaringClass();
60             final boolean supportsUpdate = !WriterCustomizer.class.equals(updateDeclaringClass);
61             LOG.debug("Customizer {} update support : {}|Update declaring class {}", customizerClass, supportsUpdate,
62                     updateDeclaringClass);
63             return supportsUpdate;
64         } catch (NoSuchMethodException e) {
65             throw new IllegalStateException("Unable to detect if customizer supports update", e);
66         }
67     }
68
69     @Override
70     protected void writeCurrentAttributes(@Nonnull final InstanceIdentifier<D> id, @Nonnull final D data,
71                                           @Nonnull final WriteContext ctx) throws WriteFailedException {
72         try {
73             customizer.writeCurrentAttributes(id, data, ctx);
74         } catch (RuntimeException e) {
75             throw new WriteFailedException.CreateFailedException(id, data, e);
76         }
77     }
78
79     @Override
80     protected void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<D> id, @Nonnull final D dataBefore,
81                                            @Nonnull final WriteContext ctx) throws WriteFailedException {
82         try {
83             customizer.deleteCurrentAttributes(id, dataBefore, ctx);
84         } catch (RuntimeException e) {
85             throw new WriteFailedException.DeleteFailedException(id, e);
86         }
87     }
88
89     @Override
90     protected void updateCurrentAttributes(@Nonnull final InstanceIdentifier<D> id,
91                                            @Nonnull final D dataBefore,
92                                            @Nonnull final D dataAfter,
93                                            @Nonnull final WriteContext ctx) throws WriteFailedException {
94         try {
95             customizer.updateCurrentAttributes(id, dataBefore, dataAfter, ctx);
96         } catch (RuntimeException e) {
97             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
98         }
99     }
100 }