001/*
002 * Copyright c 2018 Rusi Popov, MDA Tools.net All rights reserved.
003 *
004 * This program and the accompanying materials are made available under the terms of the
005 * Eclipse Public License v2.0 which accompanies this distribution, and is available at
006 * http://www.eclipse.org/legal/epl-v20.html
007 */
008package net.mdatools.modelant.uml13.maven.plugin.reverse;
009
010import java.io.File;
011import java.sql.Connection;
012import java.sql.DriverManager;
013import java.sql.SQLException;
014
015import javax.jmi.reflect.RefPackage;
016
017import org.apache.maven.plugin.AbstractMojo;
018import org.apache.maven.plugin.MojoExecutionException;
019import org.apache.maven.plugins.annotations.Execute;
020import org.apache.maven.plugins.annotations.LifecyclePhase;
021import org.apache.maven.plugins.annotations.Mojo;
022import org.apache.maven.plugins.annotations.Parameter;
023
024import net.mdatools.modelant.core.api.Function;
025import net.mdatools.modelant.repository.api.ModelRepository;
026import net.mdatools.modelant.repository.api.ModelRepositoryFactory;
027import net.mdatools.modelant.uml13.reverse.ReverseDatabaseOperation;
028
029/**
030 * Reverse engineering logic for database schemas and storing the results as
031 * UML 1.3 objects. The model produced is in fact a Platform Specific Model, which might need
032 * additional processing and tuning.
033 * Conventions for the model produced:
034 * <ol>
035 * <li>The database column types are converted to DataType instances named: &lt;type
036 * name&gt;[_&lt;column size&gt;[_&lt;column precision&gt;]]. Additionally as tagged values named
037 * {@link net.mdatools.modelant.uml13.metamodel.Convention.TAG_VALUE_DATA_LENGTH} and {@link net.mdatools.modelant.uml13.metamodel.Convention.TAG_VALUE_DATA_TYPE_PRECISION}
038 * these values are bound to the concrete data type.
039 * <li>The {@link net.mdatools.modelant.uml13.metamodel.Convention.TAG_VALUE_DATA_TYPE_PRECISION} tagged value is optional. When not provided, the precision
040 * should be treated as 0
041 * <li>The {@link net.mdatools.modelant.uml13.metamodel.Convention.TAG_VALUE_DATA_LENGTH} tagged value is mandatory.
042 * <li>Any comments found while reverse engineering the database are bound as 'documentation' tagged
043 * values. These tagged values are compatible with the Rose's approach to documentation. They are
044 * optional.
045 * <li>Each attribute pertaining to the table's primary key is bound a {@link net.mdatools.modelant.uml13.metamodel.Convention.TAG_VALUE_PRIMARY_KEY} tagged value
046 * with "Primaty Key" value. Its value is the sequence order of the column in the tible's primary key.
047 * </ol>
048 *
049 * @author Rusi Popov (popovr@mdatools.net)
050 */
051@Mojo(name="database-to-uml13",
052  defaultPhase=LifecyclePhase.COMPILE
053)
054@Execute(phase=LifecyclePhase.COMPILE)
055public class ReverseEngineerDatabaseMojo extends AbstractMojo {
056
057  /**
058   * Database driver-specific URL
059   */
060  @Parameter(required=true)
061  private String url;
062
063  /**
064   * Database user to connect the database
065   */
066  @Parameter(required=true)
067  private String user;
068
069  /**
070   * Database user's password
071   */
072  @Parameter(required=true)
073  private String password;
074
075  /**
076   * The java class name of the database driver to connect the database.
077   * The .jar with that class file should be provided as a dependency of this plugin
078   */
079  @Parameter(required=true)
080  private String driver;
081
082  /**
083   * A comma-separated list of database schemes to reverse engineer into a dingle model
084   */
085  @Parameter(required=true)
086  private String[] schema;
087
088  /**
089   * The name of the file where to export the produced UML 1.3 model in XMI 1.2 format
090   */
091  @Parameter(required=true)
092  private File outputFile;
093
094  /**
095   * The directory where to store the repository files
096   */
097  @Parameter(property="project.build.directory",required=true)
098  private File workDir;
099
100  /**
101   * Performs the reverse engineering of the database by describing the database schema into the
102   * repository provided.
103   * @throws MojoExecutionException
104   */
105  public void execute() throws MojoExecutionException {
106    Connection connection;
107    ModelRepository modelRepository;
108    RefPackage extent;
109    Function<Connection, RefPackage> operation;
110
111    try {
112      modelRepository = ModelRepositoryFactory.construct(workDir);
113      try {
114        Class.forName( driver );
115        connection = DriverManager.getConnection( url, user, password );
116        try {
117          operation = new ReverseDatabaseOperation(modelRepository, schema);
118          extent = operation.execute( connection );
119        } finally {
120          connection.close();
121        }
122        modelRepository.writeExtent( extent,
123                                     outputFile,
124                                     ModelRepository.DEFAULT_XMI_VERSION);
125      } finally {
126        modelRepository.shutdown();
127      }
128    } catch (SQLException e) {
129      throw new MojoExecutionException( "Connecting database:" + url + " with user:" + user + " and password:" + password
130                                        + " caused exception:", e);
131    } catch (ClassNotFoundException e) {
132      throw new MojoExecutionException( "Driver class " + driver + " not found", e);
133
134    } catch (Exception e) {
135      throw new MojoExecutionException( "", e);
136    }
137  }
138}