001package org.andromda.schema2xmi;
002
003import org.andromda.core.common.AndroMDALogger;
004import org.andromda.core.common.XmlObjectFactory;
005import org.apache.commons.cli.CommandLine;
006import org.apache.commons.cli.CommandLineParser;
007import org.apache.commons.cli.HelpFormatter;
008import org.apache.commons.cli.Option;
009import org.apache.commons.cli.Options;
010import org.apache.commons.cli.ParseException;
011import org.apache.commons.cli.PosixParser;
012
013
014/**
015 * Converts a database schema to an XMI document.
016 *
017 * @author Chad Brandon
018 */
019public class Schema2XMI
020{
021    private static Options options;
022
023    /**
024     * The command to display help
025     */
026    private static final String HELP = "h";
027
028    /**
029     * The command line argument to specify the XMI version that will be
030     * producted.
031     */
032    private static final String XMI_VERSION = "x";
033
034    /**
035     * The command line argument to specify the input model file.
036     */
037    private static final String INPUT_MODEL = "i";
038
039    /**
040     * The command line argument to specify the JDBC driver class
041     */
042    private static final String DRIVER = "d";
043
044    /**
045     * The command line argument to specify the schema user.
046     */
047    private static final String USER = "u";
048
049    /**
050     * The command line argument to specify the schema user password.
051     */
052    private static final String PASSWORD = "p";
053
054    /**
055     * The command line argument to specify the connection URL.
056     */
057    private static final String CONNECTION_URL = "c";
058
059    /**
060     * The command line argument to specify the transformed output file.
061     */
062    private static final String OUTPUT_MODEL = "o";
063
064    /**
065     * The command line argument specifying the URI to the type mappings file.
066     */
067    private static final String MAPPINGS = "m";
068
069    /**
070     * The command line argument specifying the package to which the model
071     * element will be generated.
072     */
073    private static final String PACKAGE = "P";
074
075    /**
076     * The command line argument specifying the name of the schema where the
077     * table resides.
078     */
079    private static final String SCHEMA = "s";
080
081    /**
082     * The command line argument specifying the tables names to match on
083     */
084    private static final String TABLE_PATTERN = "t";
085
086    /**
087     * The command line argument specifying the attribute names pattern to match on.
088     */
089    private static final String COLUMN_PATTERN = "a";
090
091    /**
092     * The command line argument specifying the class stereotype name.
093     */
094    private static final String CLASS_STEREOTYPES = "C";
095
096    /**
097     * The command line argument specifying the identifier stereotype name.
098     */
099    private static final String IDENTIFIER_STEREOTYPES = "I";
100
101    /**
102     * The command line argument specifiying the name of the tagged value to use
103     * for tagged column names.
104     */
105    private static final String TABLE_TAGGEDVALUE = "V";
106
107    /**
108     * The command line argument specifiying the name of the tagged value to use
109     * for tagged column names.
110     */
111    private static final String COLUMN_TAGGEDVALUE = "v";
112
113    /**
114     * The command line argument specifiying additional tagged values to add to
115     * each column attribute.
116     */
117    private static final String ATTRIBUTE_TAGGEDVALUES = "A";
118
119    /**
120     * Configure the CLI options.
121     */
122    static
123    {
124        try
125        {
126            AndroMDALogger.initialize();
127
128            // turn off validation because of the incorrect parsers
129            // in the JDK
130            XmlObjectFactory.setDefaultValidating(false);
131        }
132        catch (Throwable th)
133        {
134            th.printStackTrace();
135        }
136
137        options = new Options();
138
139        Option option = new Option(HELP, false, "Display help information");
140        option.setLongOpt("help");
141        options.addOption(option);
142
143        option = new Option(XMI_VERSION, true, "Specifies the XMI version that will be produced");
144        option.setLongOpt("xmi");
145        options.addOption(option);
146
147        option = new Option(INPUT_MODEL, true, "Input model file (to which model elements will be added)");
148        option.setLongOpt("input");
149        options.addOption(option);
150
151        option = new Option(DRIVER, true, "JDBC driver class");
152        option.setLongOpt("driver");
153        options.addOption(option);
154
155        option = new Option(CONNECTION_URL, true, "JDBC connection URL");
156        option.setLongOpt("connectionUrl");
157        options.addOption(option);
158
159        option = new Option(USER, true, "Schema user name");
160        option.setLongOpt("user");
161        options.addOption(option);
162
163        option = new Option(PASSWORD, true, "Schema user password");
164        option.setLongOpt("password");
165        options.addOption(option);
166
167        option = new Option(MAPPINGS, true, "The type mappings URI (i.e. file:${basedir}/DataypeMappings.xml)");
168        option.setLongOpt("mappings");
169        options.addOption(option);
170
171        option = new Option(SCHEMA, true, "The name of the schema where the tables can be found");
172        option.setLongOpt("schema");
173        options.addOption(option);
174
175        option = new Option(TABLE_PATTERN, true, "The table name pattern of tables to process (regular expression)");
176        option.setLongOpt("tablePattern");
177        options.addOption(option);
178
179        option = new Option(COLUMN_PATTERN, true, "The column name pattern of columns to process (regular expression)");
180        option.setLongOpt("columnPattern");
181        options.addOption(option);
182
183        option = new Option(PACKAGE, true, "The package to output classifiers");
184        option.setLongOpt("package");
185        options.addOption(option);
186
187        option =
188            new Option(CLASS_STEREOTYPES, true, "Comma separated list of stereotype names to add to the created class");
189        option.setLongOpt("classStereotypes");
190        options.addOption(option);
191
192        option =
193            new Option(
194                IDENTIFIER_STEREOTYPES, true, "Comma separated list of stereotype names to add to any class identifiers");
195        option.setLongOpt("identifierStereotypes");
196        options.addOption(option);
197
198        option = new Option(TABLE_TAGGEDVALUE, true, "The tagged value to use for storing the table name");
199        option.setLongOpt("tableTaggedValue");
200        options.addOption(option);
201
202        option = new Option(COLUMN_TAGGEDVALUE, true, "The tagged value to use for storing the column name");
203        option.setLongOpt("columnTaggedValue");
204        options.addOption(option);
205
206        option =
207            new Option(OUTPUT_MODEL, true, "Output location to which the result of the transformation will be written");
208        option.setLongOpt("output");
209        options.addOption(option);
210
211        option = new Option(ATTRIBUTE_TAGGEDVALUES, true, "The tagged value(s) added to each attribute generated. Comma separated list (i.e. @tag1=val1,@tag2=val2)");
212        option.setLongOpt("attributeTaggedValues");
213        options.addOption(option);
214
215    }
216
217    /**
218     * Display usage information based upon current command-line option
219     * configuration.
220     */
221    public static void displayHelp()
222    {
223        HelpFormatter formatter = new HelpFormatter();
224        formatter.printHelp(Schema2XMI.class.getName() + " [options] ...]]", "\nOptions:", options, "\n");
225    }
226
227    /**
228     * Parse a string-array of command-line arguments.
229     * <p>
230     * This will parse the arguments against the configured schema2xmi
231     * command-line options, and return a <code>CommandLine</code> object from
232     * which we can retrieve the command like options.
233     * </p>
234     *
235     * @see <a href="http://jakarta.apache.org/commons/cli/">CLI </a>
236     * @param args The command-line arguments to parse.
237     * @return The <code>CommandLine</code> result.
238     * @throws ParseException If an error occurs while parsing the command-line
239     *         options.
240     */
241    public CommandLine parseCommands(String[] args)
242        throws ParseException
243    {
244        CommandLineParser parser = new PosixParser();
245        return parser.parse(options, args);
246    }
247
248    /**
249     * @param args
250     */
251    public static void main(String[] args)
252    {
253        Schema2XMI schema2Xmi = new Schema2XMI();
254        try
255        {
256            CommandLine commandLine = schema2Xmi.parseCommands(args);
257            if (
258                commandLine.hasOption(HELP) ||
259                !(
260                    commandLine.hasOption(OUTPUT_MODEL) && commandLine.hasOption(DRIVER) &&
261                    commandLine.hasOption(CONNECTION_URL) && commandLine.hasOption(USER) &&
262                    commandLine.hasOption(PASSWORD)
263                ))
264            {
265                Schema2XMI.displayHelp();
266            }
267            else
268            {
269                String inputModel = commandLine.getOptionValue(INPUT_MODEL);
270                SchemaTransformer transformer =
271                    new SchemaTransformer(
272                        commandLine.getOptionValue(DRIVER),
273                        commandLine.getOptionValue(CONNECTION_URL),
274                        commandLine.getOptionValue(USER),
275                        commandLine.getOptionValue(PASSWORD));
276
277                // set the extra options
278                transformer.setXmiVersion(commandLine.getOptionValue(XMI_VERSION));
279                transformer.setTypeMappings(commandLine.getOptionValue(MAPPINGS));
280                transformer.setPackageName(commandLine.getOptionValue(PACKAGE));
281                transformer.setSchema(commandLine.getOptionValue(SCHEMA));
282                transformer.setTableNamePattern(commandLine.getOptionValue(TABLE_PATTERN));
283                transformer.setColumnNamePattern(commandLine.getOptionValue(COLUMN_PATTERN));
284                transformer.setClassStereotypes(commandLine.getOptionValue(CLASS_STEREOTYPES));
285                transformer.setIdentifierStereotypes(commandLine.getOptionValue(IDENTIFIER_STEREOTYPES));
286                transformer.setTableTaggedValue(commandLine.getOptionValue(TABLE_TAGGEDVALUE));
287                transformer.setColumnTaggedValue(commandLine.getOptionValue(COLUMN_TAGGEDVALUE));
288                transformer.setAttributeTaggedValues(commandLine.getOptionValue(ATTRIBUTE_TAGGEDVALUES));
289
290                String outputLocation = commandLine.getOptionValue(OUTPUT_MODEL);
291                transformer.transform(inputModel, outputLocation);
292            }
293        }
294        catch (Throwable throwable)
295        {
296            throwable = getRootCause(throwable);
297            throwable.printStackTrace();
298        }
299    }
300
301    private static Throwable getRootCause(Throwable th)
302    {
303        Throwable cause = th;
304        if (cause.getCause() != null)
305        {
306            cause = cause.getCause();
307            cause = getRootCause(cause);
308        }
309        return cause;
310    }
311}