// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.api.doc; import java.io.BufferedWriter; import java.io.EOFException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.util.Map; import java.util.LinkedHashMap; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Arrays; import com.google.gson.Gson; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; public class ApiXmlDocReader { public static void main(String[] args) { String newFile = null; String oldFile = null; String dirName = ""; LinkedHashMap<String, Command> commands = new LinkedHashMap<String, Command>(); LinkedHashMap<String, Command> oldCommands = new LinkedHashMap<String, Command>(); ArrayList<Command> addedCommands = new ArrayList<Command>(); ArrayList<Command> removedCommands = new ArrayList<Command>(); HashMap<String, Command> stableCommands = new HashMap<String, Command>(); HashMap<String, Object> jsonOut = new HashMap<String, Object>(); Gson gson = new Gson(); XStream xs = new XStream(new DomDriver()); xs.alias("command", Command.class); xs.alias("arg", Argument.class); List<String> argsList = Arrays.asList(args); Iterator<String> iter = argsList.iterator(); while (iter.hasNext()) { String arg = iter.next(); // populate the file names if (arg.equals("-new")) { newFile = iter.next(); } if (arg.equals("-old")) { oldFile = iter.next(); } if (arg.equals("-d")) { dirName = iter.next(); } } try { try (ObjectInputStream inOld = xs.createObjectInputStream(new FileReader(oldFile));){ while (true) { Command c1 = (Command)inOld.readObject(); oldCommands.put(c1.getName(), c1); } } catch (EOFException ex) { // EOF exception shows that there is no more objects in ObjectInputStream, so do nothing here } try (ObjectInputStream inNew = xs.createObjectInputStream(new FileReader(newFile));){ while (true) { Command c = (Command)inNew.readObject(); commands.put(c.getName(), c); } } catch (EOFException ex) { // EOF exception shows that there is no more objects in ObjectInputStream, so do nothing here } } catch (Exception ex) { ex.printStackTrace(); } // Check if any commands got added in new version for (Map.Entry<String,Command>entry : commands.entrySet()) { if (!oldCommands.containsKey(entry.getKey())) { addedCommands.add(entry.getValue()); } else { stableCommands.put(entry.getValue().getName(), entry.getValue()); } } // Check if any commands were removed in new version for (Map.Entry<String,Command>entry : oldCommands.entrySet()) { if (!commands.containsKey(entry.getKey())) { removedCommands.add(entry.getValue()); if (stableCommands.get(entry.getKey()) != null) { stableCommands.remove(entry.getKey()); } } } try (FileWriter fstream = new FileWriter(dirName + "/diff.txt"); BufferedWriter out = new BufferedWriter(fstream); FileWriter jfstream = new FileWriter(dirName + "/diff.json"); BufferedWriter json = new BufferedWriter(jfstream);){ // Print added commands out.write("Added commands:\n"); ArrayList<HashMap<String, Object>> addedCmds = new ArrayList<HashMap<String, Object>>(); for (Command c : addedCommands) { HashMap<String, Object> addedCmd = new HashMap<String, Object>(); if (c.getDescription() != null && !c.getDescription().isEmpty()) { out.write("\n " + c.getName() + " (" + c.getDescription() + ")\n"); addedCmd.put("description", c.getDescription()); } else { out.write("\n " + c.getName() + "\n"); } addedCmd.put("name", c.getName()); addedCmds.add(addedCmd); } jsonOut.put("commands_added", addedCmds); // Print removed commands out.write("\nRemoved commands:\n"); ArrayList<HashMap<String, Object>> removedCmds = new ArrayList<HashMap<String, Object>>(); for (Command c : removedCommands) { HashMap<String, Object> removedCmd = new HashMap<String, Object>(); if (c.getDescription() != null && !c.getDescription().isEmpty()) { out.write("\n\t" + c.getName() + " (" + c.getDescription() + ")\n"); removedCmd.put("description", c.getDescription()); } else { out.write("\n\t" + c.getName() + "\n"); } removedCmd.put("name", c.getName()); removedCmds.add(removedCmd); } jsonOut.put("commands_removed", removedCmds); out.write("\nChanges in command type (sync versus async)\n"); ArrayList<HashMap<String, Object>> syncChangeCmds = new ArrayList<HashMap<String, Object>>(); // Verify if the command was sync and became async and vice versa for (Map.Entry<String,Command>entry : stableCommands.entrySet()) { if (commands.get(entry.getKey()).isAsync() != oldCommands.get(entry.getKey()).isAsync()) { HashMap<String, Object> syncChangeCmd = new HashMap<String, Object>(); String type = "Sync"; if (commands.get(entry.getKey()).isAsync()) { type = "Async"; } syncChangeCmd.put("name", entry.getValue().getName()); syncChangeCmd.put("sync_type", type); syncChangeCmds.add(syncChangeCmd); out.write("\n\t" + entry.getValue().getName() + " became " + type); } } jsonOut.put("commands_sync_changed", syncChangeCmds); // Print differences between commands arguments out.write("\n\nChanges in commands arguments:\n"); ArrayList<HashMap<String, Object>> argsChangeCmds = new ArrayList<HashMap<String, Object>>(); for (String key : stableCommands.keySet()) { ArrayList<Argument> newReqArgs = new ArrayList<Argument>(); ArrayList<Argument> removedReqArgs = new ArrayList<Argument>(); HashMap<String, Argument> stableReqArgs = new HashMap<String, Argument>(); ArrayList<Argument> newRespArgs = new ArrayList<Argument>(); ArrayList<Argument> removedRespArgs = new ArrayList<Argument>(); HashMap<String, Object> argsChangeCmd = new HashMap<String, Object>(); Command newCommand = commands.get(key); Command oldCommand = oldCommands.get(key); // Check if any request arguments were added in new version for (Argument arg : newCommand.getRequest()) { if (oldCommand.getReqArgByName(arg.getName()) == null) { if (!(arg.getName().equals("page") || arg.getName().equals("pagesize") || arg.getName().equals("keyword"))) { newReqArgs.add(arg); } } else { stableReqArgs.put(arg.getName(), arg); } } // Check if any request arguments were removed in new version for (Argument arg : oldCommand.getRequest()) { if (newCommand.getReqArgByName(arg.getName()) == null) { removedReqArgs.add(arg); if (stableReqArgs.get(arg.getName()) != null) { stableReqArgs.remove(arg.getName()); } } } // Compare stable request arguments of old and new version for (Iterator<String> i = stableReqArgs.keySet().iterator(); i.hasNext();) { String argName = i.next(); if ((oldCommand.getReqArgByName(argName) != null) && (newCommand.getReqArgByName(argName) != null)) { if (oldCommand.getReqArgByName(argName).isRequired().equals(newCommand.getReqArgByName(argName).isRequired())) { i.remove(); } } } // Check if any response arguments were added in new version if (newCommand.getResponse() != null && oldCommand.getResponse() != null) { for (Argument arg : newCommand.getResponse()) { if (oldCommand.getResArgByName(arg.getName()) == null) { newRespArgs.add(arg); } } // Check if any response arguments were removed in new version for (Argument arg : oldCommand.getResponse()) { if (newCommand.getResArgByName(arg.getName()) == null) { removedRespArgs.add(arg); } } } if (newReqArgs.size() != 0 || newRespArgs.size() != 0 || removedReqArgs.size() != 0 || removedRespArgs.size() != 0 || stableReqArgs.size() != 0) { StringBuffer commandInfo = new StringBuffer(); commandInfo.append("\n\t" + key); out.write(commandInfo.toString()); out.write("\n"); argsChangeCmd.put("name", key); // Request if (newReqArgs.size() != 0 || removedReqArgs.size() != 0 || stableReqArgs.size() != 0) { HashMap<String, Object> requestChanges = new HashMap<String, Object>(); StringBuffer request = new StringBuffer(); request.append("\n\t\tRequest:\n"); out.write(request.toString()); if (newReqArgs.size() != 0) { StringBuffer newParameters = new StringBuffer(); newParameters.append("\n\t\t\tNew parameters: "); ArrayList<HashMap<String, Object>> newRequestParams = new ArrayList<HashMap<String, Object>>(); for (Argument newArg : newReqArgs) { HashMap<String, Object> newRequestParam = new HashMap<String, Object>(); String isRequiredParam = "optional"; if (newArg.isRequired()) { isRequiredParam = "required"; } newRequestParam.put("name", newArg.getName()); newRequestParam.put("required", newArg.isRequired()); newRequestParams.add(newRequestParam); newParameters.append(newArg.getName() + " (" + isRequiredParam + "), "); } requestChanges.put("params_new", newRequestParams); newParameters.delete(newParameters.length() - 2, newParameters.length() - 1); out.write(newParameters.toString()); out.write("\n"); } if (removedReqArgs.size() != 0) { StringBuffer removedParameters = new StringBuffer(); removedParameters.append("\n\t\t\tRemoved parameters: "); ArrayList<HashMap<String, Object>> removedRequestParams = new ArrayList<HashMap<String, Object>>(); for (Argument removedArg : removedReqArgs) { HashMap<String, Object> removedRequestParam = new HashMap<String, Object>(); removedRequestParam.put("name", removedArg.getName()); removedRequestParams.add(removedRequestParam); removedParameters.append(removedArg.getName() + ", "); } requestChanges.put("params_removed", removedRequestParams); removedParameters.delete(removedParameters.length() - 2, removedParameters.length() - 1); out.write(removedParameters.toString()); out.write("\n"); } if (stableReqArgs.size() != 0) { StringBuffer changedParameters = new StringBuffer(); changedParameters.append("\n\t\t\tChanged parameters: "); ArrayList<HashMap<String, Object>> changedRequestParams = new ArrayList<HashMap<String, Object>>(); for (Argument stableArg : stableReqArgs.values()) { HashMap<String, Object> changedRequestParam = new HashMap<String, Object>(); String newRequired = "optional"; String oldRequired = "optional"; changedRequestParam.put("required_old", false); changedRequestParam.put("required_new", false); if ((oldCommand.getReqArgByName(stableArg.getName()) != null) && (oldCommand.getReqArgByName(stableArg.getName()).isRequired() == true)) { oldRequired = "required"; changedRequestParam.put("required_old", true); } if ((newCommand.getReqArgByName(stableArg.getName()) != null) && (newCommand.getReqArgByName(stableArg.getName()).isRequired() == true)) { newRequired = "required"; changedRequestParam.put("required_new", true); } changedRequestParam.put("name", stableArg.getName()); changedRequestParams.add(changedRequestParam); changedParameters.append(stableArg.getName() + " (old version - " + oldRequired + ", new version - " + newRequired + "), "); } requestChanges.put("params_changed", changedRequestParams); changedParameters.delete(changedParameters.length() - 2, changedParameters.length() - 1); out.write(changedParameters.toString()); out.write("\n"); } argsChangeCmd.put("request", requestChanges); } // Response if (newRespArgs.size() != 0 || removedRespArgs.size() != 0) { HashMap<String, Object> responseChanges = new HashMap<String, Object>(); StringBuffer changedResponseParams = new StringBuffer(); changedResponseParams.append("\n\t\tResponse:\n"); out.write(changedResponseParams.toString()); if (newRespArgs.size() != 0) { ArrayList<HashMap<String, Object>> newResponseParams = new ArrayList<HashMap<String, Object>>(); StringBuffer newRespParams = new StringBuffer(); newRespParams.append("\n\t\t\tNew parameters: "); for (Argument newArg : newRespArgs) { HashMap<String, Object> newResponseParam = new HashMap<String, Object>(); newResponseParam.put("name", newArg.getName()); newResponseParams.add(newResponseParam); newRespParams.append(newArg.getName() + ", "); } responseChanges.put("params_new", newResponseParams); newRespParams.delete(newRespParams.length() - 2, newRespParams.length() - 1); out.write(newRespParams.toString()); out.write("\n"); } if (removedRespArgs.size() != 0) { ArrayList<HashMap<String, Object>> removedResponseParams = new ArrayList<HashMap<String, Object>>(); StringBuffer removedRespParams = new StringBuffer(); removedRespParams.append("\n\t\t\tRemoved parameters: "); for (Argument removedArg : removedRespArgs) { HashMap<String, Object> removedResponseParam = new HashMap<String, Object>(); removedResponseParam.put("name", removedArg.getName()); removedResponseParams.add(removedResponseParam); removedRespParams.append(removedArg.getName() + ", "); } responseChanges.put("params_removed", removedResponseParams); removedRespParams.delete(removedRespParams.length() - 2, removedRespParams.length() - 1); out.write(removedRespParams.toString()); out.write("\n"); } argsChangeCmd.put("response", responseChanges); } argsChangeCmds.add(argsChangeCmd); } } jsonOut.put("commands_args_changed", argsChangeCmds); json.write(gson.toJson(jsonOut)); } catch (IOException e) { e.printStackTrace(); } } }