Update the license for 2017-2018 license
[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-2018 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.onap.aai.util;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.Properties;
25 import java.util.UUID;
26
27 import org.apache.tinkerpop.gremlin.structure.Direction;
28 import org.apache.tinkerpop.gremlin.structure.Edge;
29 import org.apache.tinkerpop.gremlin.structure.Graph;
30 import org.apache.tinkerpop.gremlin.structure.Vertex;
31 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
32 import org.onap.aai.exceptions.AAIException;
33 import org.onap.aai.logging.LoggingContext;
34 import org.onap.aai.logging.LoggingContext.StatusCode;
35 import org.slf4j.MDC;
36
37 import com.att.eelf.configuration.Configuration;
38 import com.att.eelf.configuration.EELFLogger;
39 import com.att.eelf.configuration.EELFManager;
40 import com.thinkaurelius.titan.core.TitanFactory;
41 import com.thinkaurelius.titan.core.TitanGraph;
42 import org.onap.aai.dbmap.AAIGraphConfig;
43
44 public class UniquePropertyCheck {
45
46
47         private static  final  String    FROMAPPID = "AAI-UTILS";
48         private static  final  String    TRANSID   = UUID.randomUUID().toString();
49         private static  final  String    COMPONENT = "UniquePropertyCheck";
50         
51         /**
52          * The main method.
53          *
54          * @param args the arguments
55          */
56         public static void main(String[] args) {
57                 
58                 
59                 Properties props = System.getProperties();
60                 props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, "uniquePropertyCheck-logback.xml");
61                 props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
62                 EELFLogger logger = EELFManager.getInstance().getLogger(UniquePropertyCheck.class.getSimpleName());
63                 
64                 LoggingContext.init();
65                 LoggingContext.partnerName(FROMAPPID);
66                 LoggingContext.serviceName(AAIConstants.AAI_RESOURCES_MS);
67                 LoggingContext.component(COMPONENT);
68                 LoggingContext.targetEntity(AAIConstants.AAI_RESOURCES_MS);
69                 LoggingContext.targetServiceName("main");
70                 LoggingContext.requestId(TRANSID);
71                 LoggingContext.statusCode(StatusCode.COMPLETE);
72                 LoggingContext.responseCode(LoggingContext.SUCCESS);
73                 
74                 MDC.put("logFilenameAppender", UniquePropertyCheck.class.getSimpleName());
75                 
76                 if( args == null || args.length != 1 ){
77                                 String msg = "usage:  UniquePropertyCheck propertyName \n";
78                                 System.out.println(msg);
79                                 LoggingContext.statusCode(StatusCode.ERROR);
80                         LoggingContext.responseCode(LoggingContext.BUSINESS_PROCESS_ERROR);
81                                 logAndPrint(logger, msg );
82                                 System.exit(1);
83                 }
84                 String propertyName = args[0];
85                 Graph graph = null;
86                 
87                 try {   
88                 AAIConfig.init();
89                 System.out.println("    ---- NOTE --- about to open graph (takes a little while)--------\n");
90                 TitanGraph tGraph = TitanFactory.open(new AAIGraphConfig.Builder(AAIConstants.REALTIME_DB_CONFIG).forService(UniquePropertyCheck.class.getSimpleName()).withGraphType("realtime").buildConfiguration());
91                 
92                 if( tGraph == null ) {
93                         LoggingContext.statusCode(StatusCode.ERROR);
94                         LoggingContext.responseCode(LoggingContext.AVAILABILITY_TIMEOUT_ERROR);
95                         logAndPrint(logger, " Error:  Could not get TitanGraph ");
96                         System.exit(1);
97                 }
98                 
99                 graph = tGraph.newTransaction();
100                 if( graph == null ){
101                         LoggingContext.statusCode(StatusCode.ERROR);
102                         LoggingContext.responseCode(LoggingContext.AVAILABILITY_TIMEOUT_ERROR);
103                         logAndPrint(logger, "could not get graph object in UniquePropertyCheck() \n");
104                         System.exit(0);
105                 }
106         }
107             catch (AAIException e1) {
108                         String msg =  "Threw Exception: [" + e1.toString() + "]";
109                         LoggingContext.statusCode(StatusCode.ERROR);
110                         LoggingContext.responseCode(LoggingContext.UNKNOWN_ERROR);
111                         logAndPrint(logger, msg);
112                         System.exit(0);
113         }
114         catch (Exception e2) {
115                         String msg =  "Threw Exception: [" + e2.toString() + "]";
116                         LoggingContext.statusCode(StatusCode.ERROR);
117                         LoggingContext.responseCode(LoggingContext.UNKNOWN_ERROR);
118                         logAndPrint(logger, msg);
119                         System.exit(0);
120         }
121                 
122                 runTheCheckForUniqueness( TRANSID, FROMAPPID, graph, propertyName, logger );
123                 System.exit(0);
124                 
125         }// End main()
126         
127         
128         /**
129          * Run the check for uniqueness.
130          *
131          * @param transId the trans id
132          * @param fromAppId the from app id
133          * @param graph the graph
134          * @param propertyName the property name
135          * @param logger the logger
136          * @return the boolean
137          */
138         public static Boolean runTheCheckForUniqueness( String transId, String fromAppId, Graph graph, 
139                         String propertyName, EELFLogger logger ){
140                 
141                 // Note - property can be found in more than one nodetype 
142                 //    our uniqueness constraints are always across the entire db - so this 
143                 //   tool looks across all nodeTypes that the property is found in.
144                 Boolean foundDupesFlag = false;
145                 
146                 HashMap <String,String> valuesAndVidHash = new HashMap <String, String> ();
147                 HashMap <String,String> dupeHash = new HashMap <String, String> ();
148         
149                 int propCount = 0;
150                 int dupeCount = 0;
151                 Iterator<Vertex> vertItor = graph.traversal().V().has(propertyName);
152         while( vertItor.hasNext() ){
153                 propCount++;
154                 Vertex v = vertItor.next();
155                 String thisVid = v.id().toString();
156                 Object val = (v.<Object>property(propertyName)).orElse(null);
157                 if( valuesAndVidHash.containsKey(val) ){
158                         // We've seen this one before- track it in our  dupe hash
159                         dupeCount++;
160                         if( dupeHash.containsKey(val) ){
161                                 // This is not the first one being added to the dupe hash for this value
162                                 String updatedDupeList = dupeHash.get(val) + "|" + thisVid;
163                                 dupeHash.put(val.toString(), updatedDupeList);
164                         }
165                         else {
166                                 // This is the first time we see this value repeating
167                                 String firstTwoVids =  valuesAndVidHash.get(val) + "|" + thisVid;
168                                 dupeHash.put(val.toString(), firstTwoVids);
169                         }
170                 }
171                 else {
172                         valuesAndVidHash.put(val.toString(), thisVid);
173                 }               
174         }
175                 
176         
177         String info = "\n Found this property [" + propertyName + "] " + propCount + " times in our db.";
178         logAndPrint(logger, info);
179         info = " Found " + dupeCount + " cases of duplicate values for this property.\n\n";
180         logAndPrint(logger, info);
181
182         try {
183                 if( ! dupeHash.isEmpty() ){
184                         Iterator <?> dupeItr = dupeHash.entrySet().iterator();
185                         while( dupeItr.hasNext() ){
186                                 Map.Entry pair = (Map.Entry) dupeItr.next();
187                                 String dupeValue = pair.getKey().toString();;
188                                                         String vidsStr = pair.getValue().toString();
189                                 String[] vidArr = vidsStr.split("\\|");
190                                 logAndPrint(logger, "\n\n -------------- Found " + vidArr.length 
191                                                 + " nodes with " + propertyName + " of this value: [" + dupeValue + "].  Node details: ");
192                                 
193                                 for( int i = 0; i < vidArr.length; i++ ){
194                                         String vidString = vidArr[i];
195                                         Long idLong = Long.valueOf(vidString);
196                                         Vertex tvx = graph.traversal().V(idLong).next();
197                                         showPropertiesAndEdges( TRANSID, FROMAPPID, tvx, logger );
198                                 }
199                         }
200                 }
201         }
202         catch( Exception e2 ){
203                 LoggingContext.statusCode(StatusCode.ERROR);
204                         LoggingContext.responseCode(LoggingContext.DATA_ERROR);
205                         logAndPrint(logger, "Threw Exception: [" + e2.toString() + "]");
206         } 
207         finally {
208                 if( graph != null ){
209                         graph.tx().rollback();
210                 }
211         }
212         
213         return foundDupesFlag;
214         
215         }// end of runTheCheckForUniqueness()
216         
217         
218         /**
219          * Show properties and edges.
220          *
221          * @param transId the trans id
222          * @param fromAppId the from app id
223          * @param tVert the t vert
224          * @param logger the logger
225          */
226         private static void showPropertiesAndEdges( String transId, String fromAppId, Vertex tVert,
227                         EELFLogger logger ){ 
228
229                 if( tVert == null ){
230                         logAndPrint(logger, "Null node passed to showPropertiesAndEdges.");
231                 }
232                 else {
233                         String nodeType = "";
234                         Object ob = tVert.<String>property("aai-node-type").orElse(null);
235                         if( ob == null ){
236                                 nodeType = "null";
237                         }
238                         else{
239                                 nodeType = ob.toString();
240                         }
241                         
242                         logAndPrint(logger, " AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]");
243                         logAndPrint(logger, " Property Detail: ");
244                         Iterator<VertexProperty<Object>> pI = tVert.properties();
245                         while( pI.hasNext() ){
246                                 VertexProperty<Object> tp = pI.next();
247                                 Object val = tp.value();
248                                 logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] ");          
249                         }
250                         
251                         Iterator <Edge> eI = tVert.edges(Direction.BOTH);
252                         if( ! eI.hasNext() ){
253                                 logAndPrint(logger, "No edges were found for this vertex. ");
254                         }
255                         while( eI.hasNext() ){
256                                 Edge ed = eI.next();
257                                 String lab = ed.label();
258                                 Vertex vtx;
259                                 if (tVert.equals(ed.inVertex())) {
260                                         vtx = ed.outVertex();
261                                 } else {
262                                         vtx = ed.inVertex();
263                                 }
264                                 if( vtx == null ){
265                                         logAndPrint(logger, " >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
266                                 }
267                                 else {
268                                         String nType = vtx.<String>property("aai-node-type").orElse(null);
269                                         String vid = vtx.id().toString();
270                                         logAndPrint(logger, "Found an edge (" + lab + ") from this vertex to a [" + nType + "] node with VtxId = " + vid);
271                                 }
272                         }
273                 }
274         } // End of showPropertiesAndEdges()
275
276         
277         /**
278          * Log and print.
279          *
280          * @param logger the logger
281          * @param msg the msg
282          */
283         protected static void logAndPrint(EELFLogger logger, String msg) {
284                 System.out.println(msg);
285                 logger.info(msg);
286         }
287         
288 }
289
290