Auto-resolve edge type
[aai/gizmo.git] / src / main / java / org / onap / schema / RelationshipSchema.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.schema;
22
23
24 import java.io.IOException;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.stream.Collectors;
30 import javax.ws.rs.core.Response.Status;
31 import org.codehaus.jackson.map.ObjectMapper;
32 import org.onap.aai.edges.EdgeRule;
33 import org.onap.crud.exception.CrudException;
34 import com.google.common.collect.Multimap;
35
36
37 public class RelationshipSchema {
38
39   public static final String SCHEMA_SOURCE_NODE_TYPE = "from";
40   public static final String SCHEMA_TARGET_NODE_TYPE = "to";
41   public static final String SCHEMA_RELATIONSHIP_TYPE = "label";
42   public static final String SCHEMA_MULTIPLICITY_TYPE = "multiplicity";
43   public static final String SCHEMA_RULES_ARRAY = "rules";
44
45   private Map<String, Map<String, Class<?>>> relations = new HashMap<>();
46   /**
47    * Hashmap of valid relationship types along with properties.
48    */
49   private Map<String, Map<String, Class<?>>> relationTypes  = new HashMap<>();
50
51   private Map<String, EdgeRule> relationshipRules = new HashMap<>();
52   
53   // A map storing the list of valid edge types for a source/target pair
54   private Map<String, Set<String>> edgeTypesForNodePair = new HashMap<>();
55   
56
57   @SuppressWarnings("unchecked")
58   public RelationshipSchema(Multimap<String, EdgeRule> rules, String props) throws CrudException, IOException {
59     HashMap<String, String> properties = new ObjectMapper().readValue(props, HashMap.class);
60
61     // hold the true values of the edge rules by key - convert to java 8
62     for (EdgeRule rule : rules.values()) {
63       String key = buildRelation(rule.getFrom(), rule.getTo(), rule.getLabel());
64       relationshipRules.put(key, rule);
65       
66       String nodePairKey = buildNodePairKey(rule.getFrom(), rule.getTo());
67       if (edgeTypesForNodePair.get(nodePairKey) == null) {
68         Set<String> typeSet = new HashSet<String>();
69         typeSet.add(rule.getLabel());
70         edgeTypesForNodePair.put(nodePairKey, typeSet);
71       }
72       else {
73         edgeTypesForNodePair.get(nodePairKey).add(rule.getLabel());
74       }
75     }
76
77     Map<String, Class<?>> edgeProps = properties.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p -> {
78       try {
79         return resolveClass(p.getValue());
80       } catch (CrudException | ClassNotFoundException e) {
81         e.printStackTrace();
82       }
83       return null;
84     }));
85
86     rules.entries ().forEach ( (kv) -> {
87       relationTypes.put(kv.getValue ().getLabel (), edgeProps);
88       relations.put (buildRelation ( kv.getValue ().getFrom (), kv.getValue ().getTo (), kv.getValue ().getLabel ()), edgeProps);
89     });
90   }
91
92   public Map<String, Class<?>> lookupRelation(String key) {
93     return this.relations.get(key);
94   }
95
96   /**
97    * Extract the multiplicity type from the Edge rules
98    *
99    * @param key
100    * @return
101    * @throws CrudException
102    */
103   public String lookupRelationMultiplicity(String key) throws CrudException {
104     EdgeRule edgeRule = relationshipRules.get(key);
105
106     if (edgeRule == null) {
107       throw new CrudException("Invalid source/target/relationship type: " + key, Status.BAD_REQUEST);
108     }
109
110     if (edgeRule.getMultiplicityRule() != null) {
111       return edgeRule.getMultiplicityRule().toString();
112     }
113
114     return null;
115   }
116
117   public Map<String, Class<?>> lookupRelationType(String type) {
118     return this.relationTypes.get(type);
119   }
120
121   public boolean isValidType(String type) {
122     return relationTypes.containsKey(type);
123   }
124
125   public Set<String> getValidRelationTypes(String source, String target) {
126     Set<String> typeList = edgeTypesForNodePair.get(buildNodePairKey(source, target));
127
128     if (typeList == null) {
129       return new HashSet<String>();
130     }
131     
132     return typeList;
133   }
134   
135   private String buildRelation(String source, String target, String relation) {
136     return source + ":" + target + ":" + relation;
137   }
138   
139   private String buildNodePairKey(String source, String target) {
140     return source + ":" + target;
141   }
142
143   private Class<?> resolveClass(String type) throws CrudException, ClassNotFoundException {
144     Class<?> clazz = Class.forName(type);
145     validateClassTypes(clazz);
146     return clazz;
147   }
148
149   private void validateClassTypes(Class<?> clazz) throws CrudException {
150     if (!clazz.isAssignableFrom(Integer.class) && !clazz.isAssignableFrom(Double.class)
151             && !clazz.isAssignableFrom(Boolean.class) && !clazz.isAssignableFrom(String.class)) {
152       throw new CrudException("", Status.BAD_REQUEST);
153     }
154   }
155 }