2 * Copyright © 2016-2017 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.core.zusammen.plugin.dao.impl.cassandra;
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.ZusammenPluginConstants;
33 import org.openecomp.core.zusammen.plugin.dao.ElementRepository;
34 import org.openecomp.core.zusammen.plugin.dao.types.ElementEntity;
36 import java.lang.reflect.Type;
37 import java.nio.ByteBuffer;
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.List;
43 import java.util.Optional;
45 import java.util.TreeMap;
46 import java.util.stream.Collectors;
48 public class ElementRepositoryImpl implements ElementRepository {
51 public Map<Id, Id> listIds(SessionContext context, ElementEntityContext elementContext) {
53 if (elementContext.getRevisionId() == null) {
54 String revisionId = calculateLastRevisionId(context, elementContext);
55 if (revisionId == null) {
56 return new HashMap<>();
59 elementContext.setRevisionId(new Id(revisionId));
61 return getVersionElementIds(context, elementContext).entrySet().stream().collect(Collectors
62 .toMap(entry -> new Id(entry.getKey()), entry -> new Id(entry.getValue())));
64 /* return getVersionElementIds(context, elementContext).stream()
66 .collect(Collectors.toList());*/
71 public void create(SessionContext context, ElementEntityContext elementContext,
72 ElementEntity element) {
73 createElement(context, elementContext, element);
74 addElementToParent(context, elementContext, element);
78 public void update(SessionContext context, ElementEntityContext elementContext,
79 ElementEntity element) {
81 Id elementRevisionId = getElementRevision(context, elementContext, element.getId());
82 if (elementRevisionId.equals(elementContext.getRevisionId())) {
83 updateElement(context, elementContext, element);
85 createElement(context, elementContext, element);
90 public void delete(SessionContext context, ElementEntityContext elementContext,
91 ElementEntity element) {
92 removeElementFromParent(context, elementContext, element);
93 deleteElement(context, elementContext, element);
97 public Optional<ElementEntity> get(SessionContext context, ElementEntityContext elementContext,
98 ElementEntity element) {
99 String revisionId = calculateElementRevisionId(context, elementContext, element);
100 if (revisionId == null) {
101 return Optional.empty();
104 Row row = getElementAccessor(context).get(
105 elementContext.getSpace(),
106 elementContext.getItemId().toString(),
107 elementContext.getVersionId().toString(),
108 element.getId().toString(),
111 return row == null ? Optional.empty() : Optional.of(getElementEntity(element, row));
115 public Optional<ElementEntity> getDescriptor(SessionContext context,
116 ElementEntityContext elementContext,
117 ElementEntity element) {
118 String revisionId = calculateElementRevisionId(context, elementContext, element);
119 if (revisionId == null) {
120 return Optional.empty();
123 Row row = getElementAccessor(context).getDescriptor(
124 elementContext.getSpace(),
125 elementContext.getItemId().toString(),
126 elementContext.getVersionId().toString(),
127 element.getId().toString(),
130 return row == null ? Optional.empty() : Optional.of(getElementEntityDescriptor(element, row));
134 public void createNamespace(SessionContext context, ElementEntityContext elementContext,
135 ElementEntity element) {
136 getElementNamespaceAccessor(context).create(elementContext.getItemId().toString(),
137 element.getId().toString(),
138 element.getNamespace().toString());
142 public Optional<Id> getHash(SessionContext context, ElementEntityContext elementContext,
143 ElementEntity element) {
144 String revisionId = calculateElementRevisionId(context, elementContext, element);
145 if (revisionId == null) {
146 return Optional.empty();
149 Row row = getElementAccessor(context).getHash(
150 elementContext.getSpace(),
151 elementContext.getItemId().toString(),
152 elementContext.getVersionId().getValue(),
153 element.getId().toString(),
156 return row == null ? Optional.empty() : Optional.of(getElementHash(row));
159 private String calculateElementRevisionId(SessionContext context,
160 ElementEntityContext elementContext,
161 ElementEntity element) {
163 if (elementContext.getSpace().equals(ZusammenPluginConstants.PUBLIC_SPACE)) {
165 String versionRevision;
166 if (elementContext.getRevisionId() == null) {
167 versionRevision = calculateLastRevisionId(context, elementContext);
169 versionRevision = elementContext.getRevisionId().getValue();
172 elementContext.setRevisionId(new Id(versionRevision));
173 Map<String, String> elementIds = getVersionElementIds(context, elementContext);
174 if (elementIds.containsKey(element.getId().getValue())) {
175 return elementIds.get(element.getId().getValue());
181 return Id.ZERO.getValue();
185 private String calculateLastRevisionId(SessionContext context, ElementEntityContext
187 List<Row> rows = getVersionElementsAccessor(context).listRevisions(elementContext.getSpace(),
189 .getItemId().toString(), elementContext.getVersionId().toString()).all();
190 if (rows == null || rows.size() == 0) {
193 rows.sort((o1, o2) -> o1.getDate(VersionElementsField.PUBLISH_TIME)
194 .after(o2.getDate(VersionElementsField.PUBLISH_TIME)) ? -1 : 1);
195 return rows.get(0).getString(VersionElementsField.REVISION_ID);
198 /*private static String getVersionId(ElementEntityContext elementContext) {
199 return elementContext.getRevisionId() == null
200 ? elementContext.getVersionId().toString()
201 : elementContext.getRevisionId().getValue();
204 private ElementNamespaceAccessor getElementNamespaceAccessor(SessionContext context) {
205 return CassandraDaoUtils.getAccessor(context, ElementNamespaceAccessor.class);
208 private ElementAccessor getElementAccessor(SessionContext context) {
209 return CassandraDaoUtils.getAccessor(context, ElementAccessor.class);
212 private VersionElementsAccessor getVersionElementsAccessor(SessionContext context) {
213 return CassandraDaoUtils.getAccessor(context, VersionElementsAccessor.class);
216 private void createElement(SessionContext context, ElementEntityContext elementContext,
217 ElementEntity element) {
218 createElementRow(context, elementContext, element);
220 Map<String, String> elementIds = new TreeMap<>();
221 elementIds.put(element.getId().toString(), elementContext.getRevisionId().getValue());
222 getVersionElementsAccessor(context).addElements(
224 elementContext.getSpace(),
225 elementContext.getItemId().toString(),
226 elementContext.getVersionId().getValue(),
227 elementContext.getRevisionId().getValue());
230 private void createElementRow(SessionContext context, ElementEntityContext elementContext,
231 ElementEntity element) {
232 Set<String> subElementIds =
233 element.getSubElementIds().stream().map(Id::toString).collect(Collectors.toSet());
235 getElementAccessor(context).create(
236 elementContext.getSpace(),
237 elementContext.getItemId().toString(),
238 elementContext.getVersionId().getValue(),
239 element.getId().toString(),
240 elementContext.getRevisionId().getValue(),
241 element.getParentId() == null ? null : element.getParentId().toString(),
242 element.getNamespace() == null ? null : element.getNamespace().toString(),
243 JsonUtil.object2Json(element.getInfo()),
244 JsonUtil.object2Json(element.getRelations()),
246 element.getSearchableData(),
247 element.getVisualization(),
249 element.getElementHash().getValue());
252 private void updateElement(SessionContext context, ElementEntityContext elementContext,
253 ElementEntity element) {
256 if (element.getParentId() == null) {
257 getElementAccessor(context).update(
258 JsonUtil.object2Json(element.getInfo()),
259 JsonUtil.object2Json(element.getRelations()),
261 element.getSearchableData(),
262 element.getVisualization(),
263 element.getElementHash().getValue(),
264 elementContext.getSpace(),
265 elementContext.getItemId().toString(),
266 elementContext.getVersionId().toString(),
267 element.getId().toString(),
268 elementContext.getRevisionId().getValue());
270 getElementAccessor(context).update(
271 JsonUtil.object2Json(element.getInfo()),
272 JsonUtil.object2Json(element.getRelations()),
274 element.getSearchableData(),
275 element.getVisualization(),
276 element.getElementHash().getValue(),
277 element.getParentId().getValue(),
278 elementContext.getSpace(),
279 elementContext.getItemId().toString(),
280 elementContext.getVersionId().toString(),
281 element.getId().getValue(),
282 elementContext.getRevisionId().getValue());
285 Map<String, String> elementIds = new TreeMap<>();
286 elementIds.put(element.getId().getValue(), elementContext.getRevisionId().getValue());
287 getVersionElementsAccessor(context).addElements(
289 elementContext.getSpace(),
290 elementContext.getItemId().toString(),
291 elementContext.getVersionId().getValue(),
292 elementContext.getRevisionId().getValue());
295 private void deleteElement(SessionContext context, ElementEntityContext elementContext,
296 ElementEntity element) {
299 getElementAccessor(context).delete(
300 elementContext.getSpace(),
301 elementContext.getItemId().toString(),
302 elementContext.getVersionId().toString(),
303 element.getId().toString(),
304 elementContext.getRevisionId().getValue());
306 getVersionElementsAccessor(context).removeElements(
307 Collections.singleton(element.getId().toString()),
308 elementContext.getSpace(),
309 elementContext.getItemId().toString(),
310 elementContext.getVersionId().toString(),
311 elementContext.getRevisionId().getValue());
314 private void addElementToParent(SessionContext context, ElementEntityContext elementContext,
315 ElementEntity element) {
316 if (element.getParentId() == null) {
321 getElementAccessor(context).addSubElements(
322 Collections.singleton(element.getId().toString()),
323 elementContext.getSpace(),
324 elementContext.getItemId().toString(),
325 elementContext.getVersionId().toString(),
326 element.getParentId().toString(),
327 elementContext.getRevisionId().getValue());
329 Map<String, String> elementIds = new TreeMap<>();
330 elementIds.put(element.getParentId().toString(), elementContext.getRevisionId().getValue());
331 getVersionElementsAccessor(context).addElements(elementIds, elementContext.getSpace(),
332 elementContext.getItemId().getValue(), elementContext.getVersionId().getValue(),
333 elementContext.getRevisionId().getValue());
336 private void removeElementFromParent(SessionContext context, ElementEntityContext elementContext,
337 ElementEntity element) {
339 if (element.getParentId() == null) {
343 Optional<ElementEntity> parentElement =
344 get(context, elementContext, new ElementEntity(element.getParentId()));
345 if (!parentElement.isPresent()) {
348 getElementAccessor(context).removeSubElements(
349 Collections.singleton(element.getId().toString()),
350 elementContext.getSpace(),
351 elementContext.getItemId().toString(),
352 elementContext.getVersionId().toString(),
353 element.getParentId().toString(),
354 elementContext.getRevisionId().getValue());
356 getVersionElementsAccessor(context)
357 .removeElements(Collections.singleton(element.getId().toString()),
358 elementContext.getSpace(),
359 elementContext.getItemId().getValue(), elementContext.getVersionId().getValue(),
360 elementContext.getRevisionId().getValue());
362 Map<String, String> elementIds = new TreeMap<>();
363 elementIds.put(element.getParentId().toString(), elementContext.getRevisionId().getValue());
364 getVersionElementsAccessor(context).addElements(elementIds, elementContext.getSpace(),
365 elementContext.getItemId().getValue(), elementContext.getVersionId().getValue(),
366 elementContext.getRevisionId().getValue());
369 static ElementEntity getElementEntityDescriptor(ElementEntity element, Row row) {
370 element.setNamespace(getNamespace(row.getString(ElementField.NAMESPACE)));
371 element.setParentId(getParentId(row.getString(ElementField.PARENT_ID)));
372 element.setInfo(json2Object(row.getString(ElementField.INFO), Info.class));
373 element.setRelations(
374 json2Object(row.getString(ElementField.RELATIONS), new TypeToken<ArrayList<Relation>>() {
377 element.setSubElementIds(row.getSet(ElementField.SUB_ELEMENT_IDS, String.class)
378 .stream().map(Id::new).collect(Collectors.toSet()));
382 static ElementEntity getElementEntity(ElementEntity element, Row row) {
383 getElementEntityDescriptor(element, row);
385 element.setData(row.getBytes(ElementField.DATA));
386 element.setSearchableData(row.getBytes(ElementField.SEARCHABLE_DATA));
387 element.setVisualization(row.getBytes(ElementField.VISUALIZATION));
388 element.setElementHash(new Id(row.getString(ElementField.ELEMENT_HASH)));
392 private Id getElementHash(Row row) {
393 return new Id(row.getString(ElementField.ELEMENT_HASH));
396 private static Id getParentId(String parentIdStr) {
397 return parentIdStr == null ? null : new Id(parentIdStr);
400 private static Namespace getNamespace(String namespaceStr) {
401 Namespace namespace = new Namespace();
402 if (namespaceStr != null) {
403 namespace.setValue(namespaceStr);
408 private static <T> T json2Object(String json, Type typeOfT) {
409 return json == null ? null : JsonUtil.json2Object(json, typeOfT);
412 private Map<String, String> getVersionElementIds(SessionContext context,
413 ElementEntityContext elementContext) {
414 Row row = getVersionElementsAccessor(context).get(
415 elementContext.getSpace(),
416 elementContext.getItemId().toString(),
417 elementContext.getVersionId().getValue(),
418 elementContext.getRevisionId().getValue()).one();
421 : row.getMap(ElementRepositoryImpl.VersionElementsField.ELEMENT_IDS, String.class, String
425 private Id getElementRevision(SessionContext context, ElementEntityContext elementContext
427 Map<Id, Id> versionElementIds =
428 listIds(context, new ElementEntityContext
429 (elementContext.getSpace(), elementContext.getItemId(), elementContext.getVersionId(),
430 elementContext.getRevisionId()));
431 return versionElementIds.get(elementId);
437 CREATE TABLE IF NOT EXISTS element_namespace (
441 PRIMARY KEY (( item_id, element_id ))
445 interface ElementNamespaceAccessor {
446 @Query("UPDATE element_namespace SET namespace=:ns " +
447 "WHERE item_id=:item AND element_id=:id ")
448 void create(@Param("item") String itemId,
449 @Param("id") String elementId,
450 @Param("ns") String namespace);
454 interface ElementAccessor {
456 "UPDATE element SET parent_id=:parentId, namespace=:ns, info=:info, relations=:rels, " +
457 "data=:data, searchable_data=:searchableData, visualization=:visualization, " +
458 "sub_element_ids=sub_element_ids+:subs , element_hash=:elementHash " +
459 " WHERE space=:space AND item_id=:item AND version_id=:ver AND element_id=:id AND " +
461 void create(@Param("space") String space,
462 @Param("item") String itemId,
463 @Param("ver") String versionId,
464 @Param("id") String elementId,
465 @Param("rev") String revisionId,
466 @Param("parentId") String parentElementId,
467 @Param("ns") String namespace,
468 @Param("info") String info,
469 @Param("rels") String relations,
470 @Param("data") ByteBuffer data,
471 @Param("searchableData") ByteBuffer searchableData,
472 @Param("visualization") ByteBuffer visualization,
473 @Param("subs") Set<String> subElementIds,
474 @Param("elementHash") String elementHash);
477 @Query("UPDATE element SET info=?, relations=?, data=?, searchable_data=?, visualization=? ," +
478 "element_hash=? , parent_id=? " +
479 " WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
480 void update(String info, String relations, ByteBuffer data, ByteBuffer searchableData,
481 ByteBuffer visualization, String elementHash, String parentId, String space, String
483 versionId, String elementId, String revisionId);
485 @Query("UPDATE element SET info=?, relations=?, data=?, searchable_data=?, visualization=? ," +
487 " WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
488 void update(String info, String relations, ByteBuffer data, ByteBuffer searchableData,
489 ByteBuffer visualization, String elementHash, String space, String
491 versionId, String elementId, String revisionId);
494 "DELETE FROM element WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
495 void delete(String space, String itemId, String versionId, String elementId, String revisionId);
497 @Query("SELECT parent_id, namespace, info, relations, data, searchable_data, visualization, " +
498 "sub_element_ids,element_hash FROM element " +
499 "WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
500 ResultSet get(String space, String itemId, String versionId, String elementId, String
503 @Query("SELECT parent_id, namespace, info, relations, sub_element_ids FROM element " +
504 "WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
505 ResultSet getDescriptor(String space, String itemId, String versionId, String elementId,
508 @Query("UPDATE element SET sub_element_ids=sub_element_ids+? " +
509 " WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
510 void addSubElements(Set<String> subElementIds, String space, String itemId, String versionId,
511 String elementId, String revisionId);
513 @Query("UPDATE element SET sub_element_ids=sub_element_ids-? " +
514 " WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
515 void removeSubElements(Set<String> subElementIds, String space, String itemId, String versionId,
516 String elementId, String revisionId);
518 @Query("SELECT element_hash FROM element " +
519 "WHERE space=? AND item_id=? AND version_id=? AND element_id=? AND revision_id=? ")
520 ResultSet getHash(String space, String itemId, String versionId, String elementId, String
524 private static final class ElementField {
525 private static final String NAMESPACE = "namespace";
526 private static final String PARENT_ID = "parent_id";
527 private static final String INFO = "info";
528 private static final String RELATIONS = "relations";
529 private static final String DATA = "data";
530 private static final String SEARCHABLE_DATA = "searchable_data";
531 private static final String VISUALIZATION = "visualization";
532 private static final String SUB_ELEMENT_IDS = "sub_element_ids";
533 private static final String ELEMENT_HASH = "element_hash";
537 interface VersionElementsAccessor {
539 @Query("UPDATE version_elements SET element_ids=element_ids+ ? " +
540 "WHERE space=? AND item_id=? AND version_id=? AND revision_id=? ")
541 void addElements(Map<String, String> elementIds, String space, String itemId, String versionId,
542 String versionRevisionId);
544 @Query("UPDATE version_elements SET element_ids=element_ids-? " +
545 "WHERE space=? AND item_id=? AND version_id=? AND revision_id=?")
546 void removeElements(Set<String> elementIds, String space, String itemId, String versionId,
550 "SELECT element_ids FROM version_elements WHERE space=? AND item_id=? AND version_id=? AND revision_id=? ")
551 ResultSet get(String space, String itemId, String versionId, String revisionId);
554 "SELECT revision_id,publish_time FROM version_elements WHERE space=? AND item_id=? AND " +
556 ResultSet listRevisions(String space, String itemId, String versionId);
560 private static final class VersionElementsField {
561 private static final String ELEMENT_IDS = "element_ids";
562 private static final String REVISION_ID = "revision_id";
563 private static final String PUBLISH_TIME = "publish_time";