fix incorrect dependency
[sdc.git] / openecomp-be / lib / openecomp-core-lib / openecomp-zusammen-lib / openecomp-zusammen-plugin / src / main / java / org / openecomp / core / zusammen / plugin / dao / impl / CassandraElementRepository.java
1 /*
2  * Copyright © 2016-2017 European Support Limited
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 org.openecomp.core.zusammen.plugin.dao.impl;
18
19 import com.amdocs.zusammen.datatypes.Id;
20 import com.amdocs.zusammen.datatypes.Namespace;
21 import com.amdocs.zusammen.datatypes.SessionContext;
22 import com.amdocs.zusammen.datatypes.item.Info;
23 import com.amdocs.zusammen.datatypes.item.Relation;
24 import com.amdocs.zusammen.plugin.statestore.cassandra.dao.types.ElementEntityContext;
25 import com.amdocs.zusammen.utils.fileutils.json.JsonUtil;
26 import com.datastax.driver.core.ResultSet;
27 import com.datastax.driver.core.Row;
28 import com.datastax.driver.mapping.annotations.Accessor;
29 import com.datastax.driver.mapping.annotations.Param;
30 import com.datastax.driver.mapping.annotations.Query;
31 import com.google.gson.reflect.TypeToken;
32 import org.openecomp.core.zusammen.plugin.dao.ElementRepository;
33 import org.openecomp.core.zusammen.plugin.dao.types.ElementEntity;
34
35 import java.lang.reflect.Type;
36 import java.nio.ByteBuffer;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.HashSet;
41 import java.util.Optional;
42 import java.util.Set;
43 import java.util.stream.Collectors;
44
45 public class CassandraElementRepository implements ElementRepository {
46
47   private static final String VERSION_ELEMENT_NOT_EXIST_ERROR_MSG =
48       "List version elements error: " +
49           "element %s, which appears as an element of item %s version %s, does not exist";
50
51   @Override
52   public Collection<ElementEntity> list(SessionContext context,
53                                         ElementEntityContext elementContext) {
54     Set<String> elementIds = getVersionElementIds(context, elementContext);
55
56     Collection<ElementEntity> elements = new ArrayList<>();
57     for (String elementId : elementIds) {
58       elements.add(get(context, elementContext, new ElementEntity(new Id(elementId)))
59           .orElseThrow(
60               () -> new IllegalStateException(String.format(VERSION_ELEMENT_NOT_EXIST_ERROR_MSG,
61                   elementId, elementContext.getItemId().getValue(),
62                   getVersionId(elementContext)))));
63     }
64     return elements;
65   }
66
67   @Override
68   public void create(SessionContext context, ElementEntityContext elementContext,
69                      ElementEntity element) {
70     createElement(context, elementContext, element);
71     addElementToParent(context, elementContext, element);
72   }
73
74   @Override
75   public void update(SessionContext context, ElementEntityContext elementContext,
76                      ElementEntity element) {
77     updateElement(context, elementContext, element);
78   }
79
80   @Override
81   public void delete(SessionContext context, ElementEntityContext elementContext,
82                      ElementEntity element) {
83     removeElementFromParent(context, elementContext, element);
84     deleteElement(context, elementContext, element);
85   }
86
87   @Override
88   public Optional<ElementEntity> get(SessionContext context, ElementEntityContext elementContext,
89                                      ElementEntity element) {
90     Row row = getElementAccessor(context).get(
91         elementContext.getSpace(),
92         elementContext.getItemId().toString(),
93         getVersionId(elementContext),
94         element.getId().toString()).one();
95
96     return row == null ? Optional.empty() : Optional.of(getElementEntity(element, row));
97   }
98
99   @Override
100   public void createNamespace(SessionContext context, ElementEntityContext elementContext,
101                               ElementEntity element) {
102     getElementNamespaceAccessor(context).create(
103         elementContext.getSpace(),
104         elementContext.getItemId().toString(),
105         element.getId().toString(),
106         element.getNamespace().toString());
107   }
108
109   @Override
110   public boolean checkHealth(SessionContext context) {
111     ResultSet resultSet = getVersionElementsAccessor(context).checkHealth();
112     return resultSet.getColumnDefinitions().contains("element_ids");
113   }
114
115   private String getVersionId(ElementEntityContext elementContext) {
116     return elementContext.getChangeRef() == null
117         ? elementContext.getVersionId().toString()
118         : elementContext.getChangeRef();
119   }
120
121   private ElementNamespaceAccessor getElementNamespaceAccessor(SessionContext context) {
122     return CassandraDaoUtils.getAccessor(context, ElementNamespaceAccessor.class);
123   }
124
125   private ElementAccessor getElementAccessor(SessionContext context) {
126     return CassandraDaoUtils.getAccessor(context, ElementAccessor.class);
127   }
128
129   private VersionElementsAccessor getVersionElementsAccessor(SessionContext context) {
130     return CassandraDaoUtils.getAccessor(context, VersionElementsAccessor.class);
131   }
132
133   private void createElement(SessionContext context, ElementEntityContext elementContext,
134                              ElementEntity element) {
135     Set<String> subElementIds =
136         element.getSubElementIds().stream().map(Id::toString).collect(Collectors.toSet());
137     String versionId = getVersionId(elementContext);
138
139     getElementAccessor(context).create(
140         elementContext.getSpace(),
141         elementContext.getItemId().toString(),
142         versionId,
143         element.getId().toString(),
144         element.getParentId().toString(),
145         element.getNamespace().toString(),
146         JsonUtil.object2Json(element.getInfo()),
147         JsonUtil.object2Json(element.getRelations()),
148         element.getData(),
149         element.getSearchableData(),
150         element.getVisualization(),
151         subElementIds);
152
153     getVersionElementsAccessor(context).addElements(
154         Collections.singleton(element.getId().toString()),
155         elementContext.getSpace(),
156         elementContext.getItemId().toString(),
157         versionId);
158   }
159
160   private void updateElement(SessionContext context, ElementEntityContext elementContext,
161                              ElementEntity element) {
162     getElementAccessor(context).update(
163         JsonUtil.object2Json(element.getInfo()),
164         JsonUtil.object2Json(element.getRelations()),
165         element.getData(),
166         element.getSearchableData(),
167         element.getVisualization(),
168         elementContext.getSpace(),
169         elementContext.getItemId().toString(),
170         elementContext.getVersionId().toString(),
171         element.getId().toString());
172   }
173
174   private void deleteElement(SessionContext context, ElementEntityContext elementContext,
175                              ElementEntity element) {
176     String versionId = getVersionId(elementContext);
177
178     getElementAccessor(context).delete(
179         elementContext.getSpace(),
180         elementContext.getItemId().toString(),
181         versionId,
182         element.getId().toString());
183
184     getVersionElementsAccessor(context).removeElements(
185         Collections.singleton(element.getId().toString()),
186         elementContext.getSpace(),
187         elementContext.getItemId().toString(),
188         versionId);
189   }
190
191   private void addElementToParent(SessionContext context, ElementEntityContext elementContext,
192                                   ElementEntity element) {
193     getElementAccessor(context).addSubElements(
194         Collections.singleton(element.getId().toString()),
195         elementContext.getSpace(),
196         elementContext.getItemId().toString(),
197         getVersionId(elementContext),
198         element.getParentId().toString());
199   }
200
201   private void removeElementFromParent(SessionContext context, ElementEntityContext elementContext,
202                                        ElementEntity element) {
203     if (element.getParentId() == null) {
204       return;
205     }
206     getElementAccessor(context).removeSubElements(
207         Collections.singleton(element.getId().toString()),
208         elementContext.getSpace(),
209         elementContext.getItemId().toString(),
210         getVersionId(elementContext),
211         element.getParentId().toString());
212   }
213
214   private ElementEntity getElementEntity(ElementEntity element, Row row) {
215     element.setNamespace(getNamespace(row.getString(ElementField.NAMESPACE)));
216     element.setParentId(new Id(row.getString(ElementField.PARENT_ID)));
217     element.setInfo(json2Object(row.getString(ElementField.INFO), Info.class));
218     element.setRelations(
219         json2Object(row.getString(ElementField.RELATIONS), new TypeToken<ArrayList<Relation>>() {
220         }.getType()));
221     element.setData(row.getBytes(ElementField.DATA));
222     element.setSearchableData(row.getBytes(ElementField.SEARCHABLE_DATA));
223     element.setVisualization(row.getBytes(ElementField.VISUALIZATION));
224     element.setSubElementIds(row.getSet(ElementField.SUB_ELEMENT_IDS, String.class)
225         .stream().map(Id::new).collect(Collectors.toSet()));
226     return element;
227   }
228
229   private Namespace getNamespace(String namespaceStr) {
230     Namespace namespace = new Namespace();
231     if (namespaceStr != null) {
232       namespace.setValue(namespaceStr);
233     }
234     return namespace;
235   }
236
237   private static <T> T json2Object(String json, Type typeOfT) {
238     return json == null ? null : JsonUtil.json2Object(json, typeOfT);
239   }
240
241   private Set<String> getVersionElementIds(SessionContext context,
242                                            ElementEntityContext elementContext) {
243     Row row = getVersionElementsAccessor(context).get(
244         elementContext.getSpace(),
245         elementContext.getItemId().toString(),
246         getVersionId(elementContext)).one();
247     return row == null
248         ? new HashSet<>()
249         : row.getSet(CassandraElementRepository.VersionElementsField.ELEMENT_IDS, String.class);
250   }
251
252   /*
253 CREATE TABLE IF NOT EXISTS element_namespace (
254         space text,
255         item_id text,
256         element_id text,
257         namespace text,
258         PRIMARY KEY (( space, item_id, element_id ))
259 );
260    */
261   @Accessor
262   interface ElementNamespaceAccessor {
263     @Query(
264         "UPDATE element_namespace SET namespace=:ns " +
265             "WHERE space=:space AND item_id=:item AND element_id=:id ")
266     void create(@Param("space") String space,
267                 @Param("item") String itemId,
268                 @Param("id") String elementId,
269                 @Param("ns") String namespace);
270   }
271
272   /*
273 CREATE TABLE IF NOT EXISTS element (
274         space text,
275         item_id text,
276         version_id text,
277         element_id text,
278         parent_id text,
279         namespace text,
280         info text,
281         relations text,
282         data blob,
283         searchable_data blob,
284         visualization blob,
285         sub_element_ids set<text>,
286         PRIMARY KEY (( space, item_id, version_id, element_id ))
287 );
288    */
289   @Accessor
290   interface ElementAccessor {
291     @Query(
292         "UPDATE element SET parent_id=:parentId, namespace=:ns, info=:info, relations=:rels, " +
293             "data=:data, searchable_data=:searchableData, visualization=:visualization, " +
294             "sub_element_ids=sub_element_ids+:subs " +
295             "WHERE space=:space AND item_id=:item AND version_id=:ver AND element_id=:id ")
296     void create(@Param("space") String space,
297                 @Param("item") String itemId,
298                 @Param("ver") String versionId,
299                 @Param("id") String elementId,
300                 @Param("parentId") String parentElementId,
301                 @Param("ns") String namespace,
302                 @Param("info") String info,
303                 @Param("rels") String relations,
304                 @Param("data") ByteBuffer data,
305                 @Param("searchableData") ByteBuffer searchableData,
306                 @Param("visualization") ByteBuffer visualization,
307                 @Param("subs") Set<String> subElementIds);
308
309     @Query("UPDATE element SET info=?, relations=?, data=?, searchable_data=?, visualization=?" +
310         " WHERE space=? AND item_id=? AND version_id=? AND element_id=?  ")
311     void update(String info, String relations, ByteBuffer data, ByteBuffer searchableData,
312                 ByteBuffer visualization, String space, String itemId, String versionId,
313                 String elementId);
314
315     @Query("DELETE FROM element WHERE space=? AND item_id=? AND version_id=? AND element_id=?")
316     void delete(String space, String itemId, String versionId, String elementId);
317
318     @Query("SELECT parent_id, namespace, info, relations, data, searchable_data, visualization, " +
319         "sub_element_ids FROM element " +
320         "WHERE space=? AND item_id=? AND version_id=? AND element_id=? ")
321     ResultSet get(String space, String itemId, String versionId, String elementId);
322
323     @Query("UPDATE element SET sub_element_ids=sub_element_ids+? " +
324         " WHERE space=? AND item_id=? AND version_id=? AND element_id=?  ")
325     void addSubElements(Set<String> subElementIds, String space, String itemId, String versionId,
326                         String elementId);
327
328     @Query("UPDATE element SET sub_element_ids=sub_element_ids-? " +
329         " WHERE space=? AND item_id=? AND version_id=? AND element_id=? ")
330     void removeSubElements(Set<String> subElementIds, String space, String itemId, String versionId,
331                            String elementId);
332   }
333
334   private static final class ElementField {
335     private static final String NAMESPACE = "namespace";
336     private static final String PARENT_ID = "parent_id";
337     private static final String INFO = "info";
338     private static final String RELATIONS = "relations";
339     private static final String DATA = "data";
340     private static final String SEARCHABLE_DATA = "searchable_data";
341     private static final String VISUALIZATION = "visualization";
342     private static final String SUB_ELEMENT_IDS = "sub_element_ids";
343   }
344
345   /*
346   CREATE TABLE IF NOT EXISTS version_elements (
347     space text,
348     item_id text,
349     version_id text,
350     element_ids set<text>,
351     PRIMARY KEY (( space, item_id, version_id ))
352   );
353    */
354   @Accessor
355   interface VersionElementsAccessor {
356
357     @Query("UPDATE version_elements SET element_ids=element_ids+? " +
358         "WHERE space=? AND item_id=? AND version_id=?")
359     void addElements(Set<String> elementIds, String space, String itemId, String versionId);
360
361     @Query("UPDATE version_elements SET element_ids=element_ids-? " +
362         "WHERE space=? AND item_id=? AND version_id=?")
363     void removeElements(Set<String> elementIds, String space, String itemId, String versionId);
364
365     @Query("SELECT element_ids FROM version_elements WHERE space=? AND item_id=? AND version_id=?")
366     ResultSet get(String space, String itemId, String versionId);
367
368     @Query("SELECT element_ids FROM version_elements LIMIT 1")
369     ResultSet checkHealth();
370   }
371
372   private static final class VersionElementsField {
373     private static final String ELEMENT_IDS = "element_ids";
374   }
375 }