ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akuznet...@apache.org
Subject [6/8] incubator-ignite git commit: # IGNITE-329 Renaming.
Date Tue, 10 Mar 2015 10:58:50 GMT
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9cf45b43/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/MessageBox.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/MessageBox.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/MessageBox.java
new file mode 100644
index 0000000..cf6a705
--- /dev/null
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/MessageBox.java
@@ -0,0 +1,246 @@
+/*
+ * 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 org.apache.ignite.schema.ui;
+
+import javafx.event.*;
+import javafx.geometry.*;
+import javafx.scene.control.*;
+import javafx.scene.layout.*;
+import javafx.stage.*;
+
+import java.util.logging.*;
+
+import static org.apache.ignite.schema.ui.Controls.*;
+
+/**
+ * Message box functionality.
+ */
+public class MessageBox extends ModalDialog {
+    /** Logger. */
+    private static final Logger log = Logger.getLogger(MessageBox.class.getName());
+
+    /** Message box type. */
+    private enum MessageType {
+        /** Information. */
+        INFO,
+        /** Warning. */
+        WARN,
+        /** Error. */
+        ERROR,
+        /** Confirm. */
+        CONFIRM,
+        /** Confirm with cancel option. */
+        CANCELLABLE_CONFIRM
+    }
+
+    /** Message box type. */
+    public enum Result {
+        /** Return value if YES is chosen. */
+        YES,
+        /** Return value if YES_TO_ALL is chosen. */
+        YES_TO_ALL,
+        /** Return value if NO is chosen. */
+        NO,
+        /** Return value if NO_TO_ALL is chosen. */
+        NO_TO_ALL,
+        /** Return value if CANCEL is chosen. */
+        CANCEL
+    }
+
+    /** Dialog result. */
+    private Result res = Result.CANCEL;
+
+    /**
+     * Create message box.
+     *
+     * @param owner Owner window.
+     * @param type Message box type.
+     * @param msg Message to show.
+     * @param rememberChoice If {@code true} then add "Remember choice" check box.
+     */
+    private MessageBox(Stage owner, MessageType type, String msg, final boolean rememberChoice) {
+        super(owner, 480, 180);
+
+        String title;
+        String iconFile;
+
+        switch (type) {
+            case WARN:
+                title = "Warning";
+                iconFile = "sign_warning";
+                break;
+
+            case ERROR:
+                title = "Error";
+                iconFile = "error";
+                break;
+
+            case CONFIRM:
+            case CANCELLABLE_CONFIRM:
+                title = "Confirmation";
+                iconFile = "question";
+                break;
+
+            default:
+                title = "Information";
+                iconFile = "information";
+                break;
+        }
+
+        setTitle(title);
+        initStyle(StageStyle.UTILITY);
+        initModality(Modality.APPLICATION_MODAL);
+        initOwner(owner);
+        setResizable(false);
+
+        GridPaneEx contentPnl = paneEx(10, 10, 0, 10);
+
+        contentPnl.addColumn();
+        contentPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+
+        contentPnl.add(hBox(0, true, imageView(iconFile, 48)));
+
+        TextArea ta = new TextArea(msg);
+        ta.setEditable(false);
+        ta.setWrapText(true);
+        ta.setFocusTraversable(false);
+
+        contentPnl.add(ta);
+
+        final CheckBox rememberChoiceCh = checkBox("Remember choice", "", false);
+
+        if (rememberChoice) {
+            contentPnl.skip(1);
+            contentPnl.add(rememberChoiceCh);
+        }
+
+        HBox btns = hBox(10, true);
+        btns.setAlignment(Pos.CENTER);
+
+        if (MessageType.CONFIRM == type || MessageType.CANCELLABLE_CONFIRM == type) {
+            res = Result.NO;
+
+            btns.getChildren().addAll(
+                button("Yes", "Approve the request", new EventHandler<ActionEvent>() {
+                    @Override public void handle(ActionEvent e) {
+                        res = rememberChoice && rememberChoiceCh.isSelected() ? Result.YES_TO_ALL : Result.YES;
+
+                        close();
+                    }
+                }),
+                button("No", "Reject the request", new EventHandler<ActionEvent>() {
+                    @Override public void handle(ActionEvent e) {
+                        res = rememberChoice && rememberChoiceCh.isSelected() ? Result.NO_TO_ALL : Result.NO;
+
+                        close();
+                    }
+                }));
+
+            if (MessageType.CANCELLABLE_CONFIRM == type)
+                btns.getChildren().addAll(
+                    button("Cancel", "Cancel the request", new EventHandler<ActionEvent>() {
+                        @Override public void handle(ActionEvent e) {
+                            res = Result.CANCEL;
+
+                            close();
+                        }
+                    }));
+        }
+        else
+            btns.getChildren().add(button("OK", "Close dialog", new EventHandler<ActionEvent>() {
+                @Override public void handle(ActionEvent e) {
+                    close();
+                }
+            }));
+
+        setScene(scene(borderPane(null, contentPnl, btns, null, null)));
+    }
+
+    /**
+     * Show message in modal dialog.
+     *
+     * @param owner Owner window.
+     * @param type Message box type.
+     * @param msg Message to show.
+     * @return Option selected by the user.
+     */
+    private static Result showDialog(Stage owner, MessageType type, String msg, boolean rememberChoice) {
+        MessageBox dlg = new MessageBox(owner, type, msg, rememberChoice);
+
+        dlg.showModal();
+
+        return dlg.res;
+    }
+
+    /**
+     * Show confirmation dialog.
+     *
+     * @param owner Owner window.
+     * @param msg Message to show.
+     * @return {@code true} If user confirm.
+     */
+    public static boolean confirmDialog(Stage owner, String msg) {
+        return showDialog(owner, MessageType.CONFIRM, msg, false) == Result.YES;
+    }
+
+    /**
+     * Show confirmation dialog.
+     *
+     * @param owner Owner window.
+     * @param msg Message to show.
+     * @return User confirmation result.
+     */
+    public static Result confirmRememberChoiceDialog(Stage owner, String msg) {
+        return showDialog(owner, MessageType.CANCELLABLE_CONFIRM, msg, true);
+    }
+
+    /**
+     * Show information dialog.
+     *
+     * @param owner Owner window.
+     * @param msg Message to show.
+     */
+    public static void informationDialog(Stage owner, String msg) {
+        showDialog(owner, MessageType.INFO, msg, false);
+    }
+
+    /**
+     * Show warning dialog.
+     *
+     * @param owner Owner window.
+     * @param msg Message to show.
+     */
+    public static void warningDialog(Stage owner, String msg) {
+        showDialog(owner, MessageType.WARN, msg, false);
+    }
+
+    /**
+     * Show error dialog.
+     *
+     * @param owner Owner window.
+     * @param msg Error message to show.
+     * @param e Optional exception to show.
+     */
+    public static void errorDialog(Stage owner, String msg, Throwable e) {
+        log.log(Level.SEVERE, msg, e);
+
+        String exMsg = e != null ? (e.getMessage() != null ? e.getMessage() : e.getClass().getName()) : null;
+
+        showDialog(owner, MessageType.ERROR, exMsg != null ? msg + "\n" + exMsg : msg, false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9cf45b43/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java
new file mode 100644
index 0000000..6d0acb7
--- /dev/null
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.apache.ignite.schema.ui;
+
+import javafx.stage.*;
+
+/**
+ * Abstract base modal dialog.
+ */
+public abstract class ModalDialog extends Stage {
+    /** Owner window. */
+    protected final Stage owner;
+
+    /**
+     * @param owner Owner window.
+     * @param width Window width.
+     * @param height Window height.
+     */
+    protected ModalDialog(Stage owner, int width, int height) {
+        this.owner = owner;
+
+        this.setWidth(width);
+        this.setHeight(height);
+    }
+
+    /**
+     * Show modal dialog.
+     */
+    protected void showModal() {
+        setX(owner.getX() + owner.getWidth() / 2 - getWidth() / 2);
+        setY(owner.getY() + owner.getHeight() / 2 - getHeight() / 2);
+
+        showAndWait();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9cf45b43/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
new file mode 100644
index 0000000..7976543
--- /dev/null
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
@@ -0,0 +1,1615 @@
+/*
+ * 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 org.apache.ignite.schema.ui;
+
+import javafx.application.*;
+import javafx.beans.value.*;
+import javafx.collections.*;
+import javafx.concurrent.*;
+import javafx.event.*;
+import javafx.geometry.*;
+import javafx.scene.*;
+import javafx.scene.control.*;
+import javafx.scene.layout.*;
+import javafx.stage.*;
+import javafx.util.*;
+import org.apache.ignite.schema.generator.*;
+import org.apache.ignite.schema.model.*;
+import org.apache.ignite.schema.parser.*;
+
+import java.io.*;
+import java.net.*;
+import java.sql.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import static javafx.embed.swing.SwingFXUtils.*;
+import static org.apache.ignite.schema.ui.Controls.*;
+
+/**
+ * Schema load application.
+ */
+@SuppressWarnings("UnnecessaryFullyQualifiedName")
+public class SchemaImportApp extends Application {
+    /** Presets for database settings. */
+    private static class Preset {
+        /** Name in preferences. */
+        private String pref;
+
+        /** RDBMS name to show on screen. */
+        private String name;
+
+        /** Path to JDBC driver jar. */
+        private String jar;
+
+        /** JDBC driver class name. */
+        private String drv;
+
+        /** JDBC URL. */
+        private String url;
+
+        /** User name. */
+        private String user;
+
+        /**
+         * Preset constructor.
+         *
+         * @param pref Name in preferences.
+         * @param name RDBMS name to show on screen.
+         * @param jar Path to JDBC driver jar..
+         * @param drv JDBC driver class name.
+         * @param url JDBC URL.
+         * @param user User name.
+         */
+        Preset(String pref, String name, String jar, String drv, String url, String user) {
+            this.pref = pref;
+            this.name = name;
+            this.jar = jar;
+            this.drv = drv;
+            this.url = url;
+            this.user = user;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return name;
+        }
+    }
+
+    /** Default presets for popular databases. */
+    private final Preset[] presets = {
+        new Preset("h2", "H2 Database", "h2.jar", "org.h2.Driver", "jdbc:h2:[database]", "sa"),
+        new Preset("db2", "DB2", "db2jcc4.jar", "com.ibm.db2.jcc.DB2Driver", "jdbc:db2://[host]:[port]/[database]",
+            "db2admin"),
+        new Preset("oracle", "Oracle", "ojdbc6.jar", "oracle.jdbc.OracleDriver",
+            "jdbc:oracle:thin:@[host]:[port]:[database]", "system"),
+        new Preset("mysql", "MySQL", "mysql-connector-java-5-bin.jar", "com.mysql.jdbc.Driver",
+            "jdbc:mysql://[host]:[port]/[database]", "root"),
+        new Preset("mssql", "Microsoft SQL Server", "sqljdbc41.jar", "com.microsoft.sqlserver.jdbc.SQLServerDriver",
+            "jdbc:sqlserver://[host]:[port][;databaseName=database]", "sa"),
+        new Preset("posgresql", "PostgreSQL", "postgresql-9.3.jdbc4.jar", "org.postgresql.Driver",
+            "jdbc:postgresql://[host]:[port]/[database]", "sa"),
+        new Preset("custom", "Custom server...", "custom-jdbc.jar", "org.custom.Driver", "jdbc:custom", "sa")
+    };
+
+    /** */
+    private Stage owner;
+
+    /** */
+    private BorderPane rootPane;
+
+    /** Header pane. */
+    private BorderPane hdrPane;
+
+    /** */
+    private HBox dbIcon;
+
+    /** */
+    private HBox genIcon;
+
+    /** */
+    private Label titleLb;
+
+    /** */
+    private Label subTitleLb;
+
+    /** */
+    private Button prevBtn;
+
+    /** */
+    private Button nextBtn;
+
+    /** */
+    private ComboBox<Preset> rdbmsCb;
+
+    /** */
+    private TextField jdbcDrvJarTf;
+
+    /** */
+    private TextField jdbcDrvClsTf;
+
+    /** */
+    private TextField jdbcUrlTf;
+
+    /** */
+    private TextField userTf;
+
+    /** */
+    private PasswordField pwdTf;
+
+    /** */
+    private ComboBox<String> parseCb;
+
+    /** */
+    private GridPaneEx connPnl;
+
+    /** */
+    private StackPane connLayerPnl;
+
+    /** */
+    private TableView<PojoDescriptor> pojosTbl;
+
+    /** */
+    private TableView<PojoField> fieldsTbl;
+
+    /** */
+    private Node curTbl;
+
+    /** */
+    private TextField outFolderTf;
+
+    /** */
+    private TextField pkgTf;
+
+    /** */
+    private CheckBox pojoConstructorCh;
+
+    /** */
+    private CheckBox pojoIncludeKeysCh;
+
+    /** */
+    private CheckBox xmlSingleFileCh;
+
+    /** */
+    private TextField regexTf;
+
+    /** */
+    private TextField replaceTf;
+
+    /** */
+    private GridPaneEx genPnl;
+
+    /** */
+    private StackPane genLayerPnl;
+
+    /** */
+    private ProgressIndicator pi;
+
+    /** List with POJOs descriptors. */
+    private ObservableList<PojoDescriptor> pojos = FXCollections.emptyObservableList();
+
+    /** Currently selected POJO. */
+    private PojoDescriptor curPojo;
+
+    /** */
+    private final Map<String, Driver> drivers = new HashMap<>();
+
+    /** Application preferences. */
+    private final Properties prefs = new Properties();
+
+    /** File path for storing on local file system. */
+    private final File prefsFile = new File(System.getProperty("user.home"), ".ignite-schema-load");
+
+    /** Empty POJO fields model. */
+    private static final ObservableList<PojoField> NO_FIELDS = FXCollections.emptyObservableList();
+
+    /** */
+    private final ExecutorService exec = Executors.newSingleThreadExecutor(new ThreadFactory() {
+        @Override public Thread newThread(Runnable r) {
+            Thread t = new Thread(r, "ignite-schema-load-worker");
+
+            t.setDaemon(true);
+
+            return t;
+        }
+    });
+
+    /**
+     * Lock UI before start long task.
+     *
+     * @param layer Stack pane to add progress indicator.
+     * @param controls Controls to disable.
+     */
+    private void lockUI(StackPane layer, Node... controls) {
+        for (Node control : controls)
+            control.setDisable(true);
+
+        layer.getChildren().add(pi);
+    }
+
+    /**
+     * Unlock UI after long task finished.
+     *
+     * @param layer Stack pane to remove progress indicator.
+     * @param controls Controls to enable.
+     */
+    private void unlockUI(StackPane layer, Node... controls) {
+        for (Node control : controls)
+            control.setDisable(false);
+
+        layer.getChildren().remove(pi);
+    }
+
+    /**
+     * Perceptual delay to avoid UI flickering.
+     *
+     * @param started Time when background progress started.
+     */
+    private void perceptualDelay(long started) {
+        long delta = System.currentTimeMillis() - started;
+
+        if (delta < 500)
+            try {
+                Thread.sleep(500 - delta);
+            }
+            catch (InterruptedException ignored) {
+                Thread.currentThread().interrupt();
+            }
+    }
+
+    /**
+     * Fill tree with database metadata.
+     */
+    private void fill() {
+        lockUI(connLayerPnl, connPnl, nextBtn);
+
+        final String jdbcDrvJarPath = jdbcDrvJarTf.getText().trim();
+
+        final String jdbcDrvCls = jdbcDrvClsTf.getText();
+
+        final String jdbcUrl = jdbcUrlTf.getText();
+
+        String user = userTf.getText().trim();
+
+        String pwd = pwdTf.getText().trim();
+
+        final Properties jdbcInfo = new Properties();
+
+        if (!user.isEmpty())
+            jdbcInfo.put("user", user);
+
+        if (!pwd.isEmpty())
+            jdbcInfo.put("password", pwd);
+
+        final boolean tblsOnly = parseCb.getSelectionModel().getSelectedIndex() == 0;
+
+        Runnable task = new Task<Void>() {
+            /** {@inheritDoc} */
+            @Override protected Void call() throws Exception {
+                long started = System.currentTimeMillis();
+
+                try (Connection conn = connect(jdbcDrvJarPath, jdbcDrvCls, jdbcUrl, jdbcInfo)) {
+                    pojos = DatabaseMetadataParser.parse(conn, tblsOnly);
+                }
+
+                perceptualDelay(started);
+
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override protected void succeeded() {
+                super.succeeded();
+
+                pojosTbl.setItems(pojos);
+
+                if (!pojos.isEmpty())
+                    pojosTbl.getSelectionModel().clearAndSelect(0);
+
+                curTbl = pojosTbl;
+
+                pojosTbl.requestFocus();
+
+                unlockUI(connLayerPnl, connPnl, nextBtn);
+
+                hdrPane.setLeft(genIcon);
+
+                titleLb.setText("Generate XML And POJOs");
+                subTitleLb.setText(jdbcUrlTf.getText());
+
+                rootPane.setCenter(genLayerPnl);
+
+                prevBtn.setDisable(false);
+                nextBtn.setText("Generate");
+                tooltip(nextBtn, "Generate XML and POJO files");
+            }
+
+            /** {@inheritDoc} */
+            @Override protected void cancelled() {
+                super.cancelled();
+
+                unlockUI(connLayerPnl, connPnl, nextBtn);
+            }
+
+            /** {@inheritDoc} */
+            @Override protected void failed() {
+                super.succeeded();
+
+                unlockUI(connLayerPnl, connPnl, nextBtn);
+
+                MessageBox.errorDialog(owner, "Failed to get tables list from database.", getException());
+            }
+        };
+
+        exec.submit(task);
+    }
+
+    /**
+     * Generate XML and POJOs.
+     */
+    private void generate() {
+        final Collection<PojoDescriptor> selPojos = checkedPojos();
+
+        if (selPojos.isEmpty()) {
+            MessageBox.warningDialog(owner, "Please select tables to generate XML and POJOs files!");
+
+            return;
+        }
+
+        lockUI(genLayerPnl, genPnl, prevBtn, nextBtn);
+
+        final String outFolder = outFolderTf.getText();
+
+        final String pkg = pkgTf.getText();
+
+        final File destFolder = new File(outFolder);
+
+        final boolean constructor = pojoConstructorCh.isSelected();
+
+        final boolean includeKeys = pojoIncludeKeysCh.isSelected();
+
+        final boolean singleXml = xmlSingleFileCh.isSelected();
+
+        Runnable task = new Task<Void>() {
+            private void checkEmpty(final PojoDescriptor pojo, boolean selected, String msg) {
+                if (!selected) {
+                    Platform.runLater(new Runnable() {
+                        @Override public void run() {
+                            TableView.TableViewSelectionModel<PojoDescriptor> selMdl = pojosTbl.getSelectionModel();
+
+                            selMdl.clearSelection();
+                            selMdl.select(pojo);
+                            pojosTbl.scrollTo(selMdl.getSelectedIndex());
+                        }
+                    });
+
+                    throw new IllegalStateException(msg + pojo.table());
+                }
+            }
+
+            /** {@inheritDoc} */
+            @Override protected Void call() throws Exception {
+                long started = System.currentTimeMillis();
+
+                if (!destFolder.exists() && !destFolder.mkdirs())
+                    throw new IOException("Failed to create output folder: " + destFolder);
+
+                Collection<PojoDescriptor> all = new ArrayList<>();
+
+                ConfirmCallable askOverwrite = new ConfirmCallable(owner, "File already exists: %s\nOverwrite?");
+
+                // Generate XML and POJO.
+                for (PojoDescriptor pojo : selPojos) {
+                    if (pojo.checked()) {
+                        checkEmpty(pojo, pojo.hasFields(), "No fields selected for type: ");
+                        checkEmpty(pojo, pojo.hasKeyFields(), "No key fields selected for type: ");
+                        checkEmpty(pojo, pojo.hasValueFields(includeKeys), "No value fields selected for type: ");
+
+                        all.add(pojo);
+                    }
+                }
+
+                for (PojoDescriptor pojo : all) {
+                    if (!singleXml)
+                        XmlGenerator.generate(pkg, pojo, includeKeys, new File(destFolder, pojo.table() + ".xml"),
+                            askOverwrite);
+
+                    PojoGenerator.generate(pojo, outFolder, pkg, constructor, includeKeys, askOverwrite);
+                }
+
+                if (singleXml)
+                    XmlGenerator.generate(pkg, all, includeKeys, new File(outFolder, "Ignite.xml"), askOverwrite);
+
+                SnippetGenerator.generate(all, pkg, includeKeys, new File(outFolder, "Ignite.snippet"), askOverwrite);
+
+                perceptualDelay(started);
+
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override protected void succeeded() {
+                super.succeeded();
+
+                unlockUI(genLayerPnl, genPnl, prevBtn, nextBtn);
+
+                if (MessageBox.confirmDialog(owner, "Generation complete!\n\n" +
+                    "Reveal output folder in system default file browser?"))
+                    try {
+                        java.awt.Desktop.getDesktop().open(destFolder);
+                    }
+                    catch (IOException e) {
+                        MessageBox.errorDialog(owner, "Failed to open folder with results.", e);
+                    }
+            }
+
+            /** {@inheritDoc} */
+            @Override protected void cancelled() {
+                super.cancelled();
+
+                unlockUI(genLayerPnl, genPnl, prevBtn, nextBtn);
+
+                MessageBox.warningDialog(owner, "Generation canceled.");
+            }
+
+            /** {@inheritDoc} */
+            @Override protected void failed() {
+                super.succeeded();
+
+                unlockUI(genLayerPnl, genPnl, prevBtn, nextBtn);
+
+                MessageBox.errorDialog(owner, "Generation failed.", getException());
+            }
+        };
+
+        exec.submit(task);
+    }
+
+    /**
+     * @return Header pane with title label.
+     */
+    private BorderPane createHeaderPane() {
+        dbIcon = hBox(0, true, imageView("data_connection", 48));
+        genIcon = hBox(0, true, imageView("text_tree", 48));
+
+        titleLb = label("");
+        titleLb.setId("banner");
+
+        subTitleLb = label("");
+
+        BorderPane bp = borderPane(null, vBox(5, titleLb, subTitleLb), null, dbIcon, hBox(0, true, imageView("ignite", 48)));
+        bp.setId("banner");
+
+        return bp;
+    }
+
+    /**
+     * @return Panel with control buttons.
+     */
+    private Pane createButtonsPane() {
+        prevBtn = button("Prev", "Go to \"Database connection\" page", new EventHandler<ActionEvent>() {
+            @Override public void handle(ActionEvent evt) {
+                prev();
+            }
+        });
+
+        nextBtn = button("Next", "Go to \"POJO and XML generation\" page", new EventHandler<ActionEvent>() {
+            @Override public void handle(ActionEvent evt) {
+                next();
+            }
+        });
+
+        return buttonsPane(Pos.BOTTOM_RIGHT, true, prevBtn, nextBtn);
+    }
+
+    /**
+     * @return {@code true} if some changes were made to fields metadata.
+     */
+    private boolean changed() {
+        for (PojoDescriptor pojo : pojos)
+            if (pojo.changed())
+                return true;
+
+        return false;
+    }
+
+    /**
+     * Go to &quot;Connect To Database&quot; panel.
+     */
+    private void prev() {
+        if (changed() && !MessageBox.confirmDialog(owner, "Are you sure you want to return to previous page?\n" +
+            "This will discard all your changes."))
+            return;
+
+        hdrPane.setLeft(dbIcon);
+
+        titleLb.setText("Connect To Database");
+        subTitleLb.setText("Specify database connection properties...");
+
+        rootPane.setCenter(connLayerPnl);
+
+        prevBtn.setDisable(true);
+        nextBtn.setText("Next");
+        tooltip(nextBtn, "Go to \"XML and POJO generation\" page");
+    }
+
+    /**
+     * Check that text field is non empty.
+     *
+     * @param tf Text field check.
+     * @param trim If {@code true} then
+     * @param msg Warning message.
+     * @return {@code true} If text field is empty.
+     */
+    private boolean checkInput(TextField tf, boolean trim, String msg) {
+        String s = tf.getText();
+
+        s = trim ? s.trim() : s;
+
+        if (s.isEmpty()) {
+            tf.requestFocus();
+
+            MessageBox.warningDialog(owner, msg);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Go to &quot;Generate XML And POJOs&quot; panel or generate XML and POJOs.
+     */
+    private void next() {
+        if (rootPane.getCenter() == connLayerPnl) {
+            if (checkInput(jdbcDrvJarTf, true, "Path to JDBC driver is not specified!") ||
+                checkInput(jdbcDrvClsTf, true, "JDBC driver class name is not specified!") ||
+                checkInput(jdbcUrlTf, true, "JDBC URL connection string is not specified!") ||
+                checkInput(userTf, true, "User name is not specified!"))
+                return;
+
+            fill();
+        }
+        else
+            generate();
+    }
+
+    /**
+     * Connect to database.
+     *
+     * @param jdbcDrvJarPath Path to JDBC driver.
+     * @param jdbcDrvCls JDBC class name.
+     * @param jdbcUrl JDBC connection URL.
+     * @param jdbcInfo Connection properties.
+     * @return Connection to database.
+     * @throws SQLException if connection failed.
+     */
+    private Connection connect(String jdbcDrvJarPath, String jdbcDrvCls, String jdbcUrl, Properties jdbcInfo)
+        throws SQLException {
+        Driver drv = drivers.get(jdbcDrvCls);
+
+        if (drv == null) {
+            if (jdbcDrvJarPath.isEmpty())
+                throw new IllegalStateException("Driver jar file name is not specified");
+
+            File drvJar = new File(jdbcDrvJarPath);
+
+            if (!drvJar.exists())
+                throw new IllegalStateException("Driver jar file is not found");
+
+            try {
+                URL u = new URL("jar:" + drvJar.toURI() + "!/");
+
+                URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {u});
+
+                drv = (Driver)Class.forName(jdbcDrvCls, true, ucl).newInstance();
+
+                drivers.put(jdbcDrvCls, drv);
+            }
+            catch (Throwable e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        Connection conn = drv.connect(jdbcUrl, jdbcInfo);
+
+        if (conn == null)
+            throw new IllegalStateException("Connection was not established (JDBC driver returned null value).");
+
+        return conn;
+    }
+
+    /**
+     * Create connection pane with controls.
+     */
+    private Pane createConnectionPane() {
+        connPnl = paneEx(10, 10, 0, 10);
+
+        connPnl.addColumn();
+        connPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        connPnl.addColumn(35, 35, 35, Priority.NEVER);
+
+        connPnl.add(text("This utility is designed to automatically generate configuration XML files and" +
+            " POJO classes from database schema information.", 550), 3);
+
+        connPnl.wrap();
+
+        GridPaneEx presetPnl = paneEx(0, 0, 0, 0);
+        presetPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        presetPnl.addColumn();
+
+        rdbmsCb = presetPnl.add(comboBox("Select database server to get predefined settings", presets));
+
+        presetPnl.add(button("Save preset", "Save current settings in preferences", new EventHandler<ActionEvent>() {
+            @Override public void handle(ActionEvent evt) {
+                Preset preset = rdbmsCb.getSelectionModel().getSelectedItem();
+
+                savePreset(preset);
+            }
+        }));
+
+        connPnl.add(label("DB Preset:"));
+        connPnl.add(presetPnl, 2);
+
+        jdbcDrvJarTf = connPnl.addLabeled("Driver JAR:", textField("Path to driver jar"));
+
+        connPnl.add(button("...", "Select JDBC driver jar or zip", new EventHandler<ActionEvent>() {
+            /** {@inheritDoc} */
+            @Override public void handle(ActionEvent evt) {
+                FileChooser fc = new FileChooser();
+
+                try {
+                    File jarFolder = new File(jdbcDrvJarTf.getText()).getParentFile();
+
+                    if (jarFolder.exists())
+                        fc.setInitialDirectory(jarFolder);
+                }
+                catch (Throwable ignored) {
+                    // No-op.
+                }
+
+                jdbcDrvJarTf.getText();
+
+                fc.getExtensionFilters().addAll(
+                    new FileChooser.ExtensionFilter("JDBC Drivers (*.jar)", "*.jar"),
+                    new FileChooser.ExtensionFilter("ZIP archives (*.zip)", "*.zip"));
+
+                File drvJar = fc.showOpenDialog(owner);
+
+                if (drvJar != null)
+                    jdbcDrvJarTf.setText(drvJar.getAbsolutePath());
+            }
+        }));
+
+        jdbcDrvClsTf = connPnl.addLabeled("JDBC Driver:", textField("Enter class name for JDBC driver"), 2);
+
+        jdbcUrlTf = connPnl.addLabeled("JDBC URL:", textField("JDBC URL of the database connection string"), 2);
+
+        rdbmsCb.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Preset>() {
+            @Override public void changed(ObservableValue<? extends Preset> val, Preset oldVal, Preset newVal) {
+                jdbcDrvJarTf.setText(newVal.jar);
+                jdbcDrvClsTf.setText(newVal.drv);
+                jdbcUrlTf.setText(newVal.url);
+                userTf.setText(newVal.user);
+            }
+        });
+
+        userTf = connPnl.addLabeled("User:", textField("User name"), 2);
+
+        pwdTf = connPnl.addLabeled("Password:", passwordField("User password"), 2);
+
+        parseCb = connPnl.addLabeled("Parse:", comboBox("Type of tables to parse", "Tables only", "Tables and Views"), 2);
+
+        connLayerPnl = stackPane(connPnl);
+
+        return connLayerPnl;
+    }
+
+    /**
+     * Check if new class name is unique.
+     *
+     * @param pojo Current edited POJO.
+     * @param newVal New value for class name.
+     * @param key {@code true} if key class name is checked.
+     * @return {@code true} if class name is valid.
+     */
+    private boolean checkClassNameUnique(PojoDescriptor pojo, String newVal, boolean key) {
+        for (PojoDescriptor otherPojo : pojos)
+            if (pojo != otherPojo) {
+                String otherKeyCls = otherPojo.keyClassName();
+                String otherValCls = otherPojo.valueClassName();
+
+                if (newVal.equals(otherKeyCls) || newVal.equals(otherValCls)) {
+                    MessageBox.warningDialog(owner, (key ? "Key" : "Value") + " class name must be unique!");
+
+                    return false;
+                }
+            }
+
+        return true;
+    }
+
+    /**
+     * Check if new class name is valid.
+     *
+     * @param pojo Current edited POJO.
+     * @param newVal New value for class name.
+     * @param key {@code true} if key class name is checked.
+     * @return {@code true} if class name is valid.
+     */
+    private boolean checkClassName(PojoDescriptor pojo, String newVal, boolean key) {
+        if (key) {
+            if (newVal.equals(pojo.valueClassName())) {
+                MessageBox.warningDialog(owner, "Key class name must be different from value class name!");
+
+                return false;
+            }
+        }
+        else if (newVal.equals(pojo.keyClassName())) {
+            MessageBox.warningDialog(owner, "Value class name must be different from key class name!");
+
+            return false;
+        }
+
+        return checkClassNameUnique(pojo, newVal, key);
+    }
+
+    /**
+     * Create generate pane with controls.
+     */
+    private void createGeneratePane() {
+        genPnl = paneEx(10, 10, 0, 10);
+
+        genPnl.addColumn();
+        genPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        genPnl.addColumn(35, 35, 35, Priority.NEVER);
+
+        genPnl.addRow(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        genPnl.addRows(7);
+
+        TableColumn<PojoDescriptor, Boolean> useCol = customColumn("Schema / Table", "use",
+            "If checked then this table will be used for XML and POJOs generation", PojoDescriptorCell.cellFactory());
+
+        TableColumn<PojoDescriptor, String> keyClsCol = textColumn("Key Class Name", "keyClassName", "Key class name",
+            new TextColumnValidator<PojoDescriptor>() {
+                @Override public boolean valid(PojoDescriptor rowVal, String newVal) {
+                    boolean valid = checkClassName(rowVal, newVal, true);
+
+                    if (valid)
+                        rowVal.keyClassName(newVal);
+
+                    return valid;
+                }
+            });
+
+        TableColumn<PojoDescriptor, String> valClsCol = textColumn("Value Class Name", "valueClassName", "Value class name",
+            new TextColumnValidator<PojoDescriptor>() {
+                @Override public boolean valid(PojoDescriptor rowVal, String newVal) {
+                    boolean valid = checkClassName(rowVal, newVal, true);
+
+                    if (valid)
+                        rowVal.valueClassName(newVal);
+
+                    return valid;
+                }
+            });
+
+        pojosTbl = tableView("Tables not found in database", useCol, keyClsCol, valClsCol);
+
+        TableColumn<PojoField, Boolean> useFldCol = customColumn("Use", "use",
+            "Check to use this field for XML and POJO generation\n" +
+            "Note that NOT NULL columns cannot be unchecked", PojoFieldUseCell.cellFactory());
+        useFldCol.setMinWidth(50);
+        useFldCol.setMaxWidth(50);
+
+        TableColumn<PojoField, Boolean> keyCol = booleanColumn("Key", "key",
+            "Check to include this field into key object");
+
+        TableColumn<PojoField, Boolean> akCol = booleanColumn("AK", "affinityKey",
+            "Check to annotate key filed with @CacheAffinityKeyMapped annotation in generated POJO class\n" +
+            "Note that a class can have only ONE key field annotated with @CacheAffinityKeyMapped annotation");
+
+        TableColumn<PojoField, String> dbNameCol = tableColumn("DB Name", "dbName", "Field name in database");
+
+        TableColumn<PojoField, String> dbTypeNameCol = tableColumn("DB Type", "dbTypeName", "Field type in database");
+
+        TableColumn<PojoField, String> javaNameCol = textColumn("Java Name", "javaName", "Field name in POJO class",
+            new TextColumnValidator<PojoField>() {
+                @Override public boolean valid(PojoField rowVal, String newVal) {
+                    for (PojoField field : curPojo.fields())
+                        if (rowVal != field && newVal.equals(field.javaName())) {
+                            MessageBox.warningDialog(owner, "Java name must be unique!");
+
+                            return false;
+                        }
+
+                    rowVal.javaName(newVal);
+
+                    return true;
+                }
+            });
+
+        TableColumn<PojoField, String> javaTypeNameCol = customColumn("Java Type", "javaTypeName",
+            "Field java type in POJO class", JavaTypeCell.cellFactory());
+
+        fieldsTbl = tableView("Select table to see table columns",
+            useFldCol, keyCol, akCol, dbNameCol, dbTypeNameCol, javaNameCol, javaTypeNameCol);
+
+        genPnl.add(splitPane(pojosTbl, fieldsTbl, 0.6), 3);
+
+        final GridPaneEx keyValPnl = paneEx(0, 0, 0, 0);
+        keyValPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        keyValPnl.addColumn();
+        keyValPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        keyValPnl.addColumn();
+
+        pkgTf = genPnl.addLabeled("Package:", textField("Package that will be used for POJOs generation"), 2);
+
+        outFolderTf = genPnl.addLabeled("Output Folder:", textField("Output folder for XML and POJOs files"));
+
+        genPnl.add(button("...", "Select output folder", new EventHandler<ActionEvent>() {
+            @Override public void handle(ActionEvent evt) {
+                DirectoryChooser dc = new DirectoryChooser();
+
+                try {
+                    File outFolder = new File(outFolderTf.getText());
+
+                    if (outFolder.exists())
+                        dc.setInitialDirectory(outFolder);
+                }
+                catch (Throwable ignored) {
+                    // No-op.
+                }
+
+                File folder = dc.showDialog(owner);
+
+                if (folder != null)
+                    outFolderTf.setText(folder.getAbsolutePath());
+            }
+        }));
+
+        pojoIncludeKeysCh = genPnl.add(checkBox("Include key fields into value POJOs",
+            "If selected then include key fields into value object", true), 3);
+
+        pojoConstructorCh = genPnl.add(checkBox("Generate constructors for POJOs",
+            "If selected then generate empty and full constructors for POJOs", false), 3);
+
+        xmlSingleFileCh = genPnl.add(checkBox("Write all configurations to a single XML file",
+            "If selected then all configurations will be saved into the file 'Ignite.xml'", true), 3);
+
+        GridPaneEx regexPnl = paneEx(5, 5, 5, 5);
+        regexPnl.addColumn();
+        regexPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        regexPnl.addColumn();
+        regexPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+
+        regexTf = regexPnl.addLabeled("  Regexp:", textField("Regular expression. For example: (\\w+)"));
+
+        replaceTf = regexPnl.addLabeled("  Replace with:", textField("Replace text. For example: $1_SomeText"));
+
+        final ComboBox<String> replaceCb = regexPnl.addLabeled("  Replace:", comboBox("Replacement target",
+            "Key class names", "Value class names", "Java names"));
+
+        regexPnl.add(buttonsPane(Pos.CENTER_LEFT, false,
+            button("Rename Selected", "Replaces each substring of this string that matches the given regular expression" +
+                    " with the given replacement.",
+                new EventHandler<ActionEvent>() {
+                    @Override public void handle(ActionEvent evt) {
+                        if (checkInput(regexTf, false, "Regular expression should not be empty!"))
+                            return;
+
+                        String sel = replaceCb.getSelectionModel().getSelectedItem();
+
+                        boolean isFields = "Java names".equals(sel) && curTbl == fieldsTbl;
+
+                        String src = isFields ? "fields" : "tables";
+
+                        String target = "\"" + sel + "\"";
+
+                        Collection<PojoDescriptor> selPojos = pojosTbl.getSelectionModel().getSelectedItems();
+
+                        Collection<PojoField> selFields = fieldsTbl.getSelectionModel().getSelectedItems();
+
+                        boolean isEmpty = isFields ? selFields.isEmpty() : selPojos.isEmpty();
+
+                        if (isEmpty) {
+                            MessageBox.warningDialog(owner, "Please select " + src + " to rename " + target + "!");
+
+                            return;
+                        }
+
+                        if (!MessageBox.confirmDialog(owner, "Are you sure you want to rename " + target +
+                            " for all selected " + src + "?"))
+                            return;
+
+                        String regex = regexTf.getText();
+
+                        String replace = replaceTf.getText();
+
+                        try {
+                            switch (replaceCb.getSelectionModel().getSelectedIndex()) {
+                                case 0:
+                                    renameKeyClassNames(selPojos, regex, replace);
+                                    break;
+
+                                case 1:
+                                    renameValueClassNames(selPojos, regex, replace);
+                                    break;
+
+                                default:
+                                    if (isFields)
+                                        renameFieldsJavaNames(selFields, regex, replace);
+                                    else
+                                        renamePojosJavaNames(selPojos, regex, replace);
+                            }
+                        }
+                        catch (Exception e) {
+                            MessageBox.errorDialog(owner, "Failed to rename " + target + "!", e);
+                        }
+                    }
+                }),
+            button("Reset Selected", "Revert changes for selected items to initial auto-generated values", new EventHandler<ActionEvent>() {
+                @Override public void handle(ActionEvent evt) {
+                    String sel = replaceCb.getSelectionModel().getSelectedItem();
+
+                    boolean isFields = "Java names".equals(sel) && curTbl == fieldsTbl;
+
+                    String src = isFields ? "fields" : "tables";
+
+                    String target = "\"" + sel + "\"";
+
+                    Collection<PojoDescriptor> selPojos = pojosTbl.getSelectionModel().getSelectedItems();
+
+                    Collection<PojoField> selFields = fieldsTbl.getSelectionModel().getSelectedItems();
+
+                    boolean isEmpty = isFields ? selFields.isEmpty() : selPojos.isEmpty();
+
+                    if (isEmpty) {
+                        MessageBox.warningDialog(owner, "Please select " + src + "to revert " + target + "!");
+
+                        return;
+                    }
+
+                    if (!MessageBox.confirmDialog(owner,
+                        "Are you sure you want to revert " + target + " for all selected " + src + "?"))
+                        return;
+
+                    switch (replaceCb.getSelectionModel().getSelectedIndex()) {
+                        case 0:
+                            revertKeyClassNames(selPojos);
+                            break;
+
+                        case 1:
+                            revertValueClassNames(selPojos);
+                            break;
+
+                        default:
+                            if (isFields)
+                                revertFieldsJavaNames(selFields);
+                            else
+                                revertPojosJavaNames(selPojos);
+                    }
+                }
+            })
+        ), 2).setPadding(new Insets(0, 0, 0, 10));
+
+        pojosTbl.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<PojoDescriptor>() {
+            @Override public void changed(ObservableValue<? extends PojoDescriptor> val,
+                PojoDescriptor oldVal, PojoDescriptor newItem) {
+                if (newItem != null && newItem.parent() != null) {
+                    curPojo = newItem;
+
+                    fieldsTbl.setItems(curPojo.fields());
+                    fieldsTbl.getSelectionModel().clearSelection();
+
+                    keyValPnl.setDisable(false);
+                }
+                else {
+                    curPojo = null;
+                    fieldsTbl.setItems(NO_FIELDS);
+
+                    keyValPnl.setDisable(true);
+                }
+            }
+        });
+
+        pojosTbl.focusedProperty().addListener(new ChangeListener<Boolean>() {
+            @Override public void changed(ObservableValue<? extends Boolean> val, Boolean oldVal, Boolean newVal) {
+                if (newVal)
+                    curTbl = pojosTbl;
+            }
+        });
+
+        fieldsTbl.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
+            @Override public void changed(ObservableValue<? extends Number> val, Number oldVal, Number newVal) {
+                if (curPojo != null) {
+                    TableView.TableViewSelectionModel<PojoDescriptor> selMdl = pojosTbl.getSelectionModel();
+
+                    List<Integer> idxs = new ArrayList<>(selMdl.getSelectedIndices());
+
+                    if (idxs.size() > 1) {
+                        for (Integer idx : idxs) {
+                            if (pojos.get(idx) != curPojo)
+                                selMdl.clearSelection(idx);
+                        }
+                    }
+                }
+            }
+        });
+
+        fieldsTbl.focusedProperty().addListener(new ChangeListener<Boolean>() {
+            @Override public void changed(ObservableValue<? extends Boolean> val, Boolean oldVal, Boolean newVal) {
+                if (newVal)
+                    curTbl = fieldsTbl;
+            }
+        });
+
+        genPnl.add(titledPane("Rename \"Key class name\", \"Value class name\" or  \"Java name\" for selected tables",
+            regexPnl), 3);
+
+        genLayerPnl = stackPane(genPnl);
+    }
+
+    /**
+     * Rename key class name for selected POJOs.
+     *
+     * @param selPojos Selected POJOs to rename.
+     * @param regex Regex to search.
+     * @param replace Text for replacement.
+     */
+    private void renameKeyClassNames(Collection<PojoDescriptor> selPojos, String regex, String replace) {
+        for (PojoDescriptor pojo : selPojos)
+            pojo.keyClassName(pojo.keyClassName().replaceAll(regex, replace));
+    }
+
+    /**
+     * Rename value class name for selected POJOs.
+     *
+     * @param selPojos Selected POJOs to rename.
+     * @param regex Regex to search.
+     * @param replace Text for replacement.
+     */
+    private void renameValueClassNames(Collection<PojoDescriptor> selPojos, String regex, String replace) {
+        for (PojoDescriptor pojo : selPojos)
+            pojo.valueClassName(pojo.valueClassName().replaceAll(regex, replace));
+    }
+
+    /**
+     * Rename fields java name for selected POJOs.
+     *
+     * @param selPojos Selected POJOs to rename.
+     * @param regex Regex to search.
+     * @param replace Text for replacement.
+     */
+    private void renamePojosJavaNames(Collection<PojoDescriptor> selPojos, String regex, String replace) {
+        for (PojoDescriptor pojo : selPojos)
+            for (PojoField field : pojo.fields())
+                field.javaName(field.javaName().replaceAll(regex, replace));
+    }
+
+    /**
+     * Rename fields java name for current POJO.
+     *
+     * @param selFields Selected fields for current POJO to rename.
+     * @param regex Regex to search.
+     * @param replace Text for replacement.
+     */
+    private void renameFieldsJavaNames(Collection<PojoField> selFields, String regex, String replace) {
+        for (PojoField field : selFields)
+            field.javaName(field.javaName().replaceAll(regex, replace));
+    }
+
+    /**
+     * Revert key class name for selected POJOs to initial value.
+     *
+     * @param selPojos Selected POJOs to revert.
+     */
+    private void revertKeyClassNames(Collection<PojoDescriptor> selPojos) {
+        for (PojoDescriptor pojo : selPojos)
+            pojo.revertKeyClassName();
+    }
+
+    /**
+     * Revert value class name for selected POJOs to initial value.
+     *
+     * @param selPojos Selected POJOs to revert.
+     */
+    private void revertValueClassNames(Collection<PojoDescriptor> selPojos) {
+        for (PojoDescriptor pojo : selPojos)
+            pojo.revertValueClassName();
+    }
+
+    /**
+     * Revert fields java name for selected POJOs to initial value.
+     *
+     * @param selPojos Selected POJOs to revert.
+     */
+    private void revertPojosJavaNames(Collection<PojoDescriptor> selPojos) {
+        for (PojoDescriptor pojo : selPojos)
+            pojo.revertJavaNames();
+    }
+
+    /**
+     * Revert fields java name for current POJO to initial value.
+     *
+     * @param selFields Selected POJO fields to revert.
+     */
+    private void revertFieldsJavaNames(Collection<PojoField> selFields) {
+        for (PojoField field : selFields)
+            field.resetJavaName();
+    }
+
+    /**
+     * @return POJOs checked in table-tree-view.
+     */
+    private Collection<PojoDescriptor> checkedPojos() {
+        Collection<PojoDescriptor> res = new ArrayList<>();
+
+        for (PojoDescriptor pojo : pojos)
+            if (pojo.checked())
+                res.add(pojo);
+
+        return res;
+    }
+
+    /**
+     * Gets string property.
+     *
+     * @param key Property key.
+     * @param dflt Default value.
+     */
+    private String getStringProp(String key, String dflt) {
+        String val = prefs.getProperty(key);
+
+        if (val != null)
+            return val;
+
+        return dflt;
+    }
+
+    /**
+     * Sets string property.
+     *
+     * @param key Property key.
+     * @param val Value to set.
+     */
+    private void setStringProp(String key, String val) {
+        prefs.put(key, val);
+    }
+
+    /**
+     * Gets int property.
+     *
+     * @param key Property key.
+     * @param dflt Default value.
+     */
+    private int getIntProp(String key, int dflt) {
+        String val = prefs.getProperty(key);
+
+        if (val != null)
+            try {
+                return Integer.parseInt(val);
+            }
+            catch (NumberFormatException ignored) {
+                return dflt;
+            }
+
+        return dflt;
+    }
+
+    /**
+     * Sets int property.
+     *
+     * @param key Property key.
+     * @param val Value to set.
+     */
+    private void setIntProp(String key, int val) {
+        prefs.put(key, String.valueOf(val));
+    }
+
+    /**
+     * Gets boolean property.
+     *
+     * @param key Property key.
+     * @param dflt Default value.
+     */
+    private boolean getBoolProp(String key, boolean dflt) {
+        String val = prefs.getProperty(key);
+
+        if (val != null)
+            return Boolean.parseBoolean(val);
+
+        return dflt;
+    }
+
+    /**
+     * Sets boolean property.
+     *
+     * @param key Property key.
+     * @param val Value to set.
+     */
+    private void setBoolProp(String key, boolean val) {
+        prefs.put(key, String.valueOf(val));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void start(Stage primaryStage) {
+        owner = primaryStage;
+
+        if (prefsFile.exists())
+            try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(prefsFile))) {
+                prefs.load(in);
+            }
+            catch (IOException ignore) {
+                // No-op.
+            }
+
+        // Restore presets.
+        for (Preset preset : presets) {
+            String key = "presets." + preset.pref + ".";
+
+            preset.jar = getStringProp(key + "jar", preset.jar);
+            preset.drv = getStringProp(key + "drv", preset.drv);
+            preset.url = getStringProp(key + "url", preset.url);
+            preset.user = getStringProp(key + "user", preset.user);
+        }
+
+        primaryStage.setTitle("Apache Ignite Auto Schema Load Utility");
+
+        primaryStage.getIcons().addAll(
+            image("ignite", 16),
+            image("ignite", 24),
+            image("ignite", 32),
+            image("ignite", 48),
+            image("ignite", 64),
+            image("ignite", 128));
+
+        pi = progressIndicator(50);
+
+        createGeneratePane();
+
+        hdrPane = createHeaderPane();
+        rootPane = borderPane(hdrPane, createConnectionPane(), createButtonsPane(), null, null);
+
+        primaryStage.setScene(scene(rootPane));
+
+        primaryStage.setWidth(650);
+        primaryStage.setMinWidth(650);
+
+        primaryStage.setHeight(650);
+        primaryStage.setMinHeight(650);
+
+        prev();
+
+        // Restore window pos and size.
+        if (prefs.getProperty("window.x") != null) {
+            int x = getIntProp("window.x", 100);
+            int y = getIntProp("window.y", 100);
+            int w = getIntProp("window.width", 650);
+            int h = getIntProp("window.height", 650);
+
+            // Ensure that window fit any available screen.
+            if (!Screen.getScreensForRectangle(x, y, w, h).isEmpty()) {
+                if (x > 0)
+                    primaryStage.setX(x);
+
+                if (y > 0)
+                    primaryStage.setY(y);
+
+                primaryStage.setWidth(w);
+                primaryStage.setHeight(h);
+            }
+        }
+        else
+            primaryStage.centerOnScreen();
+
+        String userHome = System.getProperty("user.home").replace('\\', '/');
+
+        // Restore connection pane settings.
+        rdbmsCb.getSelectionModel().select(getIntProp("jdbc.db.preset", 0));
+        jdbcDrvJarTf.setText(getStringProp("jdbc.driver.jar", "h2.jar"));
+        jdbcDrvClsTf.setText(getStringProp("jdbc.driver.class", "org.h2.Driver"));
+        jdbcUrlTf.setText(getStringProp("jdbc.url", "jdbc:h2:" + userHome + "/ignite-schema-load/db"));
+        userTf.setText(getStringProp("jdbc.user", "sa"));
+
+        // Restore generation pane settings.
+        outFolderTf.setText(getStringProp("out.folder", userHome + "/ignite-schema-load/out"));
+
+        pkgTf.setText(getStringProp("pojo.package", "org.apache.ignite"));
+        pojoIncludeKeysCh.setSelected(getBoolProp("pojo.include", true));
+        pojoConstructorCh.setSelected(getBoolProp("pojo.constructor", false));
+
+        xmlSingleFileCh.setSelected(getBoolProp("xml.single", true));
+
+        regexTf.setText(getStringProp("naming.pattern", "(\\w+)"));
+        replaceTf.setText(getStringProp("naming.replace", "$1_SomeText"));
+
+        primaryStage.show();
+    }
+
+    /**
+     * Save preset.
+     *
+     * @param preset Preset to save.
+     */
+    private void savePreset(Preset preset) {
+        String key = "presets." + preset.pref + ".";
+
+        preset.jar = jdbcDrvJarTf.getText();
+        setStringProp(key + "jar", preset.jar);
+
+        preset.drv = jdbcDrvClsTf.getText();
+        setStringProp(key + "drv", preset.drv);
+
+        preset.url = jdbcUrlTf.getText();
+        setStringProp(key + "url", preset.url);
+
+        preset.user = userTf.getText();
+        setStringProp(key + "user", preset.user);
+
+        savePreferences();
+    }
+
+    /**
+     * Save user preferences.
+     */
+    private void savePreferences() {
+        try (FileOutputStream out = new FileOutputStream(prefsFile)) {
+            prefs.store(out, "Apache Ignite Schema Load Utility");
+        }
+        catch (IOException e) {
+            MessageBox.errorDialog(owner, "Failed to save preferences!", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() throws Exception {
+        // Save window pos and size.
+        setIntProp("window.x", (int)owner.getX());
+        setIntProp("window.y", (int)owner.getY());
+        setIntProp("window.width", (int)owner.getWidth());
+        setIntProp("window.height", (int)owner.getHeight());
+
+        // Save connection pane settings.
+        setIntProp("jdbc.db.preset", rdbmsCb.getSelectionModel().getSelectedIndex());
+        setStringProp("jdbc.driver.jar", jdbcDrvJarTf.getText());
+        setStringProp("jdbc.driver.class", jdbcDrvClsTf.getText());
+        setStringProp("jdbc.url", jdbcUrlTf.getText());
+        setStringProp("jdbc.user", userTf.getText());
+
+        // Save generation pane settings.
+        setStringProp("out.folder", outFolderTf.getText());
+
+        setStringProp("pojo.package", pkgTf.getText());
+        setBoolProp("pojo.include", pojoIncludeKeysCh.isSelected());
+        setBoolProp("pojo.constructor", pojoConstructorCh.isSelected());
+
+        setBoolProp("xml.single", xmlSingleFileCh.isSelected());
+
+        setStringProp("naming.pattern", regexTf.getText());
+        setStringProp("naming.replace", replaceTf.getText());
+
+        savePreferences();
+    }
+
+    /**
+     * Schema load utility launcher.
+     *
+     * @param args Command line arguments passed to the application.
+     */
+    public static void main(String[] args) {
+        // Workaround for JavaFX ugly text AA.
+        System.setProperty("prism.lcdtext", "false");
+        System.setProperty("prism.text", "t2k");
+
+        // Workaround for AWT + JavaFX: we should initialize AWT before JavaFX.
+        java.awt.Toolkit.getDefaultToolkit();
+
+        // Workaround for JavaFX + Mac OS dock icon.
+        if (System.getProperty("os.name").toLowerCase().contains("mac os")) {
+            System.setProperty("javafx.macosx.embedded", "true");
+
+            try {
+                Class<?> appCls = Class.forName("com.apple.eawt.Application");
+
+                Object osxApp = appCls.getDeclaredMethod("getApplication").invoke(null);
+
+                appCls.getDeclaredMethod("setDockIconImage", java.awt.Image.class)
+                    .invoke(osxApp, fromFXImage(image("ignite", 128), null));
+            }
+            catch (Throwable ignore) {
+                // No-op.
+            }
+        }
+
+        launch(args);
+    }
+
+    /**
+     * Special table cell to select possible java type conversions.
+     */
+    private static class JavaTypeCell extends TableCell<PojoField, String> {
+        /** Combo box. */
+        private final ComboBox<String> comboBox;
+
+        /** Creates a ComboBox cell factory for use in TableColumn controls. */
+        public static Callback<TableColumn<PojoField, String>, TableCell<PojoField, String>> cellFactory() {
+            return new Callback<TableColumn<PojoField, String>, TableCell<PojoField, String>>() {
+                @Override public TableCell<PojoField, String> call(TableColumn<PojoField, String> col) {
+                    return new JavaTypeCell();
+                }
+            };
+        }
+
+        /**
+         * Default constructor.
+         */
+        private JavaTypeCell() {
+            comboBox = new ComboBox<>(FXCollections.<String>emptyObservableList());
+
+            comboBox.valueProperty().addListener(new ChangeListener<String>() {
+                @Override public void changed(ObservableValue<? extends String> val, String oldVal, String newVal) {
+                    if (isEditing())
+                        commitEdit(newVal);
+                }
+            });
+
+            getStyleClass().add("combo-box-table-cell");
+        }
+
+        /** {@inheritDoc} */
+        @Override public void startEdit() {
+            if (comboBox.getItems().size() > 1) {
+                comboBox.getSelectionModel().select(getItem());
+
+                super.startEdit();
+
+                setText(null);
+                setGraphic(comboBox);
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void cancelEdit() {
+            super.cancelEdit();
+
+            setText(getItem());
+
+            setGraphic(null);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void updateItem(String item, boolean empty) {
+            super.updateItem(item, empty);
+
+            setGraphic(null);
+
+            if (!empty) {
+                setText(item);
+
+                TableRow row = getTableRow();
+
+                if (row != null) {
+                    PojoField pojo = (PojoField)row.getItem();
+
+                    if (pojo != null) {
+                        comboBox.setItems(pojo.conversions());
+
+                        comboBox.getSelectionModel().select(pojo.javaTypeName());
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Special table cell to select schema or table.
+     */
+    private static class PojoDescriptorCell extends TableCell<PojoDescriptor, Boolean> {
+        /** Creates a ComboBox cell factory for use in TableColumn controls. */
+        public static Callback<TableColumn<PojoDescriptor, Boolean>, TableCell<PojoDescriptor, Boolean>> cellFactory() {
+            return new Callback<TableColumn<PojoDescriptor, Boolean>, TableCell<PojoDescriptor, Boolean>>() {
+                @Override public TableCell<PojoDescriptor, Boolean> call(TableColumn<PojoDescriptor, Boolean> col) {
+                    return new PojoDescriptorCell();
+                }
+            };
+        }
+
+        /** Previous POJO bound to cell. */
+        private PojoDescriptor prevPojo;
+
+        /** {@inheritDoc} */
+        @Override public void updateItem(Boolean item, boolean empty) {
+            super.updateItem(item, empty);
+
+            if (!empty) {
+                TableRow row = getTableRow();
+
+                if (row != null) {
+                    final PojoDescriptor pojo = (PojoDescriptor)row.getItem();
+
+                    if (pojo != prevPojo) {
+                        prevPojo = pojo;
+
+                        boolean isTbl = pojo.parent() != null;
+
+                        CheckBox ch = new CheckBox();
+
+                        ch.setAllowIndeterminate(false);
+
+                        ch.indeterminateProperty().bindBidirectional(pojo.indeterminate());
+
+                        ch.selectedProperty().bindBidirectional(pojo.useProperty());
+
+                        Label lb = new Label(isTbl ? pojo.table() : pojo.schema());
+
+                        Pane pnl = new HBox(5);
+                        pnl.setPadding(new Insets(0, 0, 0, isTbl ? 25 : 5));
+                        pnl.getChildren().addAll(ch, lb);
+
+                        setGraphic(pnl);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Special table cell to select &quot;used&quot; fields for code generation.
+     */
+    private static class PojoFieldUseCell extends TableCell<PojoField, Boolean> {
+        /** Creates a ComboBox cell factory for use in TableColumn controls. */
+        public static Callback<TableColumn<PojoField, Boolean>, TableCell<PojoField, Boolean>> cellFactory() {
+            return new Callback<TableColumn<PojoField, Boolean>, TableCell<PojoField, Boolean>>() {
+                @Override public TableCell<PojoField, Boolean> call(TableColumn<PojoField, Boolean> col) {
+                    return new PojoFieldUseCell();
+                }
+            };
+        }
+
+        /** Previous POJO field bound to cell. */
+        private PojoField prevField;
+
+        /** {@inheritDoc} */
+        @Override public void updateItem(Boolean item, boolean empty) {
+            super.updateItem(item, empty);
+
+            if (!empty) {
+                TableRow row = getTableRow();
+
+                if (row != null) {
+                    final PojoField field = (PojoField)row.getItem();
+
+                    if (field != prevField) {
+                        prevField = field;
+
+                        setAlignment(Pos.CENTER);
+
+                        CheckBox ch = new CheckBox();
+
+                        ch.setDisable(!field.nullable());
+
+                        ch.selectedProperty().bindBidirectional(field.useProperty());
+
+                        setGraphic(ch);
+                    }
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9cf45b43/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/TextColumnValidator.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/TextColumnValidator.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/TextColumnValidator.java
new file mode 100644
index 0000000..d92ae08
--- /dev/null
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/TextColumnValidator.java
@@ -0,0 +1,32 @@
+/*
+ * 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 org.apache.ignite.schema.ui;
+
+/**
+ * Validator for editable table view text column.
+ */
+public interface TextColumnValidator<T> {
+    /**
+     * Validate new value of text.
+     *
+     * @param rowVal Row value.
+     * @param newVal New value of text.
+     * @return {@code true} if text is valid.
+     */
+    public boolean valid(T rowVal, String newVal);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9cf45b43/modules/schema-import/src/test/java/org/apache/ignite/schema/load/AbstractSchemaLoaderTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/load/AbstractSchemaLoaderTest.java b/modules/schema-import/src/test/java/org/apache/ignite/schema/load/AbstractSchemaLoaderTest.java
new file mode 100644
index 0000000..f8a3719
--- /dev/null
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/load/AbstractSchemaLoaderTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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 org.apache.ignite.schema.load;
+
+import junit.framework.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.schema.model.PojoDescriptor;
+import org.apache.ignite.schema.parser.DatabaseMetadataParser;
+import org.apache.ignite.schema.ui.*;
+
+import java.io.*;
+import java.sql.*;
+import java.util.List;
+
+import static org.apache.ignite.schema.ui.MessageBox.Result.*;
+
+/**
+ * Base functional for ignite-schema-loader tests.
+ */
+public abstract class AbstractSchemaLoaderTest extends TestCase {
+    /** DB connection URL. */
+    private static final String CONN_URL = "jdbc:h2:mem:autoCacheStore;DB_CLOSE_DELAY=-1";
+
+    /** Path to temp folder where generated POJOs will be saved. */
+    protected static final String OUT_DIR_PATH = System.getProperty("java.io.tmpdir") + "/ignite-schema-loader/out";
+
+    /** Auto confirmation of file conflicts. */
+    protected ConfirmCallable askOverwrite = new ConfirmCallable(null, "") {
+        @Override public MessageBox.Result confirm(String msg) {
+            return YES_TO_ALL;
+        }
+    };
+
+    /** List of generated for test database POJO objects. */
+    protected List<PojoDescriptor> pojos;
+
+    /** {@inheritDoc} */
+    @Override public void setUp() throws Exception {
+        Class.forName("org.h2.Driver");
+
+        Connection conn = DriverManager.getConnection(CONN_URL, "sa", "");
+
+        Statement stmt = conn.createStatement();
+
+        stmt.executeUpdate("CREATE TABLE IF NOT EXISTS PRIMITIVES (pk INTEGER PRIMARY KEY, " +
+            " boolCol BOOLEAN NOT NULL," +
+            " byteCol TINYINT NOT NULL," +
+            " shortCol SMALLINT NOT NULL," +
+            " intCol INTEGER NOT NULL, " +
+            " longCol BIGINT NOT NULL," +
+            " floatCol REAL NOT NULL," +
+            " doubleCol DOUBLE NOT NULL," +
+            " doubleCol2 DOUBLE NOT NULL, " +
+            " bigDecimalCol DECIMAL(10, 0)," +
+            " strCol VARCHAR(10)," +
+            " dateCol DATE," +
+            " timeCol TIME," +
+            " tsCol TIMESTAMP, " +
+            " arrCol BINARY(10))");
+
+        stmt.executeUpdate("CREATE TABLE IF NOT EXISTS OBJECTS (pk INTEGER PRIMARY KEY, " +
+            " boolCol BOOLEAN," +
+            " byteCol TINYINT," +
+            " shortCol SMALLINT," +
+            " intCol INTEGER," +
+            " longCol BIGINT," +
+            " floatCol REAL," +
+            " doubleCol DOUBLE," +
+            " doubleCol2 DOUBLE," +
+            " bigDecimalCol DECIMAL(10, 0)," +
+            " strCol VARCHAR(10), " +
+            " dateCol DATE," +
+            " timeCol TIME," +
+            " tsCol TIMESTAMP," +
+            " arrCol BINARY(10))");
+
+        conn.commit();
+
+        U.closeQuiet(stmt);
+
+        pojos = DatabaseMetadataParser.parse(conn, false);
+
+        U.closeQuiet(conn);
+    }
+
+    /**
+     * Compare files by lines.
+     *
+     * @param exp Stream to read of expected file from test resources.
+     * @param generated Generated file instance.
+     * @param excludePtrn Marker string to exclude lines from comparing.
+     * @return true if generated file correspond to expected.
+     */
+    protected boolean compareFilesInt(InputStream exp, File generated, String excludePtrn) {
+        try (BufferedReader baseReader = new BufferedReader(new InputStreamReader(exp))) {
+            try (BufferedReader generatedReader = new BufferedReader(new FileReader(generated))) {
+                String baseLine;
+
+                while ((baseLine = baseReader.readLine()) != null) {
+                    String generatedLine = generatedReader.readLine();
+
+                    if (!baseLine.equals(generatedLine) && !baseLine.contains(excludePtrn)
+                            && !generatedLine.contains(excludePtrn)) {
+                        System.out.println("Expected: " + baseLine);
+                        System.out.println("Generated: " + generatedLine);
+
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9cf45b43/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/PojoGeneratorTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/PojoGeneratorTest.java b/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/PojoGeneratorTest.java
new file mode 100644
index 0000000..3162290
--- /dev/null
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/PojoGeneratorTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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 org.apache.ignite.schema.load.generator;
+
+import org.apache.ignite.schema.generator.PojoGenerator;
+import org.apache.ignite.schema.load.AbstractSchemaLoaderTest;
+import org.apache.ignite.schema.model.PojoDescriptor;
+
+import java.io.File;
+
+/**
+ * Tests for POJO generator.
+ */
+public class PojoGeneratorTest extends AbstractSchemaLoaderTest {
+    /** Marker string to skip date generation while comparing.*/
+    private static final String GEN_PTRN = "Code generated by Apache Ignite Schema Load utility";
+
+    /**
+     * Test that POJOs generated correctly.
+     */
+    public void testPojoGeneration() throws Exception {
+        String pkg = "org.apache.ignite.schema.load.model";
+        String intPath = "org/apache/ignite/schema/load/model";
+
+        Boolean containsSchema = false;
+
+        for (PojoDescriptor pojo : pojos) {
+            if (pojo.valueClassName().isEmpty())
+                containsSchema = true;
+            else {
+                PojoGenerator.generate(pojo, OUT_DIR_PATH, pkg, true, true, askOverwrite);
+
+                assertTrue("Generated key class POJO content is differ from expected for type " + pojo.keyClassName(),
+                        compareFiles(pojo.keyClassName(), intPath, GEN_PTRN));
+
+                assertTrue("Generated value class POJO content is differ from expected for type " + pojo.valueClassName(),
+                        compareFiles(pojo.valueClassName(), intPath, GEN_PTRN));
+            }
+        }
+
+        assertTrue("Generated POJOs does not contains schema.", containsSchema);
+    }
+
+    /**
+     * @param typeName Type name.
+     * @param intPath Internal path.
+     * @return {@code true} if generated POJO as expected.
+     */
+    private boolean compareFiles(String typeName, String intPath, String excludePtrn) {
+        String relPath = intPath + "/" + typeName;
+
+        return compareFilesInt(getClass().getResourceAsStream("/" + relPath + ".txt"),
+                new File(OUT_DIR_PATH + "/" + relPath + ".java"), excludePtrn);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9cf45b43/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/XmlGeneratorTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/XmlGeneratorTest.java b/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/XmlGeneratorTest.java
new file mode 100644
index 0000000..027f64f
--- /dev/null
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/load/generator/XmlGeneratorTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.apache.ignite.schema.load.generator;
+
+import org.apache.ignite.schema.generator.*;
+import org.apache.ignite.schema.load.*;
+import org.apache.ignite.schema.model.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Tests for XML generator.
+ */
+public class XmlGeneratorTest extends AbstractSchemaLoaderTest {
+    /**
+     * Test that XML generated correctly.
+     */
+    public void testXmlGeneration() throws Exception {
+        Collection<PojoDescriptor> all = new ArrayList<>();
+
+        for (PojoDescriptor pojo : pojos)
+            if (pojo.parent() != null)
+                all.add(pojo);
+
+        String fileName = "Ignite.xml";
+
+        XmlGenerator.generate("org.apache.ignite.schema.load.model", all, true, new File(OUT_DIR_PATH, fileName),
+            askOverwrite);
+
+        assertTrue("Generated XML file content is differ from expected one",
+            compareFilesInt(getClass().getResourceAsStream("/org/apache/ignite/schema/load/model/" + fileName),
+                new File(OUT_DIR_PATH + "/" + fileName), "XML generated by Apache Ignite Schema Load utility"));
+    }
+}


Mime
View raw message