2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 package org.onap.aai.util;
23 import java.util.HashMap;
24 import java.util.Iterator;
26 import java.util.Properties;
27 import java.util.UUID;
29 import org.apache.tinkerpop.gremlin.structure.Direction;
30 import org.apache.tinkerpop.gremlin.structure.Edge;
31 import org.apache.tinkerpop.gremlin.structure.Graph;
32 import org.apache.tinkerpop.gremlin.structure.Vertex;
33 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
34 import org.onap.aai.exceptions.AAIException;
35 import org.onap.aai.logging.LoggingContext;
36 import org.onap.aai.logging.LoggingContext.StatusCode;
39 import com.att.eelf.configuration.Configuration;
40 import com.att.eelf.configuration.EELFLogger;
41 import com.att.eelf.configuration.EELFManager;
42 import com.thinkaurelius.titan.core.TitanFactory;
43 import com.thinkaurelius.titan.core.TitanGraph;
44 import org.onap.aai.dbmap.AAIGraphConfig;
46 public class UniquePropertyCheck {
49 private static final String FROMAPPID = "AAI-UTILS";
50 private static final String TRANSID = UUID.randomUUID().toString();
51 private static final String COMPONENT = "UniquePropertyCheck";
56 * @param args the arguments
58 public static void main(String[] args) {
61 Properties props = System.getProperties();
62 props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, "uniquePropertyCheck-logback.xml");
63 props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
64 EELFLogger logger = EELFManager.getInstance().getLogger(UniquePropertyCheck.class.getSimpleName());
66 LoggingContext.init();
67 LoggingContext.partnerName(FROMAPPID);
68 LoggingContext.serviceName(AAIConstants.AAI_RESOURCES_MS);
69 LoggingContext.component(COMPONENT);
70 LoggingContext.targetEntity(AAIConstants.AAI_RESOURCES_MS);
71 LoggingContext.targetServiceName("main");
72 LoggingContext.requestId(TRANSID);
73 LoggingContext.statusCode(StatusCode.COMPLETE);
74 LoggingContext.responseCode(LoggingContext.SUCCESS);
76 MDC.put("logFilenameAppender", UniquePropertyCheck.class.getSimpleName());
78 if( args == null || args.length != 1 ){
79 String msg = "usage: UniquePropertyCheck propertyName \n";
80 System.out.println(msg);
81 LoggingContext.statusCode(StatusCode.ERROR);
82 LoggingContext.responseCode(LoggingContext.BUSINESS_PROCESS_ERROR);
83 logAndPrint(logger, msg );
86 String propertyName = args[0];
91 System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n");
92 TitanGraph tGraph = TitanFactory.open(new AAIGraphConfig.Builder(AAIConstants.REALTIME_DB_CONFIG).forService(UniquePropertyCheck.class.getSimpleName()).withGraphType("realtime").buildConfiguration());
94 if( tGraph == null ) {
95 LoggingContext.statusCode(StatusCode.ERROR);
96 LoggingContext.responseCode(LoggingContext.AVAILABILITY_TIMEOUT_ERROR);
97 logAndPrint(logger, " Error: Could not get TitanGraph ");
101 graph = tGraph.newTransaction();
103 LoggingContext.statusCode(StatusCode.ERROR);
104 LoggingContext.responseCode(LoggingContext.AVAILABILITY_TIMEOUT_ERROR);
105 logAndPrint(logger, "could not get graph object in UniquePropertyCheck() \n");
109 catch (AAIException e1) {
110 String msg = "Threw Exception: [" + e1.toString() + "]";
111 LoggingContext.statusCode(StatusCode.ERROR);
112 LoggingContext.responseCode(LoggingContext.UNKNOWN_ERROR);
113 logAndPrint(logger, msg);
116 catch (Exception e2) {
117 String msg = "Threw Exception: [" + e2.toString() + "]";
118 LoggingContext.statusCode(StatusCode.ERROR);
119 LoggingContext.responseCode(LoggingContext.UNKNOWN_ERROR);
120 logAndPrint(logger, msg);
124 runTheCheckForUniqueness( TRANSID, FROMAPPID, graph, propertyName, logger );
131 * Run the check for uniqueness.
133 * @param transId the trans id
134 * @param fromAppId the from app id
135 * @param graph the graph
136 * @param propertyName the property name
137 * @param logger the logger
138 * @return the boolean
140 public static Boolean runTheCheckForUniqueness( String transId, String fromAppId, Graph graph,
141 String propertyName, EELFLogger logger ){
143 // Note - property can be found in more than one nodetype
144 // our uniqueness constraints are always across the entire db - so this
145 // tool looks across all nodeTypes that the property is found in.
146 Boolean foundDupesFlag = false;
148 HashMap <String,String> valuesAndVidHash = new HashMap <String, String> ();
149 HashMap <String,String> dupeHash = new HashMap <String, String> ();
153 Iterator<Vertex> vertItor = graph.traversal().V().has(propertyName);
154 while( vertItor.hasNext() ){
156 Vertex v = vertItor.next();
157 String thisVid = v.id().toString();
158 Object val = (v.<Object>property(propertyName)).orElse(null);
159 if( valuesAndVidHash.containsKey(val) ){
160 // We've seen this one before- track it in our dupe hash
162 if( dupeHash.containsKey(val) ){
163 // This is not the first one being added to the dupe hash for this value
164 String updatedDupeList = dupeHash.get(val) + "|" + thisVid;
165 dupeHash.put(val.toString(), updatedDupeList);
168 // This is the first time we see this value repeating
169 String firstTwoVids = valuesAndVidHash.get(val) + "|" + thisVid;
170 dupeHash.put(val.toString(), firstTwoVids);
174 valuesAndVidHash.put(val.toString(), thisVid);
179 String info = "\n Found this property [" + propertyName + "] " + propCount + " times in our db.";
180 logAndPrint(logger, info);
181 info = " Found " + dupeCount + " cases of duplicate values for this property.\n\n";
182 logAndPrint(logger, info);
185 if( ! dupeHash.isEmpty() ){
186 Iterator <?> dupeItr = dupeHash.entrySet().iterator();
187 while( dupeItr.hasNext() ){
188 Map.Entry pair = (Map.Entry) dupeItr.next();
189 String dupeValue = pair.getKey().toString();;
190 String vidsStr = pair.getValue().toString();
191 String[] vidArr = vidsStr.split("\\|");
192 logAndPrint(logger, "\n\n -------------- Found " + vidArr.length
193 + " nodes with " + propertyName + " of this value: [" + dupeValue + "]. Node details: ");
195 for( int i = 0; i < vidArr.length; i++ ){
196 String vidString = vidArr[i];
197 Long idLong = Long.valueOf(vidString);
198 Vertex tvx = graph.traversal().V(idLong).next();
199 showPropertiesAndEdges( TRANSID, FROMAPPID, tvx, logger );
204 catch( Exception e2 ){
205 LoggingContext.statusCode(StatusCode.ERROR);
206 LoggingContext.responseCode(LoggingContext.DATA_ERROR);
207 logAndPrint(logger, "Threw Exception: [" + e2.toString() + "]");
211 graph.tx().rollback();
215 return foundDupesFlag;
217 }// end of runTheCheckForUniqueness()
221 * Show properties and edges.
223 * @param transId the trans id
224 * @param fromAppId the from app id
225 * @param tVert the t vert
226 * @param logger the logger
228 private static void showPropertiesAndEdges( String transId, String fromAppId, Vertex tVert,
232 logAndPrint(logger, "Null node passed to showPropertiesAndEdges.");
235 String nodeType = "";
236 Object ob = tVert.<String>property("aai-node-type").orElse(null);
241 nodeType = ob.toString();
244 logAndPrint(logger, " AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]");
245 logAndPrint(logger, " Property Detail: ");
246 Iterator<VertexProperty<Object>> pI = tVert.properties();
247 while( pI.hasNext() ){
248 VertexProperty<Object> tp = pI.next();
249 Object val = tp.value();
250 logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] ");
253 Iterator <Edge> eI = tVert.edges(Direction.BOTH);
254 if( ! eI.hasNext() ){
255 logAndPrint(logger, "No edges were found for this vertex. ");
257 while( eI.hasNext() ){
259 String lab = ed.label();
261 if (tVert.equals(ed.inVertex())) {
262 vtx = ed.outVertex();
267 logAndPrint(logger, " >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
270 String nType = vtx.<String>property("aai-node-type").orElse(null);
271 String vid = vtx.id().toString();
272 logAndPrint(logger, "Found an edge (" + lab + ") from this vertex to a [" + nType + "] node with VtxId = " + vid);
276 } // End of showPropertiesAndEdges()
282 * @param logger the logger
285 protected static void logAndPrint(EELFLogger logger, String msg) {
286 System.out.println(msg);