You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/01/15 16:12:07 UTC

incubator-ignite git commit: # IGNITE-32 WIP: Added support for changing key and value class names.

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-32 4f96cd52c -> e81ad8439


# IGNITE-32 WIP: Added support for changing key and value class names.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/e81ad843
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/e81ad843
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/e81ad843

Branch: refs/heads/ignite-32
Commit: e81ad8439fff26ff242bc76fb669628ecaa3282e
Parents: 4f96cd5
Author: AKuznetsov <ak...@gridgain.com>
Authored: Thu Jan 15 22:12:03 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Thu Jan 15 22:12:03 2015 +0700

----------------------------------------------------------------------
 .../ignite/schema/db/DbMetadataParser.java      |   9 +-
 .../ignite/schema/pojo/PojoCodeGenerator.java   |  58 ++--
 .../org/apache/ignite/schema/ui/Controls.java   |  12 +-
 .../apache/ignite/schema/ui/PojoDescriptor.java |  69 ++--
 .../org/apache/ignite/schema/ui/PojoField.java  |  14 -
 .../apache/ignite/schema/ui/SchemaLoadApp.java  | 341 +++++++++++--------
 6 files changed, 288 insertions(+), 215 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e81ad843/modules/schema-load/src/main/java/org/apache/ignite/schema/db/DbMetadataParser.java
----------------------------------------------------------------------
diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/db/DbMetadataParser.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/db/DbMetadataParser.java
index 822d8d5..ec63d7b 100644
--- a/modules/schema-load/src/main/java/org/apache/ignite/schema/db/DbMetadataParser.java
+++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/db/DbMetadataParser.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.schema.db;
 
 import org.apache.ignite.lang.*;
+import org.apache.ignite.schema.ui.*;
 import org.gridgain.grid.cache.query.*;
 
 import java.math.*;
@@ -199,11 +200,11 @@ public class DbMetadataParser {
      * @return Map with schemes and tables metadata.
      * @throws SQLException If parsing failed.
      */
-    public static Map<String, Map<String, GridCacheQueryTypeMetadata>> parse(Connection conn)
+    public static Map<String, Map<String, PojoDescriptor>> parse(Connection conn)
         throws SQLException {
         DatabaseMetaData meta = conn.getMetaData();
 
-        Map<String, Map<String, GridCacheQueryTypeMetadata>> res = new HashMap<>();
+        Map<String, Map<String, PojoDescriptor>> res = new TreeMap<>();
 
         try (ResultSet schemas = meta.getSchemas()) {
             while (schemas.next()) {
@@ -215,13 +216,13 @@ public class DbMetadataParser {
 
                 String catalog = schemas.getString(2);
 
-                Map<String, GridCacheQueryTypeMetadata> items = new HashMap<>();
+                Map<String, PojoDescriptor> items = new TreeMap<>();
 
                 try (ResultSet tbls = meta.getTables(catalog, schema, "%", null)) {
                     while (tbls.next()) {
                         String tbl = tbls.getString(3);
 
-                        items.put(tbl, parse(meta, catalog, schema, tbl));
+                        items.put(tbl, new PojoDescriptor(parse(meta, catalog, schema, tbl)));
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e81ad843/modules/schema-load/src/main/java/org/apache/ignite/schema/pojo/PojoCodeGenerator.java
----------------------------------------------------------------------
diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/pojo/PojoCodeGenerator.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/pojo/PojoCodeGenerator.java
index 47946c6..4ddd4b1 100644
--- a/modules/schema-load/src/main/java/org/apache/ignite/schema/pojo/PojoCodeGenerator.java
+++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/pojo/PojoCodeGenerator.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.schema.pojo;
 
-import org.apache.ignite.schema.ui.*;
+import org.gridgain.grid.cache.query.*;
 
 import java.io.*;
 import java.util.*;
@@ -78,16 +78,14 @@ public class PojoCodeGenerator {
     /**
      * Generate java class code.
      *
-     * @param pojo POJO descriptor.
-     * @param key {@code true} if key class should be generated.
      * @param pkg Package name.
+     * @param type Type name.
+     * @param descs Type descriptors.
      * @param constructor If {@code true} then generate empty and full constructors.
      * @throws IOException If failed to write generated code into file.
      */
-    private static void generateCode(PojoDescriptor pojo, boolean key, String pkg, File pkgFolder, boolean constructor)
-        throws IOException {
-        String type = key ? pojo.keyClassName() : pojo.valueClassName();
-
+    private static void generateCode(String pkg, String type, Collection<GridCacheQueryTypeDescriptor> descs,
+        File pkgFolder, boolean constructor) throws IOException {
         Collection<String> src = new ArrayList<>(256);
 
         add0(src, "package " + pkg + ";");
@@ -110,14 +108,12 @@ public class PojoCodeGenerator {
 
         add0(src, "");
 
-        List<PojoField> fields = pojo.fields();
-
         // Fields.
-        for (PojoField field : fields) {
-            String fldName = field.javaName();
+        for (GridCacheQueryTypeDescriptor desc : descs) {
+            String fldName = desc.getJavaName();
 
             add1(src, "/** Value for " + fldName + ". */");
-            add1(src, "private " + field.javaTypeName() + " " + fldName + ";");
+            add1(src, "private " + desc.getJavaType().getSimpleName() + " " + fldName + ";");
             add0(src, "");
         }
 
@@ -137,17 +133,17 @@ public class PojoCodeGenerator {
             add1(src, " */");
             add1(src, "public " + type + "(");
 
-            Iterator<PojoField> it = fields.iterator();
+            Iterator<GridCacheQueryTypeDescriptor> it = descs.iterator();
 
             while (it.hasNext()) {
-                PojoField field = it.next();
+                GridCacheQueryTypeDescriptor desc = it.next();
 
-                add2(src, field.javaTypeName() + " " + field.javaName() + (it.hasNext() ? "," : ""));
+                add2(src, desc.getJavaType().getSimpleName() + " " + desc.getJavaName() + (it.hasNext() ? "," : ""));
             }
             add1(src, ") {");
 
-            for (PojoField field : fields)
-                add2(src, String.format("this.%1$s = %1$s;", field.javaName()));
+            for (GridCacheQueryTypeDescriptor desc : descs)
+                add2(src, String.format("this.%1$s = %1$s;", desc.getJavaName()));
 
             add1(src, "}");
 
@@ -155,10 +151,10 @@ public class PojoCodeGenerator {
         }
 
         // Methods.
-        for (PojoField field : fields) {
-            String fldName = field.javaName();
+        for (GridCacheQueryTypeDescriptor desc : descs) {
+            String fldName = desc.getJavaName();
 
-            String fldType = field.javaTypeName();
+            String fldType = desc.getJavaType().getSimpleName();
 
             String mtdName = capitalizeFirst(fldName);
 
@@ -199,10 +195,10 @@ public class PojoCodeGenerator {
 
         add2(src, String.format("%1$s that = (%1$s)o;", type));
 
-        for (PojoField field : fields) {
+        for (GridCacheQueryTypeDescriptor desc : descs) {
             add0(src, "");
             add2(src, String.format("if (%1$s != null ? !%1$s.equals(that.%1$s) : that.%1$s != null)",
-                field.javaName()));
+                desc.getJavaName()));
             add3(src, "return false;");
         }
 
@@ -215,16 +211,16 @@ public class PojoCodeGenerator {
         add1(src, "/** {@inheritDoc} */");
         add1(src, "@Override public int hashCode() {");
 
-        Iterator<PojoField> it = fields.iterator();
+        Iterator<GridCacheQueryTypeDescriptor> it = descs.iterator();
 
-        add2(src, String.format("int res = %1$s != null ? %1$s.hashCode() : 0;", it.next().javaName()));
+        add2(src, String.format("int res = %1$s != null ? %1$s.hashCode() : 0;", it.next().getJavaName()));
 
         if (it.hasNext()) {
             add0(src, "");
 
             while (it.hasNext())
                 add2(src, String.format("res = 31 * res + (%1$s != null ? %1$s.hashCode() : 0);",
-                    it.next().javaName()));
+                    it.next().getJavaName()));
         }
 
         add0(src, "");
@@ -237,8 +233,8 @@ public class PojoCodeGenerator {
         add1(src, "@Override public String toString() {");
         add2(src, "return \"" + type + " [\" + ");
 
-        for (PojoField field : fields)
-            add3(src, String.format("\" %1$s=\" + %1$s +", field.javaName()));
+        for (GridCacheQueryTypeDescriptor desc : descs)
+            add3(src, String.format("\" %1$s=\" + %1$s +", desc.getJavaName()));
 
         add3(src, "\"]\";");
         add1(src, "}");
@@ -254,21 +250,21 @@ public class PojoCodeGenerator {
     /**
      * Generate source code for type by its metadata.
      *
-     * @param pojo POJO descriptor.
+     * @param meta Type metadata.
      * @param outFolder Output folder.
      * @param pkg Types package.
      * @param constructor If {@code true} then generate empty and full constructors.
      * @throws IOException If failed to write generated code into file.
      */
-    public static void generate(PojoDescriptor pojo, String outFolder, String pkg, boolean constructor)
+    public static void generate(GridCacheQueryTypeMetadata meta, String outFolder, String pkg, boolean constructor)
         throws IOException {
         File pkgFolder = new File(outFolder, pkg.replace('.', File.separatorChar));
 
         if (!pkgFolder.exists() && !pkgFolder.mkdirs())
             throw new IOException("Failed to create folders for package: " + pkg);
 
-        generateCode(pojo, true, pkg, pkgFolder, constructor);
+        generateCode(pkg, meta.getKeyType(), meta.getKeyDescriptors(), pkgFolder, constructor);
 
-        generateCode(pojo, false, pkg, pkgFolder, constructor);
+        generateCode(pkg, meta.getType(), meta.getValueDescriptors(), pkgFolder, constructor);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e81ad843/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/Controls.java
----------------------------------------------------------------------
diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/Controls.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/Controls.java
index dcae5a3..039b478 100644
--- a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/Controls.java
+++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/Controls.java
@@ -50,14 +50,16 @@ public class Controls {
     /**
      * Create grid pane with default padding.
      *
-     * @param dfltPadding If {@code true} than set default padding for pane.
+     * @param top Top padding
+     * @param right Right padding.
+     * @param bottom Bottom padding.
+     * @param left Left padding.
      * @return New {@code GridPaneEx} instance.
      */
-    public static GridPaneEx paneEx(boolean dfltPadding) {
-        GridPaneEx paneEx =  new GridPaneEx();
+    public static GridPaneEx paneEx(double top, double right, double bottom, double left) {
+        GridPaneEx paneEx = new GridPaneEx();
 
-        if (dfltPadding)
-            paneEx.setPadding(DFLT_PADDING);
+        paneEx.setPadding(new Insets(top, right, bottom, left));
 
         return paneEx;
     }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e81ad843/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoDescriptor.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoDescriptor.java
index 2d6db52..c8c9c7f 100644
--- a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoDescriptor.java
+++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoDescriptor.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.schema.ui;
 
 import javafx.collections.*;
+import org.gridgain.grid.cache.query.*;
 
 import java.util.*;
 
@@ -25,15 +26,9 @@ import java.util.*;
  * Descriptor for java type.
  */
 public class PojoDescriptor {
-    /** Name for key class. */
-    private String keyClsName;
-
     /** Previous name for key class. */
     private final String keyClsNamePrev;
 
-    /** Name for value class. */
-    private String valClsName;
-
     /** Previous name for value class. */
     private final String valClsNamePrev;
 
@@ -43,32 +38,48 @@ public class PojoDescriptor {
     /** Java class fields. */
     private final List<PojoField> fieldsPrev;
 
+    /** Type metadata. */
+    private final GridCacheQueryTypeMetadata meta;
+
     /**
      * Type descriptor.
      *
-     * @param type Type name.
-     * @param fields List of POJO fields descriptor.
+     * @param meta Type metadata.
      */
-    public PojoDescriptor(String type, List<PojoField> fields) {
-        keyClsName = type + "Key";
-        keyClsNamePrev = keyClsName;
+    public PojoDescriptor(GridCacheQueryTypeMetadata meta) {
+        this.meta = meta;
+
+        keyClsNamePrev = meta.getKeyType();
+
+        valClsNamePrev = meta.getType();
 
-        valClsName = type;
-        valClsNamePrev = valClsName;
+        Collection<GridCacheQueryTypeDescriptor> keys = meta.getKeyDescriptors();
 
-        this.fields = FXCollections.observableList(fields);
+        Collection<GridCacheQueryTypeDescriptor> vals = meta.getValueDescriptors();
 
-        fieldsPrev = new ArrayList<>(fields.size());
+        int sz = keys.size() + vals.size();
 
-        for (PojoField field : fields)
-            fieldsPrev.add(new PojoField(field));
+        List<PojoField> flds = new ArrayList<>(sz);
+        fieldsPrev = new ArrayList<>(sz);
+
+        for (GridCacheQueryTypeDescriptor key : keys) {
+            flds.add(new PojoField(true, key));
+            fieldsPrev.add(new PojoField(true, key));
+        }
+
+        for (GridCacheQueryTypeDescriptor val : vals) {
+            flds.add(new PojoField(false, val));
+            fieldsPrev.add(new PojoField(false, val));
+        }
+
+        fields = FXCollections.observableList(flds);
     }
 
     /**
      * @return {@code true} if descriptor was changed by user via GUI.
      */
     public boolean changed() {
-        boolean diff = !keyClsName.equals(keyClsNamePrev) || !valClsName.equals(valClsNamePrev);
+        boolean diff = !meta.getKeyType().equals(keyClsNamePrev) || !meta.getType().equals(valClsNamePrev);
 
         if (!diff)
             for (int i = 0; i < fields.size(); i++) {
@@ -98,14 +109,28 @@ public class PojoDescriptor {
      * @return Name for key class.
      */
     public String keyClassName() {
-        return keyClsName;
+        return meta.getKeyType();
+    }
+
+    /**
+     * @param name Name for key class.
+     */
+    public void keyClassName(String name) {
+        meta.setKeyType(name);
     }
 
     /**
      * @return Name for value class.
      */
     public String valueClassName() {
-        return valClsName;
+        return meta.getType();
+    }
+
+    /**
+     * @param name Name for value class.
+     */
+    public void valueClassName(String name) {
+        meta.setKeyType(name);
     }
 
     /**
@@ -114,4 +139,8 @@ public class PojoDescriptor {
     public ObservableList<PojoField> fields() {
         return fields;
     }
+
+    public GridCacheQueryTypeMetadata metadata() {
+        return meta;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e81ad843/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoField.java
----------------------------------------------------------------------
diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoField.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoField.java
index c9fe987..9e9e16e 100644
--- a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoField.java
+++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/PojoField.java
@@ -58,20 +58,6 @@ public class PojoField {
     }
 
     /**
-     * Copy constructor.
-     *
-     * @param src Source field to copy from.
-     */
-    public PojoField(PojoField src) {
-        desc = src.desc;
-        key = new SimpleBooleanProperty(src.key());
-        javaName = new SimpleStringProperty(desc.getJavaName());
-        javaTypeName = new SimpleStringProperty(desc.getJavaType().getName());
-        dbName = new SimpleStringProperty(desc.getDbName());
-        dbTypeName = new SimpleStringProperty(jdbcTypeName(desc.getDbType()));
-    }
-
-    /**
      * @param jdbcType String name for JDBC type.
      */
     private static String jdbcTypeName(int jdbcType) {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e81ad843/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 bbdd68a..0df408f 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
@@ -1,4 +1,3 @@
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -93,10 +92,10 @@ public class SchemaLoadApp extends Application {
     private CheckBoxTreeItem<String> rootItem;
 
     /** */
-    private TextField regexTf;
+    private TextField keyClsTf;
 
     /** */
-    private TextField replaceTf;
+    private TextField valClsTf;
 
     /** */
     private TextField outFolderTf;
@@ -117,6 +116,12 @@ public class SchemaLoadApp extends Application {
     private CheckBox openFolderCh;
 
     /** */
+    private TextField regexTf;
+
+    /** */
+    private TextField replaceTf;
+
+    /** */
     private GridPaneEx genPnl;
 
     /** */
@@ -125,11 +130,11 @@ public class SchemaLoadApp extends Application {
     /** */
     private ProgressIndicator pi;
 
-    /** Map with types metadata. */
-    private Map<String, Map<String, GridCacheQueryTypeMetadata>> metas;
-
     /** Map with schema - table - POJO descriptors. */
-    private Map<String, Map<String, PojoDescriptor>> pojos = Collections.emptyMap();
+    private Map<String, Map<String, PojoDescriptor>> schemas = Collections.emptyMap();
+
+    /** Map all POJO descriptors. */
+    private Collection<PojoDescriptor> pojos = Collections.emptyList();
 
     /** Currently selected POJO. */
     private PojoDescriptor curPojo;
@@ -207,38 +212,14 @@ public class SchemaLoadApp extends Application {
                 long started = System.currentTimeMillis();
 
                 try (Connection conn = connect()) {
-                    metas = DbMetadataParser.parse(conn);
+                    schemas = DbMetadataParser.parse(conn);
                 }
 
-                pojos = new TreeMap<>();
-
-                for (Map.Entry<String, Map<String, GridCacheQueryTypeMetadata>> meta : metas.entrySet()) {
-                    String schema = meta.getKey();
+                pojos = new ArrayList<>();
 
-                    Map<String, GridCacheQueryTypeMetadata> tbls = meta.getValue();
-
-                    Map<String, PojoDescriptor> tblsPojo = new TreeMap<>();
-
-                    pojos.put(schema, tblsPojo);
-
-                    for (Map.Entry<String, GridCacheQueryTypeMetadata> tbl : tbls.entrySet()) {
-                        GridCacheQueryTypeMetadata type = tbl.getValue();
-
-                        Collection<GridCacheQueryTypeDescriptor> keys = type.getKeyDescriptors();
-
-                        Collection<GridCacheQueryTypeDescriptor> vals = type.getValueDescriptors();
-
-                        List<PojoField> tblFields = new ArrayList<>(keys.size() + vals.size());
-
-                        for (GridCacheQueryTypeDescriptor key : keys)
-                            tblFields.add(new PojoField(true, key));
-
-                        for (GridCacheQueryTypeDescriptor val : vals)
-                            tblFields.add(new PojoField(false, val));
-
-                        tblsPojo.put(type.getTableName(), new PojoDescriptor(type.getType(), tblFields));
-                    }
-                }
+                for (Map<String, PojoDescriptor> schema : schemas.values())
+                    for (PojoDescriptor pojo : schema.values())
+                        pojos.add(pojo);
 
                 perceptualDelay(started);
 
@@ -262,7 +243,7 @@ public class SchemaLoadApp extends Application {
 
                 rootItem.getChildren().clear();
 
-                for (Map.Entry<String, Map<String, PojoDescriptor>> schema : pojos.entrySet()) {
+                for (Map.Entry<String, Map<String, PojoDescriptor>> schema : schemas.entrySet()) {
                     CheckBoxTreeItem<String> schemaItem = addCheckBoxTreeItem(rootItem, schema.getKey());
 
                     for (String tbl : schema.getValue().keySet())
@@ -348,12 +329,9 @@ public class SchemaLoadApp extends Application {
                             String scheme = schemeItem.getValue();
                             String tbl = tblItem.getValue();
 
-                            GridCacheQueryTypeMetadata meta = metas.get(scheme).get(tbl);
-
-                            PojoDescriptor pojo = pojos.get(scheme).get(tbl);
+                            PojoDescriptor pojo = schemas.get(scheme).get(tbl);
 
-                            // Create a copy of metadata for modifications before processing.
-                            meta = new GridCacheQueryTypeMetadata(meta);
+                            GridCacheQueryTypeMetadata meta = pojo.metadata();
 
                             Collection<GridCacheQueryTypeDescriptor> keys = new ArrayList<>();
 
@@ -386,7 +364,7 @@ public class SchemaLoadApp extends Application {
                             if (!singleXml)
                                 XmlTransformer.transform(pkg, meta, new File(destFolder, meta.getType() + ".xml"));
 
-                            PojoCodeGenerator.generate(pojo, outFolder, pkg, constructor);
+                            PojoCodeGenerator.generate(meta, outFolder, pkg, constructor);
                         }
                     }
                 }
@@ -478,12 +456,9 @@ public class SchemaLoadApp extends Application {
      * @return {@code true} if some changes were made to fields metadata.
      */
     private boolean changed() {
-        for (Map.Entry<String, Map<String, PojoDescriptor>> schema : pojos.entrySet()) {
-            for (Map.Entry<String, PojoDescriptor> pojo : schema.getValue().entrySet()) {
-                if (pojo.getValue().changed())
-                    return true;
-            }
-        }
+        for (PojoDescriptor pojo : pojos)
+            if (pojo.changed())
+                return true;
 
         return false;
     }
@@ -602,7 +577,7 @@ public class SchemaLoadApp extends Application {
      * Create connection pane with controls.
      */
     private Pane createConnectionPane() {
-        connPnl = paneEx(true);
+        connPnl = paneEx(10, 10, 0, 10);
 
         connPnl.addColumn();
         connPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
@@ -643,14 +618,14 @@ public class SchemaLoadApp extends Application {
      * Create generate pane with controls.
      */
     private void createGeneratePane() {
-        genPnl = paneEx(true);
+        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(9);
+        genPnl.addRows(8);
 
         TableColumn<PojoField, Boolean> keyCol = tableColumn("Key", "key",
             "If checked then this field will be part of key object", 70, 70);
@@ -777,53 +752,157 @@ public class SchemaLoadApp extends Application {
         tree.setMinHeight(50);
         tree.setShowRoot(false);
         tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
-        tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<String>>() {
-            /** {@inheritDoc} */
-            @Override public void changed(ObservableValue<? extends TreeItem<String>> val, TreeItem<String> oldItem,
-                TreeItem<String> newItem) {
-                if (newItem != null && newItem.getParent() != null && newItem.isLeaf()) {
-                    curPojo = pojos.get(newItem.getParent().getValue()).get(newItem.getValue());
 
-                    tbl.setItems(curPojo.fields());
-                    tbl.getSelectionModel().select(0);
-                }
-                else {
-                    curPojo = null;
-                    tbl.setItems(NO_DATA);
+        genPnl.add(splitPane(tree, borderPane(null, tbl, null, null, vBox(10, upBtn, downBtn)), 0.6), 3);
 
-                    upBtn.setDisable(true);
-                    downBtn.setDisable(true);
+        GridPaneEx keyValPnl = paneEx(0, 0, 0, 0);
+        keyValPnl.addColumn();
+        keyValPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        keyValPnl.addColumn();
+        keyValPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
+        keyValPnl.addColumn();
+
+        keyClsTf = keyValPnl.addLabeled("Key class:", textField("Key class name"));
+        keyClsTf.setDisable(true);
+
+        valClsTf = keyValPnl.addLabeled("Value class:", textField("Value class name"));
+        valClsTf.setDisable(true);
+
+        final Button applyBtn = 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);
             }
-        });
+        }));
+        applyBtn.setDisable(true);
 
-        genPnl.add(splitPane(tree, borderPane(null, tbl, null, null, vBox(10, upBtn, downBtn)), 0.6), 3);
+        genPnl.add(keyValPnl, 3);
+
+        pkgTf = genPnl.addLabeled("Package:", textField("Package that will be used for POJOs generation"), 2);
+
+        outFolderTf = genPnl.addLabeled("Output Folder:", textField("Output folder for POJOs and XML files"));
+
+        genPnl.add(button("...", "Select output folder", new EventHandler<ActionEvent>() {
+            /** {@inheritDoc} */
+            @Override public void handle(ActionEvent evt) {
+                DirectoryChooser dc = new DirectoryChooser();
+
+                File folder = dc.showDialog(owner);
 
-        genPnl.add(new Label("Replace Ignite name for selected table:"), 3);
+                if (folder != null)
+                    outFolderTf.setText(folder.getAbsolutePath());
+            }
+        }));
 
-        GridPaneEx regexPnl = paneEx(false);
+        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);
+
+        openFolderCh = genPnl.add(checkBox("Reveal output folder",
+            "Open output folder in system file manager after generation complete", true), 3);
+
+        GridPaneEx regexPnl = paneEx(0, 0, 0, 0);
         regexPnl.addColumn();
         regexPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
         regexPnl.addColumn();
         regexPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
 
+        regexPnl.add(new Label("Replace Ignite name for selected or all tables:"), 4);
         regexTf = regexPnl.addLabeled("  Regexp:", textField("Regular expression. For example: (\\w+)"));
         replaceTf = regexPnl.addLabeled("  Replace with:", textField("Replace text. For example: $1_Suffix"));
 
-        genPnl.add(regexPnl, 3);
+        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!");
+
+                        return;
+                    }
+
+                    if (checkInput(regexTf, false, "Regular expression should not be empty!"))
+                        return;
+
+                    String regex = regexTf.getText();
+
+                    String replace = replaceTf.getText();
+
+                    try {
+                        for (PojoField field : curPojo.fields())
+                            field.javaName(field.javaName().replaceAll(regex, replace));
+                    }
+                    catch (Exception e) {
+                        MessageBox.errorDialog(owner, "Failed to rename Ignite names!", e);
+                    }
+                }
+            });
+        renBtn.setDisable(true);
 
-        genPnl.add(buttonsPane(Pos.BOTTOM_RIGHT, false,
-            button("Rename", "Replace Ignite names by provided regular expression for current table",
+        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();
+                else
+                    MessageBox.warningDialog(owner, "Please select table to revert changes to Ignite names!");
+            }
+        });
+        revertBtn.setDisable(true);
+
+        regexPnl.add(buttonsPane(Pos.BOTTOM_RIGHT, false,
+            renBtn,
+            button("Rename All", "Replace Ignite names by provided regular expression for all tables",
                 new EventHandler<ActionEvent>() {
                     /** {@inheritDoc} */
                     @Override public void handle(ActionEvent evt) {
-                        if (curPojo == null) {
-                            MessageBox.warningDialog(owner, "Please select table to rename Ignite names!");
-
+                        if (checkInput(regexTf, false, "Regular expression should not be empty!"))
                             return;
-                        }
 
-                        if (checkInput(regexTf, false, "Regular expression should not be empty!"))
+                        if (!MessageBox.confirmDialog(owner, "Are you sure you want to rename Ignite names in all tables?"))
                             return;
 
                         String regex = regexTf.getText();
@@ -831,88 +910,68 @@ public class SchemaLoadApp extends Application {
                         String replace = replaceTf.getText();
 
                         try {
-                            for (PojoField field : curPojo.fields())
-                                field.javaName(field.javaName().replaceAll(regex, replace));
+                            for (PojoDescriptor pojo : pojos)
+                                for (PojoField field : pojo.fields())
+                                    field.javaName(field.javaName().replaceAll(regex, replace));
                         }
                         catch (Exception e) {
                             MessageBox.errorDialog(owner, "Failed to rename Ignite names!", e);
                         }
                     }
                 }),
-            button("Rename All", "Replace Ignite names by provided regular expression for all tables",
-                new EventHandler<ActionEvent>() {
-                /** {@inheritDoc} */
-                @Override public void handle(ActionEvent evt) {
-                    if (checkInput(regexTf, false, "Regular expression should not be empty!"))
-                        return;
-
-                    if (!MessageBox.confirmDialog(owner, "Are you sure you want to rename Ignite names in all tables?"))
-                        return;
-
-                    String regex = regexTf.getText();
-
-                    String replace = replaceTf.getText();
-
-                    try {
-                        for (Map<String, PojoDescriptor> descs : pojos.values())
-                            for (PojoDescriptor pojo : descs.values())
-                                for (PojoField field : pojo.fields())
-                                    field.javaName(field.javaName().replaceAll(regex, replace));
-                    }
-                    catch (Exception e) {
-                        MessageBox.errorDialog(owner, "Failed to rename Ignite names!", e);
-                    }
-                }
-            }),
-            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();
-                    else
-                        MessageBox.warningDialog(owner, "Please select table to revert changes to Ignite names!");
-                }
-            }),
+            revertBtn,
             button("Revert All", "Revert changes to Ignite names for all tables", new EventHandler<ActionEvent>() {
                 /** {@inheritDoc} */
                 @Override public void handle(ActionEvent evt) {
                     if (!MessageBox.confirmDialog(owner, "Are you sure you want to revert Ignite names for all tables?"))
                         return;
 
-                    for (Map<String, PojoDescriptor> descs : pojos.values())
-                        for (PojoDescriptor pojo : descs.values())
-                            pojo.revertJavaNames();
+                    for (PojoDescriptor pojo : pojos)
+                        pojo.revertJavaNames();
                 }
             })
-            ), 3);
+        ), 4);
 
-        pkgTf = genPnl.addLabeled("Package:", textField("Package that will be used for POJOs generation"), 2);
+        tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<String>>() {
+            /** {@inheritDoc} */
+            @Override public void changed(ObservableValue<? extends TreeItem<String>> val, TreeItem<String> oldItem,
+                TreeItem<String> newItem) {
+                if (newItem != null && newItem.getParent() != null && newItem.isLeaf()) {
+                    curPojo = schemas.get(newItem.getParent().getValue()).get(newItem.getValue());
 
-        outFolderTf = genPnl.addLabeled("Output Folder:", textField("Output folder for POJOs and XML files"));
+                    tbl.setItems(curPojo.fields());
+                    tbl.getSelectionModel().select(0);
 
-        genPnl.add(button("...", "Select output folder", new EventHandler<ActionEvent>() {
-            /** {@inheritDoc} */
-            @Override public void handle(ActionEvent evt) {
-                DirectoryChooser dc = new DirectoryChooser();
+                    keyClsTf.setText(curPojo.keyClassName());
+                    keyClsTf.setDisable(false);
 
-                File folder = dc.showDialog(owner);
+                    valClsTf.setText(curPojo.valueClassName());
+                    valClsTf.setDisable(false);
 
-                if (folder != null)
-                    outFolderTf.setText(folder.getAbsolutePath());
-            }
-        }));
+                    applyBtn.setDisable(false);
+                    renBtn.setDisable(false);
+                    revertBtn.setDisable(false);
+                }
+                else {
+                    curPojo = null;
+                    tbl.setItems(NO_DATA);
 
-        pojoIncludeKeysCh = genPnl.add(checkBox("Include key fields into value POJOs",
-            "If selected then include key fields into value object", true), 3);
+                    keyClsTf.setText("");
+                    valClsTf.setText("");
 
-        pojoConstructorCh = genPnl.add(checkBox("Generate constructors for POJOs",
-            "If selected then generate empty and full constructors for POJOs", false), 3);
+                    keyClsTf.setDisable(true);
+                    valClsTf.setDisable(true);
 
-        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);
+                    applyBtn.setDisable(true);
+                    renBtn.setDisable(true);
+                    revertBtn.setDisable(true);
+                    upBtn.setDisable(true);
+                    downBtn.setDisable(true);
+                }
+            }
+        });
 
-        openFolderCh = genPnl.add(checkBox("Reveal output folder",
-            "Open output folder in system file manager after generation complete", true), 3);
+        genPnl.add(regexPnl, 3);
 
         genLayerPnl = stackPane(genPnl);
     }
@@ -942,8 +1001,8 @@ public class SchemaLoadApp extends Application {
         primaryStage.setWidth(600);
         primaryStage.setMinWidth(600);
 
-        primaryStage.setHeight(600);
-        primaryStage.setMinHeight(600);
+        primaryStage.setHeight(650);
+        primaryStage.setMinHeight(650);
 
         prev();
 
@@ -953,8 +1012,8 @@ public class SchemaLoadApp extends Application {
         if (userPrefs.get("window.x", null) != null) {
             double x = userPrefs.getDouble("window.x", 100);
             double y = userPrefs.getDouble("window.y", 100);
-            double w = userPrefs.getDouble("window.width", 600);
-            double h = userPrefs.getDouble("window.height", 600);
+            double w = userPrefs.getDouble("window.width", 650);
+            double h = userPrefs.getDouble("window.height", 650);
 
             // Ensure that window fit any available screen.
             if (!Screen.getScreensForRectangle(x, y, w, h).isEmpty()) {