Create plugin point for csar generation
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / ComponentCache.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.tosca;
21
22 import static org.openecomp.sdc.be.utils.CommonBeUtils.compareAsdcComponentVersions;
23
24 import io.vavr.collection.HashMap;
25 import io.vavr.collection.Map;
26 import io.vavr.collection.Stream;
27 import java.util.function.BiConsumer;
28 import java.util.function.BinaryOperator;
29 import lombok.EqualsAndHashCode;
30 import lombok.Getter;
31 import org.apache.commons.lang3.tuple.ImmutableTriple;
32 import org.openecomp.sdc.be.model.Component;
33
34 /**
35  * Provides caching abilities for components
36  */
37 public final class ComponentCache {
38     // TODO: Make this final whenever possible. The current code using the class
39
40     private final BinaryOperator<CacheEntry> merge;
41     // does not allow this.
42     private Map<String, CacheEntry> entries = HashMap.empty();
43
44     private ComponentCache(BinaryOperator<CacheEntry> merge) {
45         this.merge = merge;
46     }
47
48     /**
49      * Creates an overwritable cache based on a merging strategy
50      *
51      * @param merge The strategy used to merge two values which keys are the same
52      */
53     public static ComponentCache overwritable(BinaryOperator<CacheEntry> merge) {
54         return new ComponentCache(merge);
55     }
56
57     /**
58      * Creates a cached entry
59      *
60      * @param id        The id of the entry
61      * @param fileName  the filename of the entry
62      * @param component the cached component
63      */
64     public static CacheEntry entry(String id, String fileName, Component component) {
65         return new CacheEntry(id, fileName, component);
66     }
67
68     /**
69      * Decorate the cache with a listener called whenever a value is merged
70      *
71      * @param bc the consumer called when a value is merged
72      */
73     public ComponentCache onMerge(BiConsumer<CacheEntry, CacheEntry> bc) {
74         return new ComponentCache((oldValue, newValue) -> {
75             CacheEntry value = merge.apply(oldValue, newValue);
76             if (value.equals(newValue)) {
77                 bc.accept(oldValue, newValue);
78             }
79             return value;
80         });
81     }
82
83     // For now we'll keep this as is, to prevent the refactoring to be too big
84     public Iterable<ImmutableTriple<String, String, Component>> iterable() {
85         return all().map(e -> new ImmutableTriple<>(e.id, e.fileName, e.component));
86     }
87
88     /**
89      * Streams all the entries stored in the cache
90      */
91     public Stream<CacheEntry> all() {
92         return entries.values().toStream();
93     }
94     // TODO: Encapsulate the cache and expose functions to interact with it
95
96     /**
97      * Tells if an entry has been cached for a specific key
98      *
99      * @param key The key used to index the entry
100      */
101     public boolean notCached(String key) {
102         return !entries.get(key).isDefined();
103     }
104
105     /**
106      * Store an entry in the cache. Keep in mind that currently this mutates the cache and does not work in a referentially transparent way (This
107      * should be fixed whenever possible).
108      *
109      * @param id        The id of the entry
110      * @param fileName  the filename of the entry
111      * @param component the cached component
112      */
113     public ComponentCache put(String id, String fileName, Component component) {
114         String uuid = component.getInvariantUUID();
115         CacheEntry entry = new CacheEntry(id, fileName, component);
116         // TODO: Make the entries final whenever possible. The current code using the class does not allow this
117         entries = entries.put(uuid, entry, merge);
118         return this;
119     }
120
121     public interface MergeStrategy {
122
123         /**
124          * A strategy designed to favour the latest component version when merging two cached entries
125          */
126         static BinaryOperator<CacheEntry> overwriteIfSameVersions() {
127             return (oldValue, newValue) -> compareAsdcComponentVersions(newValue.getComponentVersion(), oldValue.getComponentVersion()) ? newValue
128                 : oldValue;
129         }
130     }
131
132     /**
133      * Entry stored by the cache
134      */
135     @EqualsAndHashCode
136     @Getter
137     public static final class CacheEntry {
138
139         final String id;
140         final String fileName;
141         final Component component;
142
143         CacheEntry(String id, String fileName, Component component) {
144             this.id = id;
145             this.fileName = fileName;
146             this.component = component;
147         }
148
149         public String getComponentVersion() {
150             return component.getVersion();
151         }
152     }
153 }