move aai-client into its own project
[so.git] / graph-inventory / aai-client / src / main / java / org / onap / so / client / graphinventory / entities / uri / SimpleBaseUri.java
1 package org.onap.so.client.graphinventory.entities.uri;
2
3 import java.io.IOException;
4 import java.io.ObjectInputStream;
5 import java.io.ObjectOutputStream;
6 import java.net.URI;
7 import java.nio.charset.StandardCharsets;
8 import java.util.Arrays;
9 import java.util.HashMap;
10 import java.util.Map;
11 import java.util.Set;
12 import java.util.stream.Collectors;
13 import java.util.stream.Stream;
14 import javax.ws.rs.core.UriBuilder;
15 import org.apache.commons.lang3.builder.HashCodeBuilder;
16 import org.apache.commons.lang3.builder.ToStringBuilder;
17 import org.apache.commons.lang3.builder.ToStringStyle;
18 import org.onap.so.client.graphinventory.Format;
19 import org.onap.so.client.graphinventory.GraphInventoryObjectBase;
20 import org.onap.so.client.graphinventory.entities.uri.parsers.UriParser;
21 import org.onap.so.client.graphinventory.entities.uri.parsers.UriParserSpringImpl;
22 import org.onap.so.client.graphinventory.exceptions.IncorrectNumberOfUriKeys;
23 import org.springframework.web.util.UriUtils;
24
25 public abstract class SimpleBaseUri<T extends GraphInventoryResourceUri<?, ?>, Parent extends GraphInventorySingleResourceUri<?, ?, ?, ?>, S extends GraphInventoryObjectBase>
26         implements GraphInventoryResourceUri<T, S> {
27
28     private static final long serialVersionUID = -1011069933894179423L;
29     protected transient UriBuilder internalURI;
30     protected static final String relationshipAPI = "/relationship-list/relationship";
31     protected static final String relatedTo = "/related-to";
32     protected Object[] values;
33     protected final S type;
34     protected final Parent parentUri;
35     protected final Map<String, Set<String>> queryParams = new HashMap<>();
36
37     protected SimpleBaseUri(S type, Object... values) {
38         this.type = type;
39         this.internalURI = UriBuilder.fromPath(this.getTemplate(type));
40         this.values = values;
41         this.parentUri = null;
42         validateValuesSize(this.getTemplate(type), values);
43     }
44
45     protected SimpleBaseUri(S type, URI uri) {
46         if (!type.passThrough()) {
47             this.type = type;
48             this.internalURI = UriBuilder.fromPath(this.getTemplate(type));
49             this.values =
50                     this.getURIKeys(uri.getRawPath().replaceAll(getPrefixPattern().toString(), "")).values().toArray();
51             this.parentUri = null;
52         } else {
53             this.type = type;
54             this.internalURI = UriBuilder.fromPath(uri.getRawPath().replaceAll(getPrefixPattern().toString(), ""));
55             this.values = new Object[0];
56             this.parentUri = null;
57         }
58
59     }
60
61     protected SimpleBaseUri(S type, UriBuilder builder, Object... values) {
62         this.internalURI = builder;
63         this.values = values;
64         this.type = type;
65         this.parentUri = null;
66
67     }
68
69     protected SimpleBaseUri(Parent parentUri, S childType, Object... childValues) {
70         this.type = childType;
71         this.internalURI = UriBuilder.fromUri(type.partialUri());
72         this.values = childValues;
73         this.parentUri = parentUri;
74
75         validateValuesSize(childType.partialUri(), values);
76     }
77
78     protected SimpleBaseUri(SimpleBaseUri<T, Parent, S> copy) {
79         this.type = copy.type;
80         this.internalURI = copy.internalURI.clone();
81         this.values = copy.values.clone();
82         if (copy.parentUri != null) {
83             this.parentUri = (Parent) copy.parentUri.clone();
84         } else {
85             this.parentUri = null;
86         }
87     }
88
89     protected void setInternalURI(UriBuilder builder) {
90         this.internalURI = builder;
91     }
92
93     @Override
94     public T queryParam(String name, String... values) {
95         this.internalURI = internalURI.queryParam(name, values);
96         if (queryParams.containsKey(name)) {
97             queryParams.get(name).addAll(Arrays.asList(values));
98         } else {
99             queryParams.put(name, Stream.of(values).collect(Collectors.toSet()));
100         }
101         return (T) this;
102     }
103
104     @Override
105     public T replaceQueryParam(String name, String... values) {
106         this.internalURI = internalURI.replaceQueryParam(name, values);
107         queryParams.put(name, Stream.of(values).collect(Collectors.toSet()));
108         return (T) this;
109     }
110
111     @Override
112     public T resultIndex(int index) {
113         this.internalURI = internalURI.replaceQueryParam("resultIndex", index);
114         return (T) this;
115     }
116
117     @Override
118     public T resultSize(int size) {
119         this.internalURI = internalURI.replaceQueryParam("resultSize", size);
120         return (T) this;
121     }
122
123     @Override
124     public T limit(int size) {
125         this.resultIndex(0).resultSize(size);
126         return (T) this;
127     }
128
129     @Override
130     public URI build() {
131         return build(this.values);
132     }
133
134     protected URI build(Object... values) {
135
136         // This is a workaround because resteasy does not encode URIs correctly
137         final String[] encoded = new String[values.length];
138         for (int i = 0; i < values.length; i++) {
139             encoded[i] = UriUtils.encode(values[i].toString(), StandardCharsets.UTF_8.toString());
140         }
141         if (this.parentUri != null) {
142             return UriBuilder
143                     .fromUri(this.parentUri.build().toString() + internalURI.buildFromEncoded(encoded).toString())
144                     .build();
145         } else {
146             return internalURI.buildFromEncoded(encoded);
147         }
148     }
149
150     @Override
151     public Map<String, String> getURIKeys() {
152         return this.getURIKeys(this.build().toString());
153     }
154
155     protected Map<String, String> getURIKeys(String uri) {
156         UriParser parser;
157         if (!("".equals(this.getTemplate(type)))) {
158             parser = new UriParserSpringImpl(this.getTemplate(type));
159         } else {
160             return new HashMap<>();
161         }
162
163
164         return parser.parse(uri);
165     }
166
167     @Override
168     public abstract T clone();
169
170     @Override
171     public S getObjectType() {
172         return this.type;
173     }
174
175     @Override
176     public boolean equals(Object o) {
177         if (o != null) {
178             return this.toString().equals(o.toString());
179         }
180         return false;
181     }
182
183     @Override
184     public int hashCode() {
185         return new HashCodeBuilder().append(this.toString()).toHashCode();
186     }
187
188
189     @Override
190     public T depth(Depth depth) {
191         this.internalURI.replaceQueryParam("depth", depth.toString());
192         return (T) this;
193     }
194
195     @Override
196     public T nodesOnly(boolean nodesOnly) {
197         if (nodesOnly) {
198             this.internalURI.replaceQueryParam("nodes-only", "");
199         }
200         return (T) this;
201     }
202
203     @Override
204     public T format(Format format) {
205         this.internalURI.replaceQueryParam("format", format);
206         return (T) this;
207     }
208
209     public void validateValuesSize(String template, Object... values) {
210         UriParser parser = new UriParserSpringImpl(template);
211         Set<String> variables = parser.getVariables();
212         if (variables.size() != values.length) {
213             throw new IncorrectNumberOfUriKeys(String.format("Expected %s variables: %s", variables.size(), variables));
214         }
215     }
216
217     protected String getTemplate(GraphInventoryObjectBase type) {
218         return type.uriTemplate();
219     }
220
221     private void writeObject(ObjectOutputStream oos) throws IOException {
222         oos.defaultWriteObject();
223         oos.writeUTF(this.internalURI.toTemplate());
224     }
225
226     private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
227         ois.defaultReadObject();
228         String uri = ois.readUTF();
229         this.setInternalURI(UriBuilder.fromUri(uri));
230     }
231
232     @Override
233     public String toString() {
234         return new ToStringBuilder(null, ToStringStyle.NO_CLASS_NAME_STYLE).append("type", type)
235                 .append("parentUri", parentUri).append("values", values).append("queryParams", queryParams).toString();
236     }
237 }