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.resources; 00024 00025 import java.util.ArrayList; 00026 import java.util.Collections; 00027 import java.util.Enumeration; 00028 import java.util.Hashtable; 00029 import java.util.Iterator; 00030 import java.util.regex.Matcher; 00031 import java.util.regex.Pattern; 00032 import org.dbview.conf.Conf; 00033 import org.dbview.utils.JavaVm; 00034 00035 00036 /** 00037 * This class implements the catalogue of soft foreign key detectors. 00038 * @author Denis Beurive 00039 */ 00040 public class SotfForeignKeyDetectorCatalog 00041 { 00042 /** 00043 * Name of the <i>property</i> that references the JAR file that contains the implementation of all soft foreign key detectors. 00044 * @remark This property is defined in the configuration file of the software. 00045 * The software's configuration file is a "property file" (see file "resources.properties"). 00046 */ 00047 private static final String __FJ_RESOURCE_NAME = "sotfForeignKeyDetectors"; // __CONFPROP__ 00048 00049 /** 00050 * This hash table lists all available soft foreign key detectors. 00051 * <ul> 00052 * <li>Key: The name of the soft foreign key detector.</li> 00053 * <li>Value: The name of the package that contains the soft foreign key detector.</li> 00054 * </ul> 00055 */ 00056 private Hashtable<String, String> __matchers = null; 00057 00058 /** 00059 * Create the catalogue of soft foreign key detectors. 00060 * @throws Exception 00061 */ 00062 public SotfForeignKeyDetectorCatalog() throws SotfForeignKeyDetectorException 00063 { 00064 ArrayList<String> jar_content = null; 00065 this.__matchers = new Hashtable<String, String>(); 00066 00067 // WARNING !!!!! 00068 // 00069 // There is a relation between the following line and the ANT script (build.xml): 00070 // <property name="dir.pkg.fk" value="org/dbview/addons/input/resources/fk"/> 00071 // 00072 Pattern p_matchers = Pattern.compile("^(.+\\.resources\\.softforeignkeydetectors)\\.([^\\.]+)\\.class$"); // __BUILD_CONF__ 00073 00074 // Load the JAR file that contains all (soft) foreign key detectors. 00075 try 00076 { 00077 jar_content = JavaVm.listJar(Conf.get(SotfForeignKeyDetectorCatalog.__FJ_RESOURCE_NAME)); 00078 } 00079 catch (Exception e) 00080 { 00081 throw new SotfForeignKeyDetectorException("An error occurred during the initialization of the catalogue: " + e.getClass().getName() + ": " + e.getMessage() ); 00082 } 00083 00084 // Locate detectors. 00085 Iterator<String> i = jar_content.iterator(); 00086 while (i.hasNext()) 00087 { 00088 String entry = i.next().replaceAll("/|\\\\", "."); 00089 // System.out.println("> " + entry); 00090 Matcher m_matcher = p_matchers.matcher(entry); 00091 00092 if (m_matcher.matches()) 00093 { 00094 // System.out.println("Matched!"); 00095 String matcher_package = m_matcher.group(1); 00096 String matcher_name = m_matcher.group(2); 00097 // System.out.println(matcher_package + " - " + matcher_name); 00098 00099 // Make sure that the detector's name starts with an upper case letter. 00100 if (! matcher_name.matches("^[A-Z].*$")) { throw new SotfForeignKeyDetectorException("A (soft) foreign key matcher must start with an upper case letter. Invalid name: " + matcher_name + "."); } 00101 00102 if (! this.__matchers.containsKey(matcher_name)) { this.__matchers.put(matcher_name, matcher_package); } 00103 else 00104 { 00105 // This case should not happen, since a JAR contains distinct entries. 00106 throw new SotfForeignKeyDetectorException("Unexpected error : The JAR that contains (soft) foreign key matchers presents duplicated entries."); 00107 } 00108 } 00109 } 00110 } 00111 00112 /** 00113 * This method returns the list of all available soft foreign key detectors. 00114 * @return The method returns the list of all available soft foreign key detectors. 00115 * @throws Exception 00116 */ 00117 public Enumeration<String> getMatchers() 00118 { 00119 Enumeration<String> e = this.__matchers.keys(); 00120 ArrayList<String> r = new ArrayList<String>(); 00121 00122 while (e.hasMoreElements()) { r.add(e.nextElement()); } 00123 00124 return Collections.enumeration(r); 00125 } 00126 00127 /** 00128 * The method produces a string that represents the catalogue. 00129 * 00130 * @return The method returns a string that represents the catalogue. 00131 */ 00132 @Override 00133 public String toString() 00134 { 00135 try 00136 { 00137 String r = ""; 00138 Enumeration<String> matchers = this.getMatchers(); 00139 00140 while (matchers.hasMoreElements()) 00141 { 00142 String matcher_name = matchers.nextElement(); 00143 String package_name = this.__matchers.get(matcher_name); 00144 00145 r = r.concat("[Matcher] " + matcher_name + System.getProperty("line.separator")); 00146 r = r.concat("\tCLI name: " + SotfForeignKeyDetectorCatalog.toCli(matcher_name)) + System.getProperty("line.separator"); 00147 r = r.concat("\tPackage: " + package_name + System.getProperty("line.separator")); 00148 } 00149 00150 return r; 00151 } 00152 catch (Exception e) 00153 { 00154 return "Could not generate textual representation of the catalogue: " + e.getMessage(); 00155 } 00156 } 00157 00158 /** 00159 * This method returns an instance of a soft foreign key detector, identified by its <i>real</i> (as opposed to "CLI") name. 00160 * @param in_real_name The CLI name of the soft foreign key detector. 00161 * @return The method returns an instance of a soft foreign key detector, identified the given (real) name. 00162 * @throws SotfForeignKeyDetectorException 00163 */ 00164 public AbstractSotfForeignKeyDetector getFkMatcherByName(String in_real_name) throws SotfForeignKeyDetectorException 00165 { 00166 String package_name = this.__matchers.get(in_real_name); 00167 00168 if (null == package_name) 00169 { throw new SotfForeignKeyDetectorException("The soft foreign key detector \"" + in_real_name + "\" does not exist."); } 00170 00171 String class_name = package_name + "." + in_real_name; 00172 00173 try 00174 { 00175 return (AbstractSotfForeignKeyDetector)Class.forName(class_name).newInstance(); 00176 } 00177 catch (ExceptionInInitializerError e) 00178 { 00179 throw new SotfForeignKeyDetectorException("Unexpected error. This error should not happen, unless you modify the software. " + e.getClass().getName() + ": " + e.getMessage()); 00180 } 00181 catch (ClassNotFoundException e) 00182 { 00183 throw new SotfForeignKeyDetectorException("Unexpected error. This error should not happen, unless you modify the software. " + e.getClass().getName() + ": " + e.getMessage()); 00184 } 00185 catch (LinkageError e) 00186 { 00187 throw new SotfForeignKeyDetectorException("Unexpected error. This error should not happen, unless you modify the software. " + e.getClass().getName() + ": " + e.getMessage()); 00188 } 00189 catch (IllegalAccessException e) 00190 { 00191 throw new SotfForeignKeyDetectorException("Unexpected error. This error should not happen, unless you modify the software. " + e.getClass().getName() + ": " + e.getMessage()); 00192 } 00193 catch (InstantiationException e) 00194 { 00195 throw new SotfForeignKeyDetectorException("Unexpected error. This error should not happen, unless you modify the software. " + e.getClass().getName() + ": " + e.getMessage()); 00196 } 00197 catch (SecurityException e) 00198 { 00199 throw new SotfForeignKeyDetectorException("Unexpected error. This error should not happen, unless you modify the software. " + e.getClass().getName() + ": " + e.getMessage()); 00200 } 00201 } 00202 00203 /** 00204 * This method returns an instance of a soft foreign key detector, identified by its <i>CLI</i> (Command Line Interface) name. 00205 * @param in_cli_name The CLI name of the soft foreign key matcher. 00206 * @return The method returns an instance of a soft foreign key matcher, identified the given CLI name. 00207 * @throws SotfForeignKeyDetectorException 00208 */ 00209 public AbstractSotfForeignKeyDetector getFkMatcherByCliName(String in_cli_name) throws SotfForeignKeyDetectorException 00210 { 00211 String real_name = SotfForeignKeyDetectorCatalog.fromCli(in_cli_name); 00212 return this.getFkMatcherByName(real_name); 00213 } 00214 00215 /** 00216 * This method returns the description of a given soft foreign key detector, given its real name. 00217 * @param in_name Name of the soft foreign key detector. 00218 * @return The method returns the description of a given soft foreign key detector. 00219 * @throws SotfForeignKeyDetectorException 00220 */ 00221 public String getFkMatcherDescriptionByName(String in_name) throws SotfForeignKeyDetectorException 00222 { 00223 AbstractSotfForeignKeyDetector m = this.getFkMatcherByName(in_name); 00224 return m.description(); 00225 } 00226 00227 /** 00228 * This method returns the description of a given soft foreign key detector, given its CLI name. 00229 * @param in_cli_name CLI name of the soft foreign key detector. 00230 * @return The method returns the description of a given soft foreign key detector. 00231 * @throws SotfForeignKeyDetectorException 00232 */ 00233 public String getFkMatcherDescriptionByCliName(String in_cli_name) throws SotfForeignKeyDetectorException 00234 { 00235 return this.getFkMatcherDescriptionByName(SotfForeignKeyDetectorCatalog.fromCli(in_cli_name)); 00236 } 00237 00238 /** 00239 * This method returns the real name of a soft foreign key detector, given the CLI name of the detector. 00240 * @param in_cli_name CLI name of the detector. 00241 * @return The method returns the real name of a soft foreign key detector. 00242 */ 00243 public static String fromCli(String in_cli_name) 00244 { 00245 return org.dbview.utils.Strings.dashToUpperCamelCase(in_cli_name); 00246 } 00247 00248 /** 00249 * This method returns the CLI name of a soft foreign key detector, given the real name of the detector. 00250 * @param in_real_name Ream name of the detector. 00251 * @return The method returns the CLI name of a soft foreign key detector. 00252 */ 00253 public static String toCli(String in_real_name) 00254 { 00255 return org.dbview.utils.Strings.upperCamelCaseToDash(in_real_name); 00256 } 00257 }