Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-32 47266bb6f -> 69feb3925


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/69feb392/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/SchemaLoadApp.java
----------------------------------------------------------------------
diff --git 
a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/SchemaLoadApp.java
 
b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/SchemaLoadApp.java
index 4aca16a..c373654 100644
--- 
a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/SchemaLoadApp.java
+++ 
b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/SchemaLoadApp.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.schema.ui;
 
 import javafx.application.*;
-import javafx.beans.property.*;
 import javafx.beans.value.*;
 import javafx.collections.*;
 import javafx.concurrent.*;
@@ -29,20 +28,18 @@ import javafx.scene.control.*;
 import javafx.scene.layout.*;
 import javafx.stage.*;
 import javafx.util.*;
-import org.apache.ignite.lang.*;
 import org.apache.ignite.schema.generator.*;
+import org.apache.ignite.schema.model.*;
+import org.apache.ignite.schema.parser.*;
 import org.gridgain.grid.cache.query.*;
 
 import java.io.*;
-import java.math.*;
 import java.net.*;
 import java.sql.*;
-import java.sql.Date;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.prefs.*;
 
-import static java.sql.Types.*;
 import static javafx.embed.swing.SwingFXUtils.*;
 import static org.apache.ignite.schema.ui.Controls.*;
 
@@ -137,7 +134,6 @@ public class SchemaLoadApp extends Application {
 
     /** */
     private final ExecutorService exec = Executors.newSingleThreadExecutor(new 
ThreadFactory() {
-        /** {@inheritDoc} */
         @Override public Thread newThread(Runnable r) {
             Thread t = new Thread(r, "schema-load-worker");
 
@@ -202,7 +198,7 @@ public class SchemaLoadApp extends Application {
                 long started = System.currentTimeMillis();
 
                 try (Connection conn = connect()) {
-                    pojos = parse(conn);
+                    pojos = DatabaseMetadataParser.parse(conn);
                 }
 
                 perceptualDelay(started);
@@ -263,9 +259,9 @@ public class SchemaLoadApp extends Application {
      * Generate XML and POJOs.
      */
     private void generate() {
-        Collection<PojoDescriptor> selItems = selectedItems();
+        final Collection<PojoDescriptor> selPojos = selectedItems();
 
-        if (selItems.isEmpty()) {
+        if (selPojos.isEmpty()) {
             MessageBox.warningDialog(owner, "Please select tables to generate 
XML and POJOs files!");
 
             return;
@@ -280,11 +276,10 @@ public class SchemaLoadApp extends Application {
         final File destFolder = new File(outFolder);
 
         Runnable task = new Task<Void>() {
-            private void checkEmpty(Collection<GridCacheQueryTypeDescriptor> 
items,
-                final PojoDescriptor pojo, String msg) {
-                if (items.isEmpty()) {
+            private void checkEmpty(final PojoDescriptor pojo, 
Collection<GridCacheQueryTypeDescriptor> descs,
+                String msg) {
+                if (descs.isEmpty()) {
                     Platform.runLater(new Runnable() {
-                        /** {@inheritDoc} */
                         @Override public void run() {
                             pojosTbl.getSelectionModel().select(pojo);
                         }
@@ -304,41 +299,19 @@ public class SchemaLoadApp extends Application {
                 Collection<GridCacheQueryTypeMetadata> all = new ArrayList<>();
 
                 boolean constructor = pojoConstructorCh.isSelected();
-                boolean include = pojoIncludeKeysCh.isSelected();
+                boolean includeKeys = pojoIncludeKeysCh.isSelected();
                 boolean singleXml = xmlSingleFileCh.isSelected();
 
                 ConfirmCallable askOverwrite = new ConfirmCallable(owner, 
"File already exists: %s\nOverwrite?");
 
                 // Generate XML and POJO.
-                for (PojoDescriptor pojo : pojos) {
+                for (PojoDescriptor pojo : selPojos) {
                     if (pojo.selected()) {
-                        GridCacheQueryTypeMetadata meta = pojo.metadata();
-
-                        Collection<GridCacheQueryTypeDescriptor> keys = new 
ArrayList<>();
-
-                        Collection<GridCacheQueryTypeDescriptor> vals = new 
ArrayList<>();
-
-                        // Fill list with key and value type descriptors.
-                        for (PojoField fld : pojo.fields()) {
-                            GridCacheQueryTypeDescriptor desc = 
fld.descriptor();
-
-                            if (fld.key()) {
-                                keys.add(desc);
-
-                                if (include)
-                                    vals.add(desc);
-                            }
-                            else
-                                vals.add(desc);
-                        }
-
-                        checkEmpty(keys, pojo, "No key fields specified for 
type: ");
-
-                        checkEmpty(vals, pojo, "No value fields specified for 
type: ");
+                        GridCacheQueryTypeMetadata meta = 
pojo.metadata(includeKeys);
 
-                        meta.setKeyDescriptors(keys);
+                        checkEmpty(pojo, meta.getKeyDescriptors(), "No key 
fields specified for type: ");
 
-                        meta.setValueDescriptors(vals);
+                        checkEmpty(pojo, meta.getValueDescriptors(), "No value 
fields specified for type: ");
 
                         all.add(meta);
 
@@ -346,13 +319,11 @@ public class SchemaLoadApp extends Application {
                             XmlGenerator.generate(pkg, meta, new 
File(destFolder, meta.getType() + ".xml"),
                                 askOverwrite);
 
-                        PojoGenerator.generate(meta, outFolder, pkg, 
constructor, askOverwrite);
+                        PojoGenerator.generate(pojo, outFolder, pkg, 
constructor, includeKeys, askOverwrite);
                     }
                 }
 
-                if (all.isEmpty())
-                    throw new IllegalStateException("Nothing selected!");
-                else if (singleXml)
+                if (singleXml)
                     XmlGenerator.generate(pkg, all, new File(outFolder, 
"Ignite.xml"), askOverwrite);
 
                 perceptualDelay(started);
@@ -562,6 +533,11 @@ public class SchemaLoadApp extends Application {
         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" +
+            " POGO classes from database schema information.", 550), 3);
+
+        connPnl.wrap();
+
         jdbcDrvJarTf = connPnl.addLabeled("Driver JAR:", textField("Path to 
driver jar"));
 
         connPnl.add(button("...", "Select JDBC driver jar or zip", new 
EventHandler<ActionEvent>() {
@@ -594,6 +570,55 @@ public class SchemaLoadApp extends Application {
     }
 
     /**
+     * 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() {
@@ -607,19 +632,21 @@ public class SchemaLoadApp extends Application {
         genPnl.addRows(7);
 
         TableColumn<PojoDescriptor, Boolean> useCol = customColumn("Schema / 
Table", "use",
-            "If checked then this table will be used for XML and POJOs 
generation", SchemaCell.cellFactory());
-
-        TableColumn<PojoDescriptor, String> keyClsCol = textColumn("Key 
Class", "keyClass", "Key class name");
+            "If checked then this table will be used for XML and POJOs 
generation", PojoDescriptorCell.cellFactory());
 
-        keyClsCol.setOnEditCommit(new 
EventHandler<TableColumn.CellEditEvent<PojoDescriptor, String>>() {
-            @Override public void 
handle(TableColumn.CellEditEvent<PojoDescriptor, String> evt) {
-                System.out.println("committed: " + evt.getNewValue());
-
-                evt.getRowValue().keyClsName.set(evt.getNewValue() + "boom");
-            }
-        });
+        TableColumn<PojoDescriptor, String> keyClsCol = textColumn("Key 
Class", "keyClassName", "Key class name",
+            new TextColumnValidator<PojoDescriptor>() {
+                @Override public boolean valid(PojoDescriptor rowVal, String 
newVal) {
+                    return checkClassName(rowVal, newVal, true);
+                }
+            });
 
-        TableColumn<PojoDescriptor, String> valClsCol = textColumn("Value 
Class", "valueClass", "Value class name");
+        TableColumn<PojoDescriptor, String> valClsCol = textColumn("Value 
Class", "valueClassName", "Value class name",
+            new TextColumnValidator<PojoDescriptor>() {
+                @Override public boolean valid(PojoDescriptor rowVal, String 
newVal) {
+                    return checkClassName(rowVal, newVal, false);
+                }
+            });
 
         pojosTbl = tableView("Tables not found in database", useCol, 
keyClsCol, valClsCol);
 
@@ -630,73 +657,27 @@ public class SchemaLoadApp extends Application {
 
         TableColumn<PojoField, String> dbTypeNameCol = tableColumn("DB Type", 
"dbTypeName", "Field type in database");
 
-        TableColumn<PojoField, String> javaNameCol = textColumn("Ignite Name", 
"javaName", "Field name in POJO class");
-
-        TableColumn<PojoField, String> javaTypeNameCol = customColumn("Java 
Type", "javaTypeName",
-            "Field java type in POJO class", JavaTypeCell.cellFactory());
-
-        final TableView<PojoField> fieldsTbl = tableView("Select table to see 
table columns",
-            keyCol, dbNameCol, dbTypeNameCol, javaNameCol, javaTypeNameCol);
-
-        final Button upBtn = button(imageView("navigate_up", 24), "Move 
selected row up",
-            new EventHandler<ActionEvent>() {
-                @Override public void handle(ActionEvent evt) {
-                    TableView.TableViewSelectionModel<PojoField> selMdl = 
fieldsTbl.getSelectionModel();
-
-                    int selIdx = selMdl.getSelectedIndex();
-
-                    if (selIdx > 0) {
-                        ObservableList<PojoField> items = fieldsTbl.getItems();
-
-                        int newId = selIdx - 1;
-
-                        items.add(newId, items.remove(selIdx));
-
-                        if (newId == 0)
-                            fieldsTbl.requestFocus();
-
-                        selMdl.select(newId);
-                    }
-                }
-            });
-
-        upBtn.setDisable(true);
+        TableColumn<PojoField, String> javaNameCol = textColumn("Ignite 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, "Ignite name must 
be unique!");
 
-        final Button downBtn = button(imageView("navigate_down", 24), "Move 
selected row down",
-            new EventHandler<ActionEvent>() {
-                @Override public void handle(ActionEvent evt) {
-                    TableView.TableViewSelectionModel<PojoField> selMdl = 
fieldsTbl.getSelectionModel();
-
-                    int selIdx = selMdl.getSelectedIndex();
-
-                    ObservableList<PojoField> items = fieldsTbl.getItems();
-
-                    int maxIdx = items.size() - 1;
-
-                    if (selIdx < maxIdx) {
-                        int newId = selIdx + 1;
-
-                        items.add(newId, items.remove(selIdx));
-
-                        if (newId == maxIdx)
-                            fieldsTbl.requestFocus();
-
-                        selMdl.select(newId);
+                            return false;
+                        }
 
-                    }
+                    return true;
                 }
             });
 
-        downBtn.setDisable(true);
+        TableColumn<PojoField, String> javaTypeNameCol = customColumn("Java 
Type", "javaTypeName",
+            "Field java type in POJO class", JavaTypeCell.cellFactory());
 
-        fieldsTbl.getSelectionModel().selectedIndexProperty().addListener(new 
ChangeListener<Number>() {
-            @Override public void changed(ObservableValue<? extends Number> 
observable, Number oldVal, Number newVal) {
-                upBtn.setDisable(newVal == null || newVal.intValue() == 0);
-                downBtn.setDisable(newVal == null || newVal.intValue() == 
fieldsTbl.getItems().size() - 1);
-            }
-        });
+        final TableView<PojoField> fieldsTbl = tableView("Select table to see 
table columns",
+            keyCol, dbNameCol, dbTypeNameCol, javaNameCol, javaTypeNameCol);
 
-        genPnl.add(splitPane(pojosTbl, borderPane(null, fieldsTbl, null, null, 
vBox(10, upBtn, downBtn)), 0.6), 3);
+        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);
@@ -704,62 +685,11 @@ public class SchemaLoadApp extends Application {
         keyValPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         keyValPnl.addColumn();
 
-//        keyValPnl.add(button("Apply", "Change key and value class names", 
new EventHandler<ActionEvent>() {
-//            @Override public void handle(ActionEvent evt) {
-//                if (checkInput(keyClsTf, true, "Key class name must not be 
empty!") ||
-//                    checkInput(valClsTf, true, "Value class name must not be 
empty!"))
-//                    return;
-//
-//                String keyCls = keyClsTf.getText().trim();
-//
-//                String valCls = valClsTf.getText().trim();
-//
-//                if (keyCls.equals(valCls)) {
-//                    MessageBox.warningDialog(owner, "Key class name must be 
different from value class name!");
-//
-//                    keyClsTf.requestFocus();
-//
-//                    return;
-//                }
-//
-//                for (PojoDescriptor pojo : pojos)
-//                    if (pojo != curPojo) {
-//                        String pojoKeyCls = pojo.keyClassName();
-//
-//                        String pojoValCls = pojo.valueClassName();
-//
-//                        if (keyCls.equals(pojoKeyCls) || 
keyCls.equals(pojoValCls)) {
-//                            MessageBox.warningDialog(owner, "Key class name 
must be unique!");
-//
-//                            keyClsTf.requestFocus();
-//
-//                            return;
-//                        }
-//
-//                        if (valCls.equals(pojoKeyCls) || 
valCls.equals(pojoValCls)) {
-//                            MessageBox.warningDialog(owner, "Value class 
name must be unique!");
-//
-//                            valClsTf.requestFocus();
-//
-//                            return;
-//                        }
-//                    }
-//
-//                curPojo.keyClassName(keyCls);
-//                curPojo.valueClassName(valCls);
-//            }
-//        }));
-//
-//        keyValPnl.setDisable(true);
-//
-//        genPnl.add(keyValPnl, 2);
-
         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>() {
-            /** {@inheritDoc} */
             @Override public void handle(ActionEvent evt) {
                 DirectoryChooser dc = new DirectoryChooser();
 
@@ -794,7 +724,6 @@ public class SchemaLoadApp extends Application {
 
         final Button renBtn = button("Rename", "Replace Ignite names by 
provided regular expression for current table",
             new EventHandler<ActionEvent>() {
-                /** {@inheritDoc} */
                 @Override public void handle(ActionEvent evt) {
                     if (curPojo == null) {
                         MessageBox.warningDialog(owner, "Please select table 
to rename Ignite names!");
@@ -821,7 +750,6 @@ public class SchemaLoadApp extends Application {
         renBtn.setDisable(true);
 
         final Button revertBtn = button("Revert", "Revert changes to Ignite 
names for current table", new EventHandler<ActionEvent>() {
-            /** {@inheritDoc} */
             @Override public void handle(ActionEvent evt) {
                 if (curPojo != null)
                     curPojo.revertJavaNames();
@@ -835,7 +763,6 @@ public class SchemaLoadApp extends Application {
             renBtn,
             button("Rename All", "Replace Ignite names by provided regular 
expression for all selected tables",
                 new EventHandler<ActionEvent>() {
-                    /** {@inheritDoc} */
                     @Override public void handle(ActionEvent evt) {
                         if (checkInput(regexTf, false, "Regular expression 
should not be empty!"))
                             return;
@@ -868,7 +795,6 @@ public class SchemaLoadApp extends Application {
                 }),
             revertBtn,
             button("Revert All", "Revert changes to Ignite names for all 
selected tables", new EventHandler<ActionEvent>() {
-                /** {@inheritDoc} */
                 @Override public void handle(ActionEvent evt) {
                     Collection<PojoDescriptor> selItems = selectedItems();
 
@@ -891,7 +817,7 @@ public class SchemaLoadApp extends Application {
         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) {
+                if (newItem != null && newItem.parent() != null) {
                     curPojo = newItem;
 
                     fieldsTbl.setItems(curPojo.fields());
@@ -910,8 +836,6 @@ public class SchemaLoadApp extends Application {
 
                     renBtn.setDisable(true);
                     revertBtn.setDisable(true);
-                    upBtn.setDisable(true);
-                    downBtn.setDisable(true);
                 }
             }
         });
@@ -1043,260 +967,6 @@ public class SchemaLoadApp extends Application {
     }
 
     /**
-     * @param name Source name.
-     * @return String converted to java class name notation.
-     */
-    private String toJavaClassName(String name) {
-        int len = name.length();
-
-        StringBuilder buf = new StringBuilder(len);
-
-        boolean capitalizeNext = true;
-
-        for (int i = 0; i < len; i++) {
-            char ch = name.charAt(i);
-
-            if (Character.isWhitespace(ch) || '_' == ch)
-                capitalizeNext = true;
-            else if (capitalizeNext) {
-                buf.append(Character.toUpperCase(ch));
-
-                capitalizeNext = false;
-            }
-            else
-                buf.append(Character.toLowerCase(ch));
-        }
-
-        return buf.toString();
-    }
-
-    /**
-     * @param name Source name.
-     * @return String converted to java field name notation.
-     */
-    private String toJavaFieldName(String name) {
-        String javaName = toJavaClassName(name);
-
-        return Character.toLowerCase(javaName.charAt(0)) + 
javaName.substring(1);
-    }
-
-    /**
-     * Convert JDBC data type to java type.
-     *
-     * @param type JDBC SQL data type.
-     * @return Java data type.
-     */
-    private Class<?> dataType(int type) {
-        switch (type) {
-            case BIT:
-            case BOOLEAN:
-                return Boolean.class;
-
-            case TINYINT:
-                return Byte.class;
-
-            case SMALLINT:
-                return Short.class;
-
-            case INTEGER:
-                return Integer.class;
-
-            case BIGINT:
-                return Long.class;
-
-            case REAL:
-                return Float.class;
-
-            case FLOAT:
-            case DOUBLE:
-                return Double.class;
-
-            case NUMERIC:
-            case DECIMAL:
-                return BigDecimal.class;
-
-            case CHAR:
-            case VARCHAR:
-            case LONGVARCHAR:
-            case NCHAR:
-            case NVARCHAR:
-            case LONGNVARCHAR:
-                return String.class;
-
-            case DATE:
-                return Date.class;
-
-            case TIME:
-                return Time.class;
-
-            case TIMESTAMP:
-                return Timestamp.class;
-
-            case BINARY:
-            case VARBINARY:
-            case LONGVARBINARY:
-            case ARRAY:
-            case BLOB:
-            case CLOB:
-            case NCLOB:
-                return Array.class;
-
-            case NULL:
-                return Void.class;
-
-            case DATALINK:
-                return URL.class;
-
-            // OTHER, JAVA_OBJECT, DISTINCT, STRUCT, REF, ROWID, SQLXML
-            default:
-                return Object.class;
-        }
-    }
-
-    /**
-     * Parse database metadata.
-     *
-     * @param dbMeta Database metadata.
-     * @param catalog Catalog name.
-     * @param schema Schema name.
-     * @param tbl Table name.
-     * @return New initialized instance of {@code GridCacheQueryTypeMetadata}.
-     * @throws SQLException If parsing failed.
-     */
-    private PojoDescriptor parseTable(PojoDescriptor parent, DatabaseMetaData 
dbMeta, String catalog,
-        String schema, String tbl) throws SQLException {
-        GridCacheQueryTypeMetadata typeMeta = new GridCacheQueryTypeMetadata();
-
-        typeMeta.setSchema(schema);
-        typeMeta.setTableName(tbl);
-
-        typeMeta.setType(toJavaClassName(tbl));
-        typeMeta.setKeyType(typeMeta.getType() + "Key");
-
-        Collection<GridCacheQueryTypeDescriptor> keyDescs = 
typeMeta.getKeyDescriptors();
-        Collection<GridCacheQueryTypeDescriptor> valDescs = 
typeMeta.getValueDescriptors();
-
-        Map<String, Class<?>> qryFields = typeMeta.getQueryFields();
-        Map<String, Class<?>> ascFields = typeMeta.getAscendingFields();
-        Map<String, Class<?>> descFields = typeMeta.getDescendingFields();
-        Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> 
groups = typeMeta.getGroups();
-
-        Set<String> pkFlds = new LinkedHashSet<>();
-
-        try (ResultSet pk = dbMeta.getPrimaryKeys(catalog, schema, tbl)) {
-            while (pk.next())
-                pkFlds.add(pk.getString(4));
-        }
-
-        try (ResultSet flds = dbMeta.getColumns(catalog, schema, tbl, null)) {
-            while (flds.next()) {
-                String dbName = flds.getString(4);
-                int dbType = flds.getInt(5);
-
-                String javaName = toJavaFieldName(dbName);
-                Class<?> javaType = dataType(dbType);
-
-                GridCacheQueryTypeDescriptor desc = new 
GridCacheQueryTypeDescriptor(javaName, javaType, dbName, dbType);
-
-                if (pkFlds.contains(dbName))
-                    keyDescs.add(desc);
-                else
-                    valDescs.add(desc);
-
-                qryFields.put(javaName, javaType);
-            }
-        }
-
-        try (ResultSet idxs = dbMeta.getIndexInfo(catalog, schema, tbl, false, 
true)) {
-            while (idxs.next()) {
-                String idx = toJavaFieldName(idxs.getString(6));
-                String col = toJavaFieldName(idxs.getString(9));
-                String askOrDesc = idxs.getString(10);
-
-                LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> 
idxCols = groups.get(idx);
-
-                if (idxCols == null) {
-                    idxCols = new LinkedHashMap<>();
-
-                    groups.put(idx, idxCols);
-                }
-
-                Class<?> dataType = qryFields.get(col);
-
-                Boolean desc = askOrDesc != null ? "D".equals(askOrDesc) : 
null;
-
-                if (desc != null) {
-                    if (desc)
-                        descFields.put(col, dataType);
-                    else
-                        ascFields.put(col, dataType);
-                }
-
-                idxCols.put(col, new IgniteBiTuple<Class<?>, 
Boolean>(dataType, desc));
-            }
-        }
-
-        List<PojoField> flds = new ArrayList<>();
-
-        return new PojoDescriptor(parent, typeMeta, flds);
-    }
-
-    /**
-     * Parse database metadata.
-     *
-     * @param conn Connection to database.
-     * @return Map with schemes and tables metadata.
-     * @throws SQLException If parsing failed.
-     */
-    private ObservableList<PojoDescriptor> parse(Connection conn) throws 
SQLException {
-        DatabaseMetaData dbMeta = conn.getMetaData();
-
-        List<PojoDescriptor> res = new ArrayList<>();
-
-        try (ResultSet schemas = dbMeta.getSchemas()) {
-            while (schemas.next()) {
-                String schema = schemas.getString(1);
-
-                // Skip system tables from INFORMATION_SCHEMA.
-                if ("INFORMATION_SCHEMA".equalsIgnoreCase(schema))
-                    continue;
-
-                String catalog = schemas.getString(2);
-
-                PojoDescriptor parent = PojoDescriptor.createSchema(schema);
-
-                List<PojoDescriptor> children = new ArrayList<>();
-
-                try (ResultSet tbls = dbMeta.getTables(catalog, schema, "%", 
null)) {
-                    while (tbls.next()) {
-                        String tbl = tbls.getString(3);
-
-                        children.add(parseTable(parent, dbMeta, catalog, 
schema, tbl));
-                    }
-                }
-
-                if (!children.isEmpty()) {
-                    parent.children(children);
-
-                    res.add(parent);
-                    res.addAll(children);
-                }
-            }
-        }
-
-        Collections.sort(res, new Comparator<PojoDescriptor>() {
-            @Override public int compare(PojoDescriptor o1, PojoDescriptor o2) 
{
-                GridCacheQueryTypeMetadata t1 = o1.typeMeta;
-                GridCacheQueryTypeMetadata t2 = o2.typeMeta;
-
-                return (t1.getSchema() + 
t1.getTableName()).compareTo(t2.getSchema() + t2.getTableName());
-            }
-        });
-
-        return FXCollections.observableList(res);
-    }
-
-    /**
      * Schema load utility launcher.
      *
      * @param args Command line arguments passed to the application.
@@ -1330,568 +1000,6 @@ public class SchemaLoadApp extends Application {
     }
 
     /**
-     * Field descriptor with properties for JavaFX GUI bindings.
-     */
-    public static class PojoField {
-        /** If this field belongs to primary key. */
-        private final BooleanProperty key;
-
-        /** Field name for POJO. */
-        private final StringProperty javaName;
-
-        /** Field type for POJO. */
-        private final StringProperty javaTypeName;
-
-        /** Field name in database. */
-        private final StringProperty dbName;
-
-        /** Field type in database. */
-        private final StringProperty dbTypeName;
-
-        /** Is NULL allowed for field in database. */
-        private final boolean nullable;
-
-        /** Field type descriptor. */
-        private final GridCacheQueryTypeDescriptor desc;
-
-        /** List of possible java type conversions. */
-        private final ObservableList<String> conversions;
-
-        /** */
-        private static final Map<String, Class<?>> classesMap = new 
HashMap<>();
-
-        /**
-         * @param clss Class to add.
-         */
-        private static void fillClassesMap(Class<?>... clss) {
-            for (Class<?> cls : clss)
-                classesMap.put(cls.getName(), cls);
-        }
-
-        /**
-         * @param clss List of classes to get class names.
-         * @return List of classes names to show in UI for manual select.
-         */
-        private static List<String> classNames(Class<?>... clss) {
-            List<String> names = new ArrayList<>(clss.length);
-
-            for (Class<?> cls : clss)
-                names.add(cls.getName());
-
-            return names;
-        }
-
-        /** Null number conversions. */
-        private static final ObservableList<String> NULL_NUM_CONVERSIONS = 
FXCollections.observableArrayList();
-
-        /** Not null number conversions. */
-        private static final ObservableList<String> NOT_NULL_NUM_CONVERSIONS = 
FXCollections.observableArrayList();
-
-        static {
-            List<String> primitives = classNames(boolean.class, byte.class, 
short.class,
-                int.class, long.class, float.class, double.class);
-
-            List<String> objects = classNames(Boolean.class, Byte.class, 
Short.class, Integer.class,
-                Long.class, Float.class, Double.class, BigDecimal.class);
-
-            NULL_NUM_CONVERSIONS.addAll(objects);
-
-            NOT_NULL_NUM_CONVERSIONS.addAll(primitives);
-            NOT_NULL_NUM_CONVERSIONS.addAll(objects);
-
-            fillClassesMap(boolean.class, Boolean.class,
-                byte.class, Byte.class,
-                short.class, Short.class,
-                int.class, Integer.class,
-                long.class, Long.class,
-                float.class, Float.class,
-                double.class, Double.class,
-                BigDecimal.class,
-                String.class,
-                java.sql.Date.class, java.sql.Time.class, 
java.sql.Timestamp.class,
-                Array.class, Void.class, URL.class, Object.class);
-        }
-
-        /**
-         * @param dbType Database type.
-         * @param nullable Nullable.
-         * @param dflt Default.
-         * @return List of possible type conversions.
-         */
-        private static ObservableList<String> conversions(int dbType, boolean 
nullable, String dflt) {
-            switch (dbType) {
-                case TINYINT:
-                case SMALLINT:
-                case INTEGER:
-                case BIGINT:
-                case REAL:
-                case FLOAT:
-                case DOUBLE:
-                    return nullable ? NULL_NUM_CONVERSIONS : 
NOT_NULL_NUM_CONVERSIONS;
-
-                default:
-                    return FXCollections.singletonObservableList(dflt);
-            }
-        }
-
-        /**
-         * @param key {@code true} if this field belongs to primary key.
-         * @param nullable {@code true} if {@code NULL} is allowed for this 
field in database.
-         * @param desc Field type descriptor.
-         */
-        private PojoField(boolean key, boolean nullable, 
GridCacheQueryTypeDescriptor desc) {
-            this.desc = desc;
-            this.key = new SimpleBooleanProperty(key);
-
-            javaName = new SimpleStringProperty(desc.getJavaName());
-
-            String typeName = desc.getJavaType().getName();
-
-            javaTypeName = new SimpleStringProperty(typeName);
-
-            dbName = new SimpleStringProperty(desc.getDbName());
-
-            dbTypeName = new 
SimpleStringProperty(jdbcTypeName(desc.getDbType()));
-
-            this.nullable = nullable;
-
-            conversions = conversions(desc.getDbType(), nullable, typeName);
-        }
-
-        /**
-         * Copy constructor.
-         *
-         * @param src Source POJO field descriptor.
-         */
-        private PojoField(PojoField src) {
-            this(src.key(), src.nullable(), src.descriptor());
-        }
-
-        /**
-         * @param jdbcType String name for JDBC type.
-         */
-        private String jdbcTypeName(int jdbcType) {
-            switch (jdbcType) {
-                case BIT:
-                    return "BIT";
-                case TINYINT:
-                    return "TINYINT";
-                case SMALLINT:
-                    return "SMALLINT";
-                case INTEGER:
-                    return "INTEGER";
-                case BIGINT:
-                    return "BIGINT";
-                case FLOAT:
-                    return "FLOAT";
-                case REAL:
-                    return "REAL";
-                case DOUBLE:
-                    return "DOUBLE";
-                case NUMERIC:
-                    return "NUMERIC";
-                case DECIMAL:
-                    return "DECIMAL";
-                case CHAR:
-                    return "CHAR";
-                case VARCHAR:
-                    return "VARCHAR";
-                case LONGVARCHAR:
-                    return "LONGVARCHAR";
-                case DATE:
-                    return "DATE";
-                case TIME:
-                    return "TIME";
-                case TIMESTAMP:
-                    return "TIMESTAMP";
-                case BINARY:
-                    return "BINARY";
-                case VARBINARY:
-                    return "VARBINARY";
-                case LONGVARBINARY:
-                    return "LONGVARBINARY";
-                case NULL:
-                    return "NULL";
-                case OTHER:
-                    return "OTHER";
-                case JAVA_OBJECT:
-                    return "JAVA_OBJECT";
-                case DISTINCT:
-                    return "DISTINCT";
-                case STRUCT:
-                    return "STRUCT";
-                case ARRAY:
-                    return "ARRAY";
-                case BLOB:
-                    return "BLOB";
-                case CLOB:
-                    return "CLOB";
-                case REF:
-                    return "REF";
-                case DATALINK:
-                    return "DATALINK";
-                case BOOLEAN:
-                    return "BOOLEAN";
-                case ROWID:
-                    return "ROWID";
-                case NCHAR:
-                    return "NCHAR";
-                case NVARCHAR:
-                    return "NVARCHAR";
-                case LONGNVARCHAR:
-                    return "LONGNVARCHAR";
-                case NCLOB:
-                    return "NCLOB";
-                case SQLXML:
-                    return "SQLXML";
-                default:
-                    return "Unknown";
-            }
-        }
-
-        /**
-         * @return {@code true} if this field belongs to primary key.
-         */
-        public boolean key() {
-            return key.get();
-        }
-
-        /**
-         * @param pk {@code true} if this field belongs to primary key.
-         */
-        public void key(boolean pk) {
-            key.set(pk);
-        }
-
-        /**
-         * @return POJO field java name.
-         */
-        public String javaName() {
-            return javaName.get();
-        }
-
-        /**
-         * @param name POJO field java name.
-         */
-        public void javaName(String name) {
-            javaName.set(name);
-        }
-
-        /**
-         * @return POJO field java type name.
-         */
-        public String javaTypeName() {
-            return javaTypeName.get();
-        }
-
-        /**
-         * @return Type descriptor.
-         */
-        public GridCacheQueryTypeDescriptor descriptor() {
-            desc.setJavaName(javaName.get());
-            desc.setJavaType(classesMap.get(javaTypeName()));
-
-            return desc;
-        }
-
-        /**
-         * @return Is NULL allowed for field in database.
-         */
-        public boolean nullable() {
-            return nullable;
-        }
-
-        /**
-         * @return POJO field JDBC type in database.
-         */
-        public int dbType() {
-            return desc.getDbType();
-        }
-
-        /**
-         * @return Boolean property support for {@code key} property.
-         */
-        public BooleanProperty keyProperty() {
-            return key;
-        }
-
-        /**
-         * @return String property support for {@code javaName} property.
-         */
-        public StringProperty javaNameProperty() {
-            return javaName;
-        }
-
-        /**
-         * @return String property support for {@code javaTypeName} property.
-         */
-        public StringProperty javaTypeNameProperty() {
-            return javaTypeName;
-        }
-
-        /**
-         * @return String property support for {@code dbName} property.
-         */
-        public StringProperty dbNameProperty() {
-            return dbName;
-        }
-
-        /**
-         * @return String property support for {@code dbName} property.
-         */
-        public StringProperty dbTypeNameProperty() {
-            return dbTypeName;
-        }
-
-        /**
-         * @return List of possible java type conversions.
-         */
-        public ObservableList<String> conversions() {
-            return conversions;
-        }
-    }
-
-    /**
-     * Descriptor for java type.
-     */
-    public static class PojoDescriptor {
-        /** Selected property. */
-        private final BooleanProperty use;
-
-        /** Schema name to show on screen. */
-        private final String schema;
-
-        /** Table name to show on screen. */
-        private final String tbl;
-
-        /** Key class name to show on screen. */
-        private final StringProperty keyClsName;
-
-        /** Previous name for key class. */
-        private final String keyClsNamePrev;
-
-        /** Value class name to show on screen. */
-        private final StringProperty valClsName;
-
-        /** Previous name for value class. */
-        private final String valClsNamePrev;
-
-        /** Parent item (schema name). */
-        private final PojoDescriptor parent;
-
-        /** Children items (tables names). */
-        private Collection<PojoDescriptor> children = Collections.emptyList();
-
-        /** Indeterminate state of parent. */
-        private final BooleanProperty indeterminate = new 
SimpleBooleanProperty(false);
-
-        /** Java class fields. */
-        private final ObservableList<PojoField> fields;
-
-        /** Java class fields. */
-        private final List<PojoField> fieldsPrev;
-
-        /** Type metadata. */
-        private final GridCacheQueryTypeMetadata typeMeta;
-
-        private static PojoDescriptor createSchema(String schema) {
-            GridCacheQueryTypeMetadata schemaMeta = new 
GridCacheQueryTypeMetadata();
-
-            schemaMeta.setSchema(schema);
-            schemaMeta.setTableName("");
-
-            return new PojoDescriptor(null, schemaMeta, 
Collections.<PojoField>emptyList());
-        }
-
-        /**
-         * @param prn
-         * @param typeMeta
-         * @param flds
-         */
-        private PojoDescriptor(PojoDescriptor prn, GridCacheQueryTypeMetadata 
typeMeta, List<PojoField> flds) {
-            parent = prn;
-
-            boolean isTbl = parent != null;
-
-            schema = isTbl ? "" : typeMeta.getSchema();
-            tbl = isTbl ? typeMeta.getTableName() : "";
-
-            keyClsNamePrev = isTbl ? typeMeta.getKeyType() : "";
-            keyClsName = new SimpleStringProperty(keyClsNamePrev);
-
-            valClsNamePrev = isTbl ? typeMeta.getType() : "";
-            valClsName = new SimpleStringProperty(valClsNamePrev);
-
-            use = new SimpleBooleanProperty(true);
-
-            use.addListener(new ChangeListener<Boolean>() {
-                @Override public void changed(ObservableValue<? extends 
Boolean> val, Boolean oldVal, Boolean newVal) {
-                    for (PojoDescriptor child : children)
-                        child.use.set(newVal);
-
-                    if (parent != null && !parent.children.isEmpty()) {
-                        Iterator<PojoDescriptor> it = 
parent.children.iterator();
-
-                        boolean parentIndeterminate = false;
-                        boolean first = it.next().use.get();
-
-                        while (it.hasNext()) {
-                            if (it.next().use.get() != first) {
-                                parentIndeterminate = true;
-
-                                break;
-                            }
-                        }
-
-                        parent.indeterminate.set(parentIndeterminate);
-
-                        if (!parentIndeterminate)
-                            parent.use.set(first);
-                    }
-                }
-            });
-
-            if (isTbl) {
-                fieldsPrev = new ArrayList<>(flds.size());
-
-                for (PojoField fld : flds)
-                    fieldsPrev.add(new PojoField(fld));
-
-                fields = FXCollections.observableList(flds);
-
-//                Collection<GridCacheQueryTypeDescriptor> keys = 
typeMeta.getKeyDescriptors();
-//
-//                Collection<GridCacheQueryTypeDescriptor> vals = 
typeMeta.getValueDescriptors();
-//
-//                int sz = keys.size() + vals.size();
-//
-//                List<PojoField> flds = new ArrayList<>(sz);
-//                fieldsPrev = new ArrayList<>(sz);
-//
-//                for (GridCacheQueryTypeDescriptor key : keys) {
-//                    flds.add(new PojoField(true, false /* TODO: IGNITE-32 
FIX nullable*/, key));
-//                    fieldsPrev.add(new PojoField(true, false /* TODO: 
IGNITE-32 FIX nullable*/, key));
-//                }
-//
-//                for (GridCacheQueryTypeDescriptor val : vals) {
-//                    flds.add(new PojoField(false, false /* TODO: IGNITE-32 
FIX nullable*/, val));
-//                    fieldsPrev.add(new PojoField(false, false /* TODO: 
IGNITE-32 FIX nullable*/, val));
-//                }
-//
-//                fields = FXCollections.observableList(flds);
-            }
-            else {
-                fields = FXCollections.emptyObservableList();
-                fieldsPrev = FXCollections.emptyObservableList();
-            }
-
-            this.typeMeta = typeMeta;
-        }
-
-        /**
-         * @return {@code true} if POJO descriptor is a table descriptor and 
selected in GUI.
-         */
-        public boolean selected() {
-            return parent != null && use.get();
-        }
-
-        /**
-         * @return Boolean property support for {@code use} property.
-         */
-        public BooleanProperty useProperty() {
-            return use;
-        }
-
-        /**
-         * @return Boolean property support for parent {@code indeterminate} 
property.
-         */
-        public BooleanProperty indeterminate() {
-            return indeterminate;
-        }
-
-        /**
-         * @return Key class name property.
-         */
-        public StringProperty keyClassProperty() {
-            return keyClsName;
-        }
-
-        /**
-         * @return Value class name property.
-         */
-        public StringProperty valueClassProperty() {
-            return valClsName;
-        }
-
-        /**
-         * @return Schema name.
-         */
-        public String schema() {
-            return schema;
-        }
-
-        /**
-         * @return Table name.
-         */
-        public String table() {
-            return tbl;
-        }
-
-        /**
-         * Sets children items.
-         *
-         * @param children Items to set.
-         */
-        public void children(Collection<PojoDescriptor> children) {
-            this.children = children;
-        }
-
-        /**
-         * @return {@code true} if descriptor was changed by user via GUI.
-         */
-        public boolean changed() {
-            boolean diff = !keyClsName.get().equals(keyClsNamePrev) || 
!valClsName.get().equals(valClsNamePrev);
-
-            if (!diff)
-                for (int i = 0; i < fields.size(); i++) {
-                    PojoField cur = fields.get(i);
-                    PojoField prev = fieldsPrev.get(i);
-
-                    // User can change via GUI only key and java name 
properties.
-                    if (cur.key() != prev.key() || 
!cur.javaName().equals(prev.javaName())) {
-                        diff = true;
-
-                        break;
-                    }
-                }
-
-            return diff;
-        }
-
-        /**
-         * Revert changes to java names made by user.
-         */
-        public void revertJavaNames() {
-            for (int i = 0; i < fields.size(); i++)
-                fields.get(i).javaName(fieldsPrev.get(i).javaName());
-        }
-
-        /**
-         * @return Java class fields.
-         */
-        public ObservableList<PojoField> fields() {
-            return fields;
-        }
-
-        /**
-         * @return Type metadata.
-         */
-        public GridCacheQueryTypeMetadata metadata() {
-            return typeMeta;
-        }
-    }
-
-    /**
      * Special table cell to select possible java type conversions.
      */
     private static class JavaTypeCell extends TableCell<PojoField, String> {
@@ -1901,7 +1009,6 @@ public class SchemaLoadApp extends Application {
         /** 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>>() {
-                /** {@inheritDoc} */
                 @Override public TableCell<PojoField, String> 
call(TableColumn<PojoField, String> col) {
                     return new JavaTypeCell();
                 }
@@ -1915,7 +1022,6 @@ public class SchemaLoadApp extends Application {
             comboBox = new 
ComboBox<>(FXCollections.<String>emptyObservableList());
 
             comboBox.valueProperty().addListener(new ChangeListener<String>() {
-                /** {@inheritDoc} */
                 @Override public void changed(ObservableValue<? extends 
String> val, String oldVal, String newVal) {
                     if (isEditing())
                         commitEdit(newVal);
@@ -1969,17 +1075,19 @@ public class SchemaLoadApp extends Application {
     /**
      * Special table cell to select schema or table.
      */
-    private static class SchemaCell extends TableCell<PojoDescriptor, Boolean> 
{
+    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>>() {
-                /** {@inheritDoc} */
                 @Override public TableCell<PojoDescriptor, Boolean> 
call(TableColumn<PojoDescriptor, Boolean> col) {
-                    return new SchemaCell();
+                    return new PojoDescriptorCell();
                 }
             };
         }
 
+        /** Previous POJO bound to cell. */
+        private PojoDescriptor prevPojo;
+
         /** {@inheritDoc} */
         @Override public void updateItem(Boolean item, boolean empty) {
             super.updateItem(item, empty);
@@ -1988,16 +1096,20 @@ public class SchemaLoadApp extends Application {
                 TableRow row = getTableRow();
 
                 if (row != null) {
-                    final PojoDescriptor schemaItem = 
(PojoDescriptor)row.getItem();
+                    final PojoDescriptor pojo = (PojoDescriptor)row.getItem();
 
-                    if (schemaItem != null && getGraphic() == null) {
-                        boolean isTbl = schemaItem.schema.isEmpty();
+                    if (pojo != prevPojo) {
+                        prevPojo = pojo;
 
-                        final CheckBox ch = new CheckBox(isTbl ? 
schemaItem.table() : schemaItem.schema());
+                        boolean isTbl = pojo.parent() != null;
+
+                        CheckBox ch = new CheckBox(isTbl ? pojo.table() : 
pojo.schema());
 
                         ch.setAllowIndeterminate(false);
-                        
ch.selectedProperty().bindBidirectional(schemaItem.useProperty());
-                        
ch.indeterminateProperty().bindBidirectional(schemaItem.indeterminate());
+                        ch.setMnemonicParsing(false);
+
+                        
ch.indeterminateProperty().bindBidirectional(pojo.indeterminate());
+                        
ch.selectedProperty().bindBidirectional(pojo.useProperty());
 
                         Pane pnl = new HBox();
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/69feb392/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/TextColumnValidator.java
----------------------------------------------------------------------
diff --git 
a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/TextColumnValidator.java
 
b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/TextColumnValidator.java
new file mode 100644
index 0000000..d92ae08
--- /dev/null
+++ 
b/modules/schema-load/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);
+}

Reply via email to