DBVIEW
|
00001 /* 00002 DbView - Graph Visualization 00003 Copyright (C) 2012 Denis BEURIVE 00004 00005 This program is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 /** 00020 * @author Denis Beurive 00021 */ 00022 00023 package org.dbview.runtime.actions; 00024 00025 import java.util.ArrayList; 00026 import java.util.Enumeration; 00027 import java.util.Hashtable; 00028 import java.util.Iterator; 00029 import java.util.List; 00030 import java.io.*; 00031 import org.jdom.Element; 00032 import org.dbview.adapter.AbstractCli; 00033 import org.dbview.adapter.AbstractDescription; 00034 import org.dbview.adapter.CliParameter; 00035 import org.dbview.db.structure.*; 00036 import org.dbview.input_addons.*; 00037 import org.dbview.output_addons.*; 00038 import org.dbview.resources.*; 00039 import org.dbview.utils.Strings; 00040 import org.jgrapht.GraphPath; 00041 import org.jgrapht.UndirectedGraph; 00042 import org.jgrapht.alg.KShortestPaths; 00043 00044 /** 00045 * This class implements all action defined by the command line interface. 00046 * 00047 * @author Denis Beurive 00048 */ 00049 00050 public class Actions 00051 { 00052 00053 /** 00054 * This method lists all input targets. 00055 * 00056 * @throws Exception 00057 */ 00058 public static void listInputTargets() throws Exception 00059 { 00060 InputCatalog catalog = new InputCatalog(); 00061 Enumeration<String> e = catalog.getTargets(); 00062 while (e.hasMoreElements()) 00063 { 00064 System.out.println("\t" + e.nextElement()); 00065 } 00066 } 00067 00068 /** 00069 * This method lists all foreign key matchers. 00070 * @throws Exception 00071 */ 00072 public static void listFkMatchers() throws Exception 00073 { 00074 SotfForeignKeyDetectorCatalog catalogue = new SotfForeignKeyDetectorCatalog(); 00075 Enumeration<String> e = catalogue.getMatchers(); 00076 while (e.hasMoreElements()) 00077 { 00078 String matcher_name = e.nextElement(); 00079 String desc = catalogue.getFkMatcherDescriptionByName(matcher_name); 00080 System.out.println("\t" + SotfForeignKeyDetectorCatalog.toCli(matcher_name)); 00081 System.out.println(org.dbview.utils.Strings.indent("\t", desc)); 00082 System.out.println(); 00083 } 00084 System.out.println("Please note that, if you don't find the soft foreign key detector that you need, you can easily create a new one, and add it to the list. Only very basic knowledge in Java is required for this operation. Basically, you write one class, and you reccompile the software (usng the provided ANT specification). That's it. Look at the online documentation for an example."); 00085 00086 System.out.println(); 00087 } 00088 00089 /** 00090 * This method prints the help for a specific input add-on. 00091 * @param in_args This hash table contains the parameters required for printing the help for a specific input add-on. 00092 * Keys are: 00093 * <ul> 00094 * <li>name; Name of the input add-on.</li> 00095 * </ul> 00096 * 00097 * @throws Exception 00098 */ 00099 public static void helpInputAddOn(Hashtable<String, Object> in_args) throws Exception 00100 { 00101 String add_on_name = (String)in_args.get("name"); 00102 00103 InputCatalog catalog = new InputCatalog(); 00104 AbstractDescription description = (AbstractDescription) catalog.getAdaptor(add_on_name, "Description"); 00105 AbstractCli cli = (AbstractCli) catalog.getAdaptor(add_on_name, "Cli"); 00106 00107 System.out.println(description.brief()); 00108 ArrayList<CliParameter> opt = cli.getOptions(); 00109 System.out.println("Parameters:"); 00110 for (CliParameter param : opt) 00111 { 00112 System.out.println("\t" + param.parameter + " (" + (param.mandatory ? "mandatory" : "optional") + ")"); 00113 // System.out.println("\ttype:\t\t" + 00114 // CliParameterTypes.toString(param.type)); 00115 // System.out.println("\tmandatory:\t" + (param.mandatory ? "TRUE" : 00116 // "FALSE")); 00117 // System.out.println("\tdescription:\t" + param.description); 00118 // System.out.println(); 00119 } 00120 } 00121 00122 /** 00123 * This method prints the help for a specific output target. 00124 * @param in_args This hash table contains the parameters required for printing the help for a specific output add-on. 00125 * Keys are: 00126 * <ul> 00127 * <li>name: Name of the output add-on. 00128 * </ul> 00129 * 00130 * @throws Exception 00131 */ 00132 public static void helpOutputAddOn(Hashtable<String, Object> in_args) throws Exception 00133 { 00134 String add_on_name = (String)in_args.get("name"); 00135 00136 OutputCatalog catalog = new OutputCatalog(); 00137 AbstractDescription description = (AbstractDescription) catalog.getAdaptor(add_on_name, "Description"); 00138 AbstractCli cli = (AbstractCli) catalog.getAdaptor(add_on_name, "Cli"); 00139 00140 System.out.println(description.brief()); 00141 ArrayList<CliParameter> opt = cli.getOptions(); 00142 System.out.println("Parameters:"); 00143 for (CliParameter param : opt) 00144 { 00145 System.out.println("\t" + param.parameter + " (" + (param.mandatory ? "mandatory" : "optional") + ")"); 00146 // System.out.println("\ttype:\t\t" + 00147 // CliParameterTypes.toString(param.type)); 00148 // System.out.println("\tmandatory:\t" + (param.mandatory ? "TRUE" : 00149 // "FALSE")); 00150 // System.out.println("\tdescription:\t" + param.description); 00151 // System.out.println(); 00152 } 00153 } 00154 00155 /** 00156 * This method lists all output targets. 00157 * 00158 * @throws Exception 00159 */ 00160 public static void listOutputTargets() throws Exception 00161 { 00162 OutputCatalog catalog = new OutputCatalog(); 00163 Enumeration<String> e = catalog.getTargets(); 00164 while (e.hasMoreElements()) 00165 { 00166 System.out.println("\t" + OutputCatalog.toCli(e.nextElement())); 00167 } 00168 } 00169 00170 /** 00171 * This method adds a new profile to the repository. 00172 * 00173 * @param in_args This hash table contains the parameters required for updating a profile. 00174 * Keys are: 00175 * <ul> 00176 * <li>name: Name of the new profile to add.</li> 00177 * <li>input-target: Profile's target.</li> 00178 * <li>input-target-configuration: XML document, generated by the CLI parser, that represents the profile.</li> 00179 * </ul> 00180 * 00181 * @throws Exception 00182 */ 00183 public static void addProfile(Hashtable<String, Object> in_args) throws Exception 00184 { 00185 String profile_name = (String)in_args.get("name"); 00186 String target_name = (String)in_args.get("input-target"); 00187 Element configuration = (Element)in_args.get("input-target-configuration"); 00188 00189 InputCatalog catalog = new InputCatalog(); 00190 AbstractConfiguration profile = (AbstractConfiguration) catalog.getAdaptor(target_name, "Configuration"); 00191 profile.fromXml(configuration, target_name, profile_name); 00192 // System.out.println(profile.printToXml()); 00193 ProfilesRepository.add(profile); 00194 } 00195 00196 /** 00197 * This method removes a profile from the repository. 00198 * @param in_args This hash table contains the parameters required for updating a profile. 00199 * Keys are: 00200 * <ul> 00201 * <li>name: Name of the profile to remove.</li> 00202 * </ul> 00203 00204 * @throws Exception 00205 */ 00206 // public static void removeProfile(String in_profile_name) throws Exception 00207 public static void removeProfile(Hashtable<String, Object> in_args) throws Exception 00208 { 00209 String profile_name = (String)in_args.get("name"); 00210 ProfilesRepository.remove(profile_name); 00211 } 00212 00213 /** 00214 * This method removes a profile from the repository. 00215 * @param in_args This hash table contains the parameters required for updating a profile. 00216 * Keys are: 00217 * <ul> 00218 * <li>name: Name of the profile to upddate.</li> 00219 * <li>target: Name of the profile's target.</li> 00220 * <li>new_configuration: XML document, generated by the CLI parser, that represents the new profile.</li> 00221 * <li>old_configuration: XML document, generated by the CLI parser, that represents the old profile.</li> 00222 * </ul> 00223 * 00224 * @throws Exception 00225 */ 00226 public static void updateProfile(Hashtable<String, Object> in_args) throws Exception 00227 00228 { 00229 String profile_name = (String)in_args.get("name"); 00230 String target_name = (String)in_args.get("target"); 00231 Element new_configuration = (Element)in_args.get("new_configuration"); 00232 Element old_configuration = (Element)in_args.get("old_configuration"); 00233 00234 // try { System.out.println("New profile:"); 00235 // System.out.println(org.dbview.utils.Jdom.print(in_new_configuration)); 00236 // System.out.println("Old profile:"); 00237 // System.out.println(org.dbview.utils.Jdom.print(in_old_configuration)); 00238 // } catch (Exception e) { } 00239 00240 // Build the new version of the profile... 00241 Element old_data = old_configuration.getChild("data"); 00242 @SuppressWarnings("unchecked") 00243 List<Element> params = (List<Element>)new_configuration.getChildren(); 00244 for (int i = 0; i < params.size(); i++) 00245 { 00246 Element param = params.get(i); 00247 String name = param.getName(); 00248 Element e = old_data.getChild(name); 00249 if (null == e) 00250 { 00251 throw new Exception("Unexpected error : the specified parameter \"" + name + "\" could not be found in the current configuration. Please note that this error should not happen unless you modify the software."); 00252 } 00253 try 00254 { 00255 e.setText(param.getText()); 00256 } 00257 catch (Exception ex) 00258 { 00259 throw new Exception("Unexpected error : " + ex.getMessage()); 00260 } 00261 } 00262 00263 // try { System.out.println("Profile to inject into repository:"); 00264 // System.out.println(org.dbview.utils.Jdom.print(in_old_configuration)); 00265 // } catch (Exception e) { } 00266 00267 // Update the repository with the new version of the profile. 00268 try 00269 { 00270 InputCatalog c = new InputCatalog(); 00271 AbstractConfiguration new_conf = (AbstractConfiguration) c.getAdaptor(target_name, "Configuration"); 00272 new_conf.fromXml(old_configuration, null, null); 00273 ProfilesRepository.update(new_conf); 00274 } 00275 catch (Exception ex) 00276 { 00277 throw new Exception("Unexpected error: " + ex.getMessage() + " " + ex.getClass().getName()); 00278 } 00279 } 00280 00281 /** 00282 * This method prints a given profile. 00283 * @param in_args This hash table contains the parameters required for showing a profile. 00284 * Keys are: 00285 * <ul> 00286 * <li>name: Name of the profile to show.</li> 00287 * </ul> 00288 * @throws Exception 00289 */ 00290 public static void showProfile(Hashtable<String, Object> in_args) throws Exception 00291 00292 { 00293 String name = (String)in_args.get("name"); 00294 ProfilesRepository.init(); 00295 AbstractConfiguration profile_configuration = ProfilesRepository.getProfileInstance(name); 00296 if (null == profile_configuration) 00297 { 00298 throw new Exception("The profile \"" + name + "\" does not exist."); 00299 } 00300 00301 ArrayList<String[]> data = profile_configuration.toStrings(); 00302 ArrayList<String> fields = new ArrayList<String>(); 00303 for (int i = 0; i < data.size(); i++) 00304 { 00305 fields.add(data.get(i)[0]); 00306 } 00307 Strings.margingRight(fields, 2); 00308 for (int i = 0; i < data.size(); i++) 00309 { 00310 System.out.println("\t" + fields.get(i) + data.get(i)[1]); 00311 } 00312 } 00313 00314 /** 00315 * This method prints the list of profile's names stored in the repository. 00316 * 00317 * @throws Exception 00318 */ 00319 public static void listProfiles() throws Exception 00320 { 00321 ArrayList<String> profiles = null; 00322 00323 ProfilesRepository.init(); 00324 profiles = ProfilesRepository.getProfilesNames(); 00325 for (int i = 0; i < profiles.size(); i++) 00326 { 00327 System.out.println(profiles.get(i)); 00328 00329 Hashtable<String, Object> params = new Hashtable<String, Object>(); 00330 params.put("name", profiles.get(i)); 00331 Actions.showProfile(params); 00332 System.out.println(); 00333 } 00334 } 00335 00336 /** 00337 * This method exports a given database to a given output format. 00338 * @param in_args his hash table contains the parameters for the export. 00339 * Keys are: 00340 * <ul> 00341 * <li>path-between: If the user request the calculation of a path, this array contains the names of the tables at the extremities.</li> 00342 * <li>path-limit: If the user request the calculation of a path, this integer represents the maximum number of paths.</li> 00343 * <li>zoom-list: If the user request a zoom around tables, this array contains the list of tables to zoom in.</li> 00344 * <li>zoom-level: If the user request a zoom around tables, this integer represents the neighbourhood area.</li> 00345 * <li>input-target-name: Name of the add-on that is used to connect to a database.</li> 00346 * <li>output-target-name: Name of the add-on used to export the database.</li> 00347 * <li>input-configuration: Specific configuration for the input add-on.</li> 00348 * <li>output-configuration: Specific configuration for the output add-on.</li> 00349 * </ul> 00350 * 00351 * @throws Exception 00352 */ 00353 00354 public static void export(Hashtable<String, Object> in_args) throws Exception 00355 { 00356 @SuppressWarnings("unchecked") 00357 ArrayList<String> path_between = in_args.containsKey("path-between") ? (ArrayList<String>)in_args.get("path-between") : null; 00358 Integer path_limit = in_args.containsKey("path-limit") ? (Integer)in_args.get("path-limit") : null; 00359 00360 @SuppressWarnings("unchecked") 00361 ArrayList<String> zoom_list = in_args.containsKey("zoom-list") ? (ArrayList<String>)in_args.get("zoom-list") : null; 00362 Integer zoom_level = in_args.containsKey("zoom-level") ? (Integer)in_args.get("zoom-level") : null; 00363 00364 String input_target = (String)in_args.get("input-target-name"); 00365 String output_target = (String)in_args.get("output-target-name"); 00366 Element input_configuration = (Element)in_args.get("input-configuration"); 00367 Element in_output_confguration = (Element)in_args.get("output-configuration"); 00368 00369 00370 // Create the catalogues. 00371 InputCatalog in_catalog = new InputCatalog(); 00372 OutputCatalog out_catalog = new OutputCatalog(); 00373 00374 // First get the "loader" adapter for the requested input target. 00375 AbstractLoader loader = (AbstractLoader) in_catalog.getAdaptor(input_target, "Loader"); 00376 00377 // Then, get the "exporter" adaptor for the requested output target. 00378 AbstractExporter exporter = (AbstractExporter) out_catalog.getAdaptor(output_target, "Exporter"); 00379 00380 // System.out.println("OK"); 00381 00382 // Load the database. 00383 Database db = loader.load(input_configuration); 00384 // System.out.println("DB loaded!"); 00385 00386 // Get the list of tables to export. 00387 Object representation; 00388 if (null != zoom_list) 00389 { 00390 ArrayList<Table> tables = db.zoomAroundByNames(zoom_list, zoom_level); 00391 representation = exporter.export(db, in_output_confguration, tables); 00392 } 00393 else 00394 { 00395 if (null != path_between) 00396 { 00397 ArrayList<Object> lr = new ArrayList<Object>(); 00398 String from_table_name = path_between.get(0); 00399 String to_table_name = path_between.get(1); 00400 00401 // Make sure that the given table's names exist in the loaded database. 00402 if (null == db.getTable(from_table_name)) 00403 { throw new Exception("The name of the table you specified as starting point of the path (\"" + from_table_name + "\") does not exist in the database."); } 00404 00405 if (null == db.getTable(to_table_name)) 00406 { throw new Exception("The name of the table you specified as ending point of the path (\"" + to_table_name + "\") does not exist in the database."); } 00407 00408 // Get the JgraphT object that represents the database. 00409 UndirectedGraph<Table, JgraphtTableToTableEdge> g = db.jgrapht(null); 00410 00411 // Calculate the shortest path(es) between the two specified tables. 00412 KShortestPaths<Table, JgraphtTableToTableEdge> pathesFinder = new KShortestPaths<Table, JgraphtTableToTableEdge>(g, db.getTable(from_table_name), path_limit); 00413 List <GraphPath<Table, JgraphtTableToTableEdge>> pathes = pathesFinder.getPaths(db.getTable(to_table_name)); 00414 Iterator<GraphPath<Table, JgraphtTableToTableEdge>> pathesIterator = pathes.iterator(); 00415 00416 while (pathesIterator.hasNext()) 00417 { 00418 // Get the start and the end of the pathes (we already know) 00419 GraphPath<Table, JgraphtTableToTableEdge> gr = pathesIterator.next(); 00420 00421 // For memory: 00422 // String StartVertex = gr.getStartVertex().getName(); 00423 // String EndVertex = gr.getEndVertex().getName(); 00424 00425 // Get the list of jumps. 00426 List <JgraphtTableToTableEdge> edges = gr.getEdgeList(); 00427 Iterator<JgraphtTableToTableEdge> edgesItearator = edges.iterator(); 00428 ArrayList<Table> tables = new ArrayList<Table>(); 00429 while (edgesItearator.hasNext()) 00430 { 00431 JgraphtTableToTableEdge edge = (JgraphtTableToTableEdge)edgesItearator.next(); 00432 00433 Table src = edge.getSource(); 00434 Table dst = edge.getTarget(); 00435 if (! tables.contains(src)) { tables.add(src); } 00436 if (! tables.contains(dst)) { tables.add(dst); } 00437 } 00438 lr.add((String)exporter.export(db, in_output_confguration, tables)); 00439 } 00440 } 00441 else 00442 { 00443 ArrayList<Table> tables = db.getTables(); 00444 representation = exporter.export(db, in_output_confguration, tables); 00445 } 00446 } 00447 00448 // DEBUG 00449 // System.out.println("export() - exported..."); 00450 } 00451 00452 00453 }