Sync the latest code changes
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / util / UniquePropertyCheck.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
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
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  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  */
22 package org.onap.aai.util;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.Properties;
27 import java.util.UUID;
28
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;
37 import org.slf4j.MDC;
38
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;
45
46 public class UniquePropertyCheck {
47
48
49         private static  final  String    FROMAPPID = "AAI-UTILS";
50         private static  final  String    TRANSID   = UUID.randomUUID().toString();
51         private static  final  String    COMPONENT = "UniquePropertyCheck";
52         
53         /**
54          * The main method.
55          *
56          * @param args the arguments
57          */
58         public static void main(String[] args) {
59                 
60                 
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());
65                 
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);
75                 
76                 MDC.put("logFilenameAppender", UniquePropertyCheck.class.getSimpleName());
77                 
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 );
84                                 System.exit(1);
85                 }
86                 String propertyName = args[0];
87                 Graph graph = null;
88                 
89                 try {   
90                 AAIConfig.init();
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());
93                 
94                 if( tGraph == null ) {
95                         LoggingContext.statusCode(StatusCode.ERROR);
96                         LoggingContext.responseCode(LoggingContext.AVAILABILITY_TIMEOUT_ERROR);
97                         logAndPrint(logger, " Error:  Could not get TitanGraph ");
98                         System.exit(1);
99                 }
100                 
101                 graph = tGraph.newTransaction();
102                 if( graph == null ){
103                         LoggingContext.statusCode(StatusCode.ERROR);
104                         LoggingContext.responseCode(LoggingContext.AVAILABILITY_TIMEOUT_ERROR);
105                         logAndPrint(logger, "could not get graph object in UniquePropertyCheck() \n");
106                         System.exit(0);
107                 }
108         }
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);
114                         System.exit(0);
115         }
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);
121                         System.exit(0);
122         }
123                 
124                 runTheCheckForUniqueness( TRANSID, FROMAPPID, graph, propertyName, logger );
125                 System.exit(0);
126                 
127         }// End main()
128         
129         
130         /**
131          * Run the check for uniqueness.
132          *
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
139          */
140         public static Boolean runTheCheckForUniqueness( String transId, String fromAppId, Graph graph, 
141                         String propertyName, EELFLogger logger ){
142                 
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;
147                 
148                 HashMap <String,String> valuesAndVidHash = new HashMap <String, String> ();
149                 HashMap <String,String> dupeHash = new HashMap <String, String> ();
150         
151                 int propCount = 0;
152                 int dupeCount = 0;
153                 Iterator<Vertex> vertItor = graph.traversal().V().has(propertyName);
154         while( vertItor.hasNext() ){
155                 propCount++;
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
161                         dupeCount++;
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);
166                         }
167                         else {
168                                 // This is the first time we see this value repeating
169                                 String firstTwoVids =  valuesAndVidHash.get(val) + "|" + thisVid;
170                                 dupeHash.put(val.toString(), firstTwoVids);
171                         }
172                 }
173                 else {
174                         valuesAndVidHash.put(val.toString(), thisVid);
175                 }               
176         }
177                 
178         
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);
183
184         try {
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: ");
194                                 
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 );
200                                 }
201                         }
202                 }
203         }
204         catch( Exception e2 ){
205                 LoggingContext.statusCode(StatusCode.ERROR);
206                         LoggingContext.responseCode(LoggingContext.DATA_ERROR);
207                         logAndPrint(logger, "Threw Exception: [" + e2.toString() + "]");
208         } 
209         finally {
210                 if( graph != null ){
211                         graph.tx().rollback();
212                 }
213         }
214         
215         return foundDupesFlag;
216         
217         }// end of runTheCheckForUniqueness()
218         
219         
220         /**
221          * Show properties and edges.
222          *
223          * @param transId the trans id
224          * @param fromAppId the from app id
225          * @param tVert the t vert
226          * @param logger the logger
227          */
228         private static void showPropertiesAndEdges( String transId, String fromAppId, Vertex tVert,
229                         EELFLogger logger ){ 
230
231                 if( tVert == null ){
232                         logAndPrint(logger, "Null node passed to showPropertiesAndEdges.");
233                 }
234                 else {
235                         String nodeType = "";
236                         Object ob = tVert.<String>property("aai-node-type").orElse(null);
237                         if( ob == null ){
238                                 nodeType = "null";
239                         }
240                         else{
241                                 nodeType = ob.toString();
242                         }
243                         
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 + "] ");          
251                         }
252                         
253                         Iterator <Edge> eI = tVert.edges(Direction.BOTH);
254                         if( ! eI.hasNext() ){
255                                 logAndPrint(logger, "No edges were found for this vertex. ");
256                         }
257                         while( eI.hasNext() ){
258                                 Edge ed = eI.next();
259                                 String lab = ed.label();
260                                 Vertex vtx;
261                                 if (tVert.equals(ed.inVertex())) {
262                                         vtx = ed.outVertex();
263                                 } else {
264                                         vtx = ed.inVertex();
265                                 }
266                                 if( vtx == null ){
267                                         logAndPrint(logger, " >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
268                                 }
269                                 else {
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);
273                                 }
274                         }
275                 }
276         } // End of showPropertiesAndEdges()
277
278         
279         /**
280          * Log and print.
281          *
282          * @param logger the logger
283          * @param msg the msg
284          */
285         protected static void logAndPrint(EELFLogger logger, String msg) {
286                 System.out.println(msg);
287                 logger.info(msg);
288         }
289         
290 }
291
292