HONEYCOMB-431: add validation support to Writers
[honeycomb.git] / infra / translate-impl / src / main / java / io / fd / honeycomb / translate / impl / write / GenericListWriter.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 static io.fd.honeycomb.translate.impl.write.GenericWriter.isUpdateSupported;
20
21 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
22 import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
23 import io.fd.honeycomb.translate.util.RWUtils;
24 import io.fd.honeycomb.translate.util.write.AbstractGenericWriter;
25 import io.fd.honeycomb.translate.write.ListWriter;
26 import io.fd.honeycomb.translate.write.Validator;
27 import io.fd.honeycomb.translate.write.WriteContext;
28 import io.fd.honeycomb.translate.write.WriteFailedException;
29 import javax.annotation.Nonnull;
30 import org.opendaylight.yangtools.yang.binding.DataObject;
31 import org.opendaylight.yangtools.yang.binding.Identifiable;
32 import org.opendaylight.yangtools.yang.binding.Identifier;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34
35 /**
36  * Generic list node writer with customizable behavior thanks to injected customizer.
37  */
38 public final class GenericListWriter<D extends DataObject & Identifiable<K>, K extends Identifier<D>> extends
39         AbstractGenericWriter<D> implements ListWriter<D, K> {
40
41     private final WriterCustomizer<D> customizer;
42
43     public GenericListWriter(@Nonnull final InstanceIdentifier<D> type,
44                              @Nonnull final ListWriterCustomizer<D, K> customizer) {
45         super(type, isUpdateSupported(customizer));
46         this.customizer = customizer;
47     }
48
49     public GenericListWriter(@Nonnull final InstanceIdentifier<D> type,
50                              @Nonnull final ListWriterCustomizer<D, K> customizer,
51                              @Nonnull final Validator<D> validator) {
52         super(type, isUpdateSupported(customizer), validator);
53         this.customizer = customizer;
54     }
55
56     @Override
57     protected void writeCurrentAttributes(@Nonnull final InstanceIdentifier<D> id, @Nonnull final D data,
58                                           @Nonnull final WriteContext ctx) throws WriteFailedException {
59         try {
60             customizer.writeCurrentAttributes(id, data, ctx);
61         } catch (RuntimeException e) {
62             throw new WriteFailedException.CreateFailedException(id, data, e);
63         }
64     }
65
66     @Override
67     protected void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<D> id, @Nonnull final D dataBefore,
68                                            @Nonnull final WriteContext ctx) throws WriteFailedException {
69         try {
70             customizer.deleteCurrentAttributes(id, dataBefore, ctx);
71         } catch (RuntimeException e) {
72             throw new WriteFailedException.DeleteFailedException(id, e);
73         }
74     }
75
76     @Override
77     protected void updateCurrentAttributes(@Nonnull final InstanceIdentifier<D> id, @Nonnull final D dataBefore,
78                                            @Nonnull final D dataAfter, @Nonnull final WriteContext ctx)
79         throws WriteFailedException {
80         try {
81             customizer.updateCurrentAttributes(id, dataBefore, dataAfter, ctx);
82         } catch (RuntimeException e) {
83             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
84         }
85     }
86
87     @Override
88     protected void writeCurrent(final InstanceIdentifier<D> id, final D data, final WriteContext ctx)
89         throws WriteFailedException {
90         super.writeCurrent(getManagedId(id, data), data, ctx);
91     }
92
93     @Override
94     protected void updateCurrent(final InstanceIdentifier<D> id, final D dataBefore, final D dataAfter,
95                                  final WriteContext ctx) throws WriteFailedException {
96         super.updateCurrent(getManagedId(id, dataBefore), dataBefore, dataAfter, ctx);
97     }
98
99     @Override
100     protected void deleteCurrent(final InstanceIdentifier<D> id, final D dataBefore, final WriteContext ctx)
101         throws WriteFailedException {
102         super.deleteCurrent(getManagedId(id, dataBefore), dataBefore, ctx);
103     }
104
105     @Override
106     protected InstanceIdentifier<D> getManagedId(@Nonnull final InstanceIdentifier<? extends DataObject> currentId,
107                                                  @Nonnull final D current) {
108         final InstanceIdentifier<D> id = (InstanceIdentifier<D>) currentId;
109         // Make sure the key is present
110         if (isWildcarded(id)) {
111             return getSpecificId(id, current);
112         } else {
113             return id;
114         }
115     }
116
117     private boolean isWildcarded(final InstanceIdentifier<D> id) {
118         return id.firstIdentifierOf(getManagedDataObjectType().getTargetType()).isWildcarded();
119     }
120
121     private InstanceIdentifier<D> getSpecificId(final InstanceIdentifier<D> currentId, final D current) {
122         return RWUtils.replaceLastInId(currentId,
123             new InstanceIdentifier.IdentifiableItem<>(currentId.getTargetType(), current.getKey()));
124     }
125 }