http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreMultitreadedSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreMultitreadedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreMultitreadedSelfTest.java new file mode 100644 index 0000000..f2688d3 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreMultitreadedSelfTest.java @@ -0,0 +1,106 @@ +/* + * 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.cache.store.jdbc; + +import org.apache.ignite.*; +import org.apache.ignite.cache.*; +import org.apache.ignite.configuration.*; +import org.apache.ignite.spi.discovery.tcp.*; +import org.gridgain.grid.cache.query.*; +import org.gridgain.grid.util.typedef.*; +import org.h2.jdbcx.*; +import org.springframework.beans.*; +import org.springframework.beans.factory.xml.*; +import org.springframework.context.support.*; +import org.springframework.core.io.*; + +import java.io.*; +import java.net.*; +import java.util.*; + +import static org.gridgain.grid.cache.GridCacheAtomicityMode.*; +import static org.gridgain.grid.cache.GridCacheMode.*; + +/** + * + */ +public class PojoCacheStoreMultitreadedSelfTest extends AbstractCacheStoreMultithreadedSelfTest<JdbcPojoCacheStore> { + /** {@inheritDoc} */ + @Override protected JdbcPojoCacheStore store() throws Exception { + JdbcPojoCacheStore store = new JdbcPojoCacheStore(); + + store.setDataSource(JdbcConnectionPool.create(DFLT_CONN_URL, "sa", "")); + + UrlResource metaUrl; + + try { + metaUrl = new UrlResource(new File("modules/core/src/test/config/store/auto/all.xml").toURI().toURL()); + } + catch (MalformedURLException e) { + throw new IgniteCheckedException("Failed to resolve metadata path [err=" + e.getMessage() + ']', e); + } + + try { + GenericApplicationContext springCtx = new GenericApplicationContext(); + + new XmlBeanDefinitionReader(springCtx).loadBeanDefinitions(metaUrl); + + springCtx.refresh(); + + Collection<GridCacheQueryTypeMetadata> typeMetadata = + springCtx.getBeansOfType(GridCacheQueryTypeMetadata.class).values(); + + store.setTypeMetadata(typeMetadata); + } + catch (BeansException e) { + if (X.hasCause(e, ClassNotFoundException.class)) + throw new IgniteCheckedException("Failed to instantiate Spring XML application context " + + "(make sure all classes used in Spring configuration are present at CLASSPATH) " + + "[springUrl=" + metaUrl + ']', e); + else + throw new IgniteCheckedException("Failed to instantiate Spring XML application context [springUrl=" + + metaUrl + ", err=" + e.getMessage() + ']', e); + } + + return store; + } + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration c = super.getConfiguration(gridName); + + TcpDiscoverySpi disco = new TcpDiscoverySpi(); + + disco.setIpFinder(IP_FINDER); + + c.setDiscoverySpi(disco); + + CacheConfiguration cc = defaultCacheConfiguration(); + + cc.setCacheMode(PARTITIONED); + cc.setAtomicityMode(ATOMIC); + cc.setSwapEnabled(false); + cc.setWriteBehindEnabled(false); + + // TODO: IGNITE-32 FIXME cc.setStore(store); + + c.setCacheConfiguration(cc); + + return c; + } +}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreSelfTest.java new file mode 100644 index 0000000..fa77385 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/PojoCacheStoreSelfTest.java @@ -0,0 +1,551 @@ +/* + * 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.cache.store.jdbc; + +import org.apache.ignite.*; +import org.apache.ignite.cache.store.jdbc.model.*; +import org.apache.ignite.lang.*; +import org.apache.ignite.transactions.*; +import org.gridgain.grid.cache.query.*; +import org.gridgain.grid.util.typedef.*; +import org.gridgain.grid.util.typedef.internal.*; +import org.gridgain.testframework.junits.cache.GridAbstractCacheStoreSelfTest.*; +import org.gridgain.testframework.junits.common.*; +import org.h2.jdbcx.*; +import org.jetbrains.annotations.*; +import org.springframework.beans.*; +import org.springframework.beans.factory.xml.*; +import org.springframework.context.support.*; +import org.springframework.core.io.*; + +import java.io.*; +import java.net.*; +import java.sql.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +/** + * Class for {@code PojoCacheStore} tests. + */ +public class PojoCacheStoreSelfTest extends GridCommonAbstractTest { + /** Default connection URL (value is <tt>jdbc:h2:mem:jdbcCacheStore;DB_CLOSE_DELAY=-1</tt>). */ + protected static final String DFLT_CONN_URL = "jdbc:h2:mem:autoCacheStore;DB_CLOSE_DELAY=-1"; + + /** Organization count. */ + protected static final int ORGANIZATION_CNT = 1000; + + /** Person count. */ + protected static final int PERSON_CNT = 100000; + + /** */ + protected final JdbcPojoCacheStore store; + + /** + * @throws Exception If failed. + */ + @SuppressWarnings({"AbstractMethodCallInConstructor", "OverriddenMethodCallDuringObjectConstruction"}) + public PojoCacheStoreSelfTest() throws Exception { + super(false); + + store = store(); + + inject(store); + } + + /** + * @return Store. + */ + protected JdbcPojoCacheStore store() throws IgniteCheckedException { + JdbcPojoCacheStore store = new JdbcPojoCacheStore(); + + store.setDataSource(JdbcConnectionPool.create(DFLT_CONN_URL, "sa", "")); + + UrlResource metaUrl; + + try { + metaUrl = new UrlResource(new File("modules/core/src/test/config/store/auto/all.xml").toURI().toURL()); + } + catch (MalformedURLException e) { + throw new IgniteCheckedException("Failed to resolve metadata path [err=" + e.getMessage() + ']', e); + } + + try { + GenericApplicationContext springCtx = new GenericApplicationContext(); + + new XmlBeanDefinitionReader(springCtx).loadBeanDefinitions(metaUrl); + + springCtx.refresh(); + + Collection<GridCacheQueryTypeMetadata> typeMetadata = + springCtx.getBeansOfType(GridCacheQueryTypeMetadata.class).values(); + + store.setTypeMetadata(typeMetadata); + } + catch (BeansException e) { + if (X.hasCause(e, ClassNotFoundException.class)) + throw new IgniteCheckedException("Failed to instantiate Spring XML application context " + + "(make sure all classes used in Spring configuration are present at CLASSPATH) " + + "[springUrl=" + metaUrl + ']', e); + else + throw new IgniteCheckedException("Failed to instantiate Spring XML application context [springUrl=" + + metaUrl + ", err=" + e.getMessage() + ']', e); + } + + return store; + } + + /** + * @param store Store. + * @throws Exception If failed. + */ + protected void inject(JdbcCacheStore store) throws Exception { + getTestResources().inject(store); + } + + /** + * @throws Exception If failed. + */ + public void testLoadCache() throws Exception { + Connection conn = DriverManager.getConnection(DFLT_CONN_URL, "sa", ""); + + Statement stmt = conn.createStatement(); + + PreparedStatement orgStmt = conn.prepareStatement("INSERT INTO Organization(id, name, city) VALUES (?, ?, ?)"); + + for (int i = 0; i < ORGANIZATION_CNT; i++) { + orgStmt.setInt(1, i); + orgStmt.setString(2, "name" + i); + orgStmt.setString(3, "city" + i % 10); + + orgStmt.addBatch(); + } + + orgStmt.executeBatch(); + + conn.commit(); + + PreparedStatement prnStmt = conn.prepareStatement("INSERT INTO Person(id, org_id, name) VALUES (?, ?, ?)"); + + for (int i = 0; i < PERSON_CNT; i++) { + prnStmt.setInt(1, i); + prnStmt.setInt(2, i % 100); + prnStmt.setString(3, "name" + i); + + prnStmt.addBatch(); + } + + prnStmt.executeBatch(); + + conn.commit(); + + U.closeQuiet(stmt); + + U.closeQuiet(conn); + + final Collection<OrganizationKey> orgKeys = new ArrayList<>(ORGANIZATION_CNT); + final Collection<PersonKey> prnKeys = new ArrayList<>(PERSON_CNT); + + IgniteBiInClosure<Object, Object> c = new CI2<Object, Object>() { + @Override public void apply(Object k, Object v) { + if (k instanceof OrganizationKey && v instanceof Organization) + orgKeys.add((OrganizationKey)k); + else if (k instanceof PersonKey && v instanceof Person) + prnKeys.add((PersonKey)k); + } + }; + + store.loadCache(c); + + assertEquals(ORGANIZATION_CNT, orgKeys.size()); + assertEquals(PERSON_CNT, prnKeys.size()); + + store.removeAll(null, orgKeys); + store.removeAll(null, prnKeys); + + orgKeys.clear(); + prnKeys.clear(); + + store.loadCache(c); + + assertTrue(orgKeys.isEmpty()); + assertTrue(prnKeys.isEmpty()); + } + + /** + * @throws Exception If failed. + */ + public void testStore() throws Exception { + // Create dummy transaction + IgniteTx tx = new DummyTx(); + + OrganizationKey k1 = new OrganizationKey(1); + Organization v1 = new Organization(1, "Name1", "City1"); + + OrganizationKey k2 = new OrganizationKey(2); + Organization v2 = new Organization(2, "Name2", "City2"); + + store.put(tx, k1, v1); + store.put(tx, k2, v2); + + store.txEnd(tx, true); + + assertEquals(v1, store.load(null, k1)); + assertEquals(v2, store.load(null, k2)); + + OrganizationKey k3 = new OrganizationKey(3); + + assertNull(store.load(tx, k3)); + + store.remove(tx, k1); + + store.txEnd(tx, true); + + assertNull(store.load(tx, k1)); + assertEquals(v2, store.load(tx, k2)); + assertNull(store.load(null, k3)); + } + + /** + * @throws IgniteCheckedException if failed. + */ + public void testRollback() throws IgniteCheckedException { + IgniteTx tx = new DummyTx(); + + OrganizationKey k1 = new OrganizationKey(1); + Organization v1 = new Organization(1, "Name1", "City1"); + + // Put. + store.put(tx, k1, v1); + + store.txEnd(tx, false); // Rollback. + + tx = new DummyTx(); + + assertNull(store.load(tx, k1)); + + OrganizationKey k2 = new OrganizationKey(2); + Organization v2 = new Organization(2, "Name2", "City2"); + + // Put all. + assertNull(store.load(tx, k2)); + + store.putAll(tx, Collections.singletonMap(k2, v2)); + + store.txEnd(tx, false); // Rollback. + + tx = new DummyTx(); + + assertNull(store.load(tx, k2)); + + OrganizationKey k3 = new OrganizationKey(3); + Organization v3 = new Organization(3, "Name3", "City3"); + + store.putAll(tx, Collections.singletonMap(k3, v3)); + + store.txEnd(tx, true); // Commit. + + tx = new DummyTx(); + + assertEquals(v3, store.load(tx, k3)); + + OrganizationKey k4 = new OrganizationKey(4); + Organization v4 = new Organization(4, "Name4", "City4"); + + store.put(tx, k4, v4); + + store.txEnd(tx, false); // Rollback. + + tx = new DummyTx(); + + assertNull(store.load(tx, k4)); + + assertEquals(v3, store.load(tx, k3)); + + // Remove. + store.remove(tx, k3); + + store.txEnd(tx, false); // Rollback. + + tx = new DummyTx(); + + assertEquals(v3, store.load(tx, k3)); + + // Remove all. + store.removeAll(tx, Arrays.asList(k3)); + + store.txEnd(tx, false); // Rollback. + + tx = new DummyTx(); + + assertEquals(v3, store.load(tx, k3)); + } + + /** + * @throws IgniteCheckedException if failed. + */ + public void testAllOpsWithTXNoCommit() throws IgniteCheckedException { + doTestAllOps(new DummyTx(), false); + } + + /** + * @throws IgniteCheckedException if failed. + */ + public void testAllOpsWithTXCommit() throws IgniteCheckedException { + doTestAllOps(new DummyTx(), true); + } + + /** + * @throws IgniteCheckedException if failed. + */ + public void testAllOpsWithoutTX() throws IgniteCheckedException { + doTestAllOps(null, false); + } + + /** + * @param tx Transaction. + * @param commit Commit. + * @throws IgniteCheckedException If failed. + */ + private void doTestAllOps(@Nullable IgniteTx tx, boolean commit) throws IgniteCheckedException { + try { + final OrganizationKey k1 = new OrganizationKey(1); + final Organization v1 = new Organization(1, "Name1", "City1"); + + store.put(tx, k1, v1); + + if (tx != null && commit) { + store.txEnd(tx, true); + + tx = new DummyTx(); + } + + if (tx == null || commit) + assertEquals(v1, store.load(tx, k1)); + + Map<OrganizationKey, Organization> m = new HashMap<>(); + + final OrganizationKey k2 = new OrganizationKey(2); + final Organization v2 = new Organization(2, "Name2", "City2"); + + final OrganizationKey k3 = new OrganizationKey(3); + final Organization v3 = new Organization(3, "Name3", "City3"); + + m.put(k2, v2); + m.put(k3, v3); + + store.putAll(tx, m); + + if (tx != null && commit) { + store.txEnd(tx, true); + + tx = new DummyTx(); + } + + final AtomicInteger cntr = new AtomicInteger(); + + final OrganizationKey no_such_key = new OrganizationKey(4); + + if (tx == null || commit) { + store.loadAll(tx, Arrays.asList(k1, k2, k3, no_such_key), new CI2<Object, Object>() { + @Override public void apply(Object o, Object o1) { + if (k1.equals(o)) + assertEquals(v1, o1); + + if (k2.equals(o)) + assertEquals(v2, o1); + + if (k3.equals(o)) + assertEquals(v3, o1); + + if (no_such_key.equals(o)) + fail(); + + cntr.incrementAndGet(); + } + }); + + assertEquals(3, cntr.get()); + } + + store.removeAll(tx, Arrays.asList(k2, k3)); + + if (tx != null && commit) { + store.txEnd(tx, true); + + tx = new DummyTx(); + } + + if (tx == null || commit) { + assertNull(store.load(tx, k2)); + assertNull(store.load(tx, k3)); + assertEquals(v1, store.load(tx, k1)); + } + + store.remove(tx, k1); + + if (tx != null && commit) { + store.txEnd(tx, true); + + tx = new DummyTx(); + } + + if (tx == null || commit) + assertNull(store.load(tx, k1)); + } + finally { + if (tx != null) + store.txEnd(tx, false); + } + } + + /** + * @throws Exception If failed. + */ + public void testSimpleMultithreading() throws Exception { + final Random rnd = new Random(); + + final Queue<OrganizationKey> queue = new LinkedBlockingQueue<>(); + + multithreaded(new Callable<Object>() { + @Nullable @Override public Object call() throws Exception { + for (int i = 0; i < 1000; i++) { + IgniteTx tx = rnd.nextBoolean() ? new DummyTx() : null; + + int op = rnd.nextInt(10); + + boolean queueEmpty = false; + + if (op < 4) { // Load. + OrganizationKey key = queue.poll(); + + if (key == null) + queueEmpty = true; + else { + if (rnd.nextBoolean()) + assertNotNull(store.load(tx, key)); + else { + final AtomicInteger cntr = new AtomicInteger(); + + store.loadAll(tx, Collections.singleton(key), new CI2<Object, Object>() { + @Override public void apply(Object o, Object o1) { + cntr.incrementAndGet(); + + assertNotNull(o); + assertNotNull(o1); + + OrganizationKey key = (OrganizationKey)o; + Organization val = (Organization)o1; + + assertTrue(key.getId().equals(val.getId())); + } + }); + + assertEquals(1, cntr.get()); + } + + if (tx != null) + store.txEnd(tx, true); + + queue.add(key); + } + } + else if (op < 6) { // Remove. + OrganizationKey key = queue.poll(); + + if (key == null) + queueEmpty = true; + else { + if (rnd.nextBoolean()) + store.remove(tx, key); + else + store.removeAll(tx, Collections.singleton(key)); + + if (tx != null) + store.txEnd(tx, true); + } + } + else { // Update. + OrganizationKey key = queue.poll(); + + if (key == null) + queueEmpty = true; + else { + Organization val = + new Organization(key.getId(), "Name" + key.getId(), "City" + key.getId()); + + if (rnd.nextBoolean()) + store.put(tx, key, val); + else + store.putAll(tx, Collections.singletonMap(key, val)); + + if (tx != null) + store.txEnd(tx, true); + + queue.add(key); + } + } + + if (queueEmpty) { // Add. + OrganizationKey key = new OrganizationKey(rnd.nextInt()); + Organization val = new Organization(key.getId(), "Name" + key.getId(), "City" + key.getId()); + + if (rnd.nextBoolean()) + store.put(tx, key, val); + else + store.putAll(tx, Collections.singletonMap(key, val)); + + if (tx != null) + store.txEnd(tx, true); + + queue.add(key); + } + } + + return null; + } + }, 37); + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + super.beforeTest(); + + Class.forName("org.h2.Driver"); + Connection conn = DriverManager.getConnection(DFLT_CONN_URL, "sa", ""); + + Statement stmt = conn.createStatement(); + + stmt.executeUpdate("DROP TABLE IF EXISTS Organization"); + stmt.executeUpdate("DROP TABLE IF EXISTS Person"); + + stmt.executeUpdate("CREATE TABLE Organization (id integer PRIMARY KEY, name varchar(50), city varchar(50))"); + stmt.executeUpdate("CREATE TABLE Person (id integer PRIMARY KEY, org_id integer, name varchar(50))"); + + stmt.executeUpdate("CREATE INDEX Org_Name_IDX On Organization (name)"); + stmt.executeUpdate("CREATE INDEX Org_Name_City_IDX On Organization (name, city)"); + stmt.executeUpdate("CREATE INDEX Person_Name_IDX1 On Person (name)"); + stmt.executeUpdate("CREATE INDEX Person_Name_IDX2 On Person (name desc)"); + + conn.commit(); + + U.closeQuiet(stmt); + + U.closeQuiet(conn); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Organization.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Organization.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Organization.java new file mode 100644 index 0000000..92a58d3 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Organization.java @@ -0,0 +1,153 @@ +/* + * 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.cache.store.jdbc.model; + +import java.io.*; + +/** + * Organization definition. + * + * Code generated by Apache Ignite Schema Load utility. + */ +public class Organization implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Value for id. */ + private Integer id; + + /** Value for name. */ + private String name; + + /** Value for city. */ + private String city; + + /** + * Empty constructor. + */ + public Organization() { + // No-op. + } + + /** + * Full constructor. + */ + public Organization( + Integer id, + String name, + String city + ) { + this.id = id; + this.name = name; + this.city = city; + } + + /** + * Gets id. + * + * @return Value for id. + */ + public Integer getId() { + return id; + } + + /** + * Sets id. + * + * @param id New value for id. + */ + public void setId(Integer id) { + this.id = id; + } + + /** + * Gets name. + * + * @return Value for name. + */ + public String getName() { + return name; + } + + /** + * Sets name. + * + * @param name New value for name. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Gets city. + * + * @return Value for city. + */ + public String getCity() { + return city; + } + + /** + * Sets city. + * + * @param city New value for city. + */ + public void setCity(String city) { + this.city = city; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (!(o instanceof Organization)) + return false; + + Organization that = (Organization)o; + + if (id != null ? !id.equals(that.id) : that.id != null) + return false; + + if (name != null ? !name.equals(that.name) : that.name != null) + return false; + + if (city != null ? !city.equals(that.city) : that.city != null) + return false; + + return true; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = id != null ? id.hashCode() : 0; + + res = 31 * res + (name != null ? name.hashCode() : 0); + res = 31 * res + (city != null ? city.hashCode() : 0); + + return res; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "Organization [id=" + id + + ", name=" + name + + ", city=" + city + + "]"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/OrganizationKey.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/OrganizationKey.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/OrganizationKey.java new file mode 100644 index 0000000..7b48aed --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/OrganizationKey.java @@ -0,0 +1,96 @@ +/* + * 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.cache.store.jdbc.model; + +import java.io.*; + +/** + * OrganizationKey definition. + * + * Code generated by Apache Ignite Schema Load utility. + */ +public class OrganizationKey implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Value for id. */ + private Integer id; + + /** + * Empty constructor. + */ + public OrganizationKey() { + // No-op. + } + + /** + * Full constructor. + */ + public OrganizationKey( + Integer id + ) { + this.id = id; + } + + /** + * Gets id. + * + * @return Value for id. + */ + public Integer getId() { + return id; + } + + /** + * Sets id. + * + * @param id New value for id. + */ + public void setId(Integer id) { + this.id = id; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (!(o instanceof OrganizationKey)) + return false; + + OrganizationKey that = (OrganizationKey)o; + + if (id != null ? !id.equals(that.id) : that.id != null) + return false; + + return true; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = id != null ? id.hashCode() : 0; + + return res; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "OrganizationKey [id=" + id + + "]"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Person.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Person.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Person.java new file mode 100644 index 0000000..6d8c1d2 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/Person.java @@ -0,0 +1,153 @@ +/* + * 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.cache.store.jdbc.model; + +import java.io.*; + +/** + * Person definition. + * + * Code generated by Apache Ignite Schema Load utility. + */ +public class Person implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Value for id. */ + private Integer id; + + /** Value for orgId. */ + private Integer orgId; + + /** Value for name. */ + private String name; + + /** + * Empty constructor. + */ + public Person() { + // No-op. + } + + /** + * Full constructor. + */ + public Person( + Integer id, + Integer orgId, + String name + ) { + this.id = id; + this.orgId = orgId; + this.name = name; + } + + /** + * Gets id. + * + * @return Value for id. + */ + public Integer getId() { + return id; + } + + /** + * Sets id. + * + * @param id New value for id. + */ + public void setId(Integer id) { + this.id = id; + } + + /** + * Gets orgId. + * + * @return Value for orgId. + */ + public Integer getOrgId() { + return orgId; + } + + /** + * Sets orgId. + * + * @param orgId New value for orgId. + */ + public void setOrgId(Integer orgId) { + this.orgId = orgId; + } + + /** + * Gets name. + * + * @return Value for name. + */ + public String getName() { + return name; + } + + /** + * Sets name. + * + * @param name New value for name. + */ + public void setName(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (!(o instanceof Person)) + return false; + + Person that = (Person)o; + + if (id != null ? !id.equals(that.id) : that.id != null) + return false; + + if (orgId != null ? !orgId.equals(that.orgId) : that.orgId != null) + return false; + + if (name != null ? !name.equals(that.name) : that.name != null) + return false; + + return true; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = id != null ? id.hashCode() : 0; + + res = 31 * res + (orgId != null ? orgId.hashCode() : 0); + res = 31 * res + (name != null ? name.hashCode() : 0); + + return res; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "Person [id=" + id + + ", orgId=" + orgId + + ", name=" + name + + "]"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/PersonKey.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/PersonKey.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/PersonKey.java new file mode 100644 index 0000000..068041b --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/PersonKey.java @@ -0,0 +1,96 @@ +/* + * 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.cache.store.jdbc.model; + +import java.io.*; + +/** + * PersonKey definition. + * + * Code generated by Apache Ignite Schema Load utility. + */ +public class PersonKey implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Value for id. */ + private Integer id; + + /** + * Empty constructor. + */ + public PersonKey() { + // No-op. + } + + /** + * Full constructor. + */ + public PersonKey( + Integer id + ) { + this.id = id; + } + + /** + * Gets id. + * + * @return Value for id. + */ + public Integer getId() { + return id; + } + + /** + * Sets id. + * + * @param id New value for id. + */ + public void setId(Integer id) { + this.id = id; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (!(o instanceof PersonKey)) + return false; + + PersonKey that = (PersonKey)o; + + if (id != null ? !id.equals(that.id) : that.id != null) + return false; + + return true; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = id != null ? id.hashCode() : 0; + + return res; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "PersonKey [id=" + id + + "]"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/package.html ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/package.html b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/package.html new file mode 100644 index 0000000..d10c624 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/model/package.html @@ -0,0 +1,24 @@ +<!-- + 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. + --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<body> + <!-- Package description. --> + Contains store tests model classes. +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/pom.xml ---------------------------------------------------------------------- diff --git a/modules/schema-load/pom.xml b/modules/schema-load/pom.xml new file mode 100644 index 0000000..88eee8e --- /dev/null +++ b/modules/schema-load/pom.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + 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. + --> + +<!-- + POM file. +--> +<project + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite</artifactId> + <version>${ignite.version}</version> + <relativePath>../..</relativePath> + </parent> + + <artifactId>ignite-schema-load</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-core</artifactId> + <version>${ignite.version}</version> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <directory>src/main/java</directory> + <excludes> + <exclude>**/*.java</exclude> + </excludes> + </resource> + </resources> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>org.apache.ignite.schema.ui.SchemaLoadApp</mainClass> + </manifest> + </archive> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>jfxrt.jar</id> + <activation> + <property> + <name>java.vendor</name> + <value>Oracle Corporation</value> + </property> + </activation> + <dependencies> + <dependency> + <groupId>javafx</groupId> + <artifactId>jfxrt</artifactId> + <version>${java.version}</version> + <scope>system</scope> + <systemPath>${java.home}/lib/jfxrt.jar</systemPath> + </dependency> + </dependencies> + </profile> + </profiles> +</project> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/data_connection_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/data_connection_48x48.png b/modules/schema-load/src/main/java/media/data_connection_48x48.png new file mode 100644 index 0000000..475f219 Binary files /dev/null and b/modules/schema-load/src/main/java/media/data_connection_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/error_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/error_48x48.png b/modules/schema-load/src/main/java/media/error_48x48.png new file mode 100644 index 0000000..e341b8a Binary files /dev/null and b/modules/schema-load/src/main/java/media/error_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/ignite_128x128.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/ignite_128x128.png b/modules/schema-load/src/main/java/media/ignite_128x128.png new file mode 100644 index 0000000..d99a83c Binary files /dev/null and b/modules/schema-load/src/main/java/media/ignite_128x128.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/ignite_16x16.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/ignite_16x16.png b/modules/schema-load/src/main/java/media/ignite_16x16.png new file mode 100644 index 0000000..3e07d33 Binary files /dev/null and b/modules/schema-load/src/main/java/media/ignite_16x16.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/ignite_24x24.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/ignite_24x24.png b/modules/schema-load/src/main/java/media/ignite_24x24.png new file mode 100644 index 0000000..8da5c97 Binary files /dev/null and b/modules/schema-load/src/main/java/media/ignite_24x24.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/ignite_32x32.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/ignite_32x32.png b/modules/schema-load/src/main/java/media/ignite_32x32.png new file mode 100644 index 0000000..c6c6819 Binary files /dev/null and b/modules/schema-load/src/main/java/media/ignite_32x32.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/ignite_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/ignite_48x48.png b/modules/schema-load/src/main/java/media/ignite_48x48.png new file mode 100644 index 0000000..5b684cc Binary files /dev/null and b/modules/schema-load/src/main/java/media/ignite_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/ignite_64x64.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/ignite_64x64.png b/modules/schema-load/src/main/java/media/ignite_64x64.png new file mode 100644 index 0000000..c1d348b Binary files /dev/null and b/modules/schema-load/src/main/java/media/ignite_64x64.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/information_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/information_48x48.png b/modules/schema-load/src/main/java/media/information_48x48.png new file mode 100644 index 0000000..8712a1b Binary files /dev/null and b/modules/schema-load/src/main/java/media/information_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/navigate_down_24x24.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/navigate_down_24x24.png b/modules/schema-load/src/main/java/media/navigate_down_24x24.png new file mode 100644 index 0000000..a06dc3b Binary files /dev/null and b/modules/schema-load/src/main/java/media/navigate_down_24x24.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/navigate_up_24x24.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/navigate_up_24x24.png b/modules/schema-load/src/main/java/media/navigate_up_24x24.png new file mode 100644 index 0000000..e2fad4c Binary files /dev/null and b/modules/schema-load/src/main/java/media/navigate_up_24x24.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/question_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/question_48x48.png b/modules/schema-load/src/main/java/media/question_48x48.png new file mode 100644 index 0000000..84683f9 Binary files /dev/null and b/modules/schema-load/src/main/java/media/question_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/sign_warning_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/sign_warning_48x48.png b/modules/schema-load/src/main/java/media/sign_warning_48x48.png new file mode 100644 index 0000000..5e7cccd Binary files /dev/null and b/modules/schema-load/src/main/java/media/sign_warning_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/style.css ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/style.css b/modules/schema-load/src/main/java/media/style.css new file mode 100644 index 0000000..99f3d68 --- /dev/null +++ b/modules/schema-load/src/main/java/media/style.css @@ -0,0 +1,58 @@ +.root { + -fx-background-color: eeeeee; +} + +.button { + -fx-font-size: 14; + -fx-focus-color: gray; +} + +.label { + -fx-font-size: 14; +} + +.check-box { + -fx-font-size: 14; + -fx-focus-color: gray; +} + +.text-field { + -fx-font-size: 14; + -fx-background-color: -fx-text-box-border, -fx-control-inner-background, -fx-control-inner-background; + -fx-background-radius: 0, 0, 0, 0; +} + +.text-field:focused { + -fx-background-color: -fx-text-box-border, -fx-control-inner-background, -fx-control-inner-background; + -fx-background-radius: 0, 0, 0, 0; +} + +.tree-view { + -fx-focus-color: gray; +} + +.table-view { + -fx-focus-color: gray; +} + +.tooltip { + -fx-background-radius: 0 0 0 0; +} + +.page-corner { + -fx-shape: " "; +} + +.progress-indicator { + -fx-progress-color: gray +} + +.split-pane { + -fx-background-color: -fx-box-border, eeeeee; +} + +#banner { + -fx-font-size: 20px; + -fx-font-weight: bold; + -fx-background-color: white +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/media/text_tree_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/media/text_tree_48x48.png b/modules/schema-load/src/main/java/media/text_tree_48x48.png new file mode 100644 index 0000000..6ca9e65 Binary files /dev/null and b/modules/schema-load/src/main/java/media/text_tree_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/PojoGenerator.java ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/PojoGenerator.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/PojoGenerator.java new file mode 100644 index 0000000..fadb3a3 --- /dev/null +++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/PojoGenerator.java @@ -0,0 +1,316 @@ +/* + * 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.generator; + +import org.apache.ignite.schema.ui.*; +import org.gridgain.grid.cache.query.*; + +import java.io.*; +import java.util.*; + +import static org.apache.ignite.schema.ui.MessageBox.Result.*; + +/** + * POJO generator for key and value classes. + */ +public class PojoGenerator { + /** */ + private static final String TAB = " "; + /** */ + private static final String TAB2 = TAB + TAB; + /** */ + private static final String TAB3 = TAB + TAB + TAB; + + /** + * Add line to source code without indent. + * + * @param src Source code. + * @param line Code line. + */ + private static void add0(Collection<String> src, String line) { + src.add(line); + } + + /** + * Add line to source code with one indent. + * + * @param src Source code. + * @param line Code line. + */ + private static void add1(Collection<String> src, String line) { + src.add(TAB + line); + } + + /** + * Add line to source code with two indents. + * + * @param src Source code. + * @param line Code line. + */ + private static void add2(Collection<String> src, String line) { + src.add(TAB2 + line); + } + + /** + * Add line to source code with three indents. + * + * @param src Source code. + * @param line Code line. + */ + private static void add3(Collection<String> src, String line) { + src.add(TAB3 + line); + } + + /** + * @param str Source string. + * @return String with first letters in upper case. + */ + private static String capitalizeFirst(String str) { + return Character.toUpperCase(str.charAt(0)) + str.substring(1); + } + + /** + * Generate java class code. + * + * @param pkg Package name. + * @param type Type name. + * @param descs Type descriptors. + * @param constructor If {@code true} then generate empty and full constructors. + * @param askOverwrite Callback to ask user to confirm file overwrite. + * @throws IOException If failed to write generated code into file. + */ + private static void generateCode(String pkg, String type, Collection<GridCacheQueryTypeDescriptor> descs, + File pkgFolder, boolean constructor, ConfirmCallable askOverwrite) throws IOException { + File out = new File(pkgFolder, type + ".java"); + + if (out.exists()) { + MessageBox.Result choice = askOverwrite.confirm(out.getName()); + + if (CANCEL == choice) + throw new IllegalStateException("POJO generation was canceled!"); + + if (NO == choice || NO_TO_ALL == choice) + return; + } + + Collection<String> src = new ArrayList<>(256); + + add0(src, "/*"); + add0(src, " * Licensed to the Apache Software Foundation (ASF) under one or more"); + add0(src, " * contributor license agreements. See the NOTICE file distributed with"); + add0(src, " * this work for additional information regarding copyright ownership."); + add0(src, " * The ASF licenses this file to You under the Apache License, Version 2.0"); + add0(src, " * (the \"License\"); you may not use this file except in compliance with"); + add0(src, " * the License. You may obtain a copy of the License at"); + add0(src, " *"); + add0(src, " * http://www.apache.org/licenses/LICENSE-2.0"); + add0(src, " *"); + add0(src, " * Unless required by applicable law or agreed to in writing, software"); + add0(src, " * distributed under the License is distributed on an \"AS IS\" BASIS,"); + add0(src, " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied."); + add0(src, " * See the License for the specific language governing permissions and"); + add0(src, " * limitations under the License."); + add0(src, " */"); + + add0(src, ""); + + add0(src, "package " + pkg + ";"); + + add0(src, ""); + + add0(src, "import java.io.*;"); + + add0(src, ""); + + add0(src, "/**"); + add0(src, " * " + type + " definition."); + add0(src, " *"); + add0(src, " * Code generated by Apache Ignite Schema Load utility."); + add0(src, " */"); + add0(src, "public class " + type + " implements Serializable {"); + + add1(src, "/** */"); + add1(src, "private static final long serialVersionUID = 0L;"); + + add0(src, ""); + + // Fields. + for (GridCacheQueryTypeDescriptor desc : descs) { + String fldName = desc.getJavaName(); + + add1(src, "/** Value for " + fldName + ". */"); + add1(src, "private " + desc.getJavaType().getSimpleName() + " " + fldName + ";"); + add0(src, ""); + } + + // Constructors. + if (constructor) { + add1(src, "/**"); + add1(src, " * Empty constructor."); + add1(src, " */"); + add1(src, "public " + type + "() {"); + add2(src, "// No-op."); + add1(src, "}"); + + add0(src, ""); + + add1(src, "/**"); + add1(src, " * Full constructor."); + add1(src, " */"); + add1(src, "public " + type + "("); + + Iterator<GridCacheQueryTypeDescriptor> it = descs.iterator(); + + while (it.hasNext()) { + GridCacheQueryTypeDescriptor desc = it.next(); + + add2(src, desc.getJavaType().getSimpleName() + " " + desc.getJavaName() + (it.hasNext() ? "," : "")); + } + add1(src, ") {"); + + for (GridCacheQueryTypeDescriptor desc : descs) + add2(src, String.format("this.%1$s = %1$s;", desc.getJavaName())); + + add1(src, "}"); + + add0(src, ""); + } + + // Methods. + for (GridCacheQueryTypeDescriptor desc : descs) { + String fldName = desc.getJavaName(); + + String fldType = desc.getJavaType().getSimpleName(); + + String mtdName = capitalizeFirst(fldName); + + add1(src, "/**"); + add1(src, " * Gets " + fldName + "."); + add1(src, " *"); + add1(src, " * @return Value for " + fldName + "."); + add1(src, " */"); + add1(src, "public " + fldType + " get" + mtdName + "() {"); + add2(src, "return " + fldName + ";"); + add1(src, "}"); + + add0(src, ""); + + add1(src, "/**"); + add1(src, " * Sets " + fldName + "."); + add1(src, " *"); + add1(src, " * @param " + fldName + " New value for " + fldName + "."); + add1(src, " */"); + add1(src, "public void set" + mtdName + "(" + fldType + " " + fldName + ") {"); + add2(src, "this." + fldName + " = " + fldName + ";"); + add1(src, "}"); + + add0(src, ""); + } + + add1(src, "/** {@inheritDoc} */"); + add1(src, "@Override public boolean equals(Object o) {"); + add2(src, "if (this == o)"); + add3(src, "return true;"); + + add0(src, ""); + + add2(src, "if (!(o instanceof " + type + "))"); + add3(src, "return false;"); + + add0(src, ""); + + add2(src, String.format("%1$s that = (%1$s)o;", type)); + + for (GridCacheQueryTypeDescriptor desc : descs) { + add0(src, ""); + add2(src, String.format("if (%1$s != null ? !%1$s.equals(that.%1$s) : that.%1$s != null)", + desc.getJavaName())); + add3(src, "return false;"); + } + + add0(src, ""); + add2(src, "return true;"); + add1(src, "}"); + + add0(src, ""); + + add1(src, "/** {@inheritDoc} */"); + add1(src, "@Override public int hashCode() {"); + + Iterator<GridCacheQueryTypeDescriptor> it = descs.iterator(); + + 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().getJavaName())); + } + + add0(src, ""); + add2(src, "return res;"); + add1(src, "}"); + + add0(src, ""); + + add1(src, "/** {@inheritDoc} */"); + add1(src, "@Override public String toString() {"); + + it = descs.iterator(); + + add2(src, String.format("return \"%1$s [%2$s=\" + %2$s +", type, it.next().getJavaName())); + + while (it.hasNext()) + add3(src, String.format("\", %1$s=\" + %1$s +", it.next().getJavaName())); + + add3(src, "\"]\";"); + add1(src, "}"); + + add0(src, "}"); + + try (Writer writer = new BufferedWriter(new FileWriter(out))) { + for (String line : src) + writer.write(line + '\n'); + } + } + + /** + * Generate source code for type by its metadata. + * + * @param meta Type metadata. + * @param outFolder Output folder. + * @param pkg Types package. + * @param constructor If {@code true} then generate empty and full constructors. + * @param askOverwrite Callback to ask user to confirm file overwrite. + * @throws IOException If failed to write generated code into file. + */ + public static void generate(GridCacheQueryTypeMetadata meta, String outFolder, String pkg, boolean constructor, + ConfirmCallable askOverwrite) + 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(pkg, meta.getKeyType(), meta.getKeyDescriptors(), pkgFolder, constructor, askOverwrite); + + generateCode(pkg, meta.getType(), meta.getValueDescriptors(), pkgFolder, constructor, askOverwrite); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java new file mode 100644 index 0000000..a038bd9 --- /dev/null +++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java @@ -0,0 +1,320 @@ +/* + * 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.generator; + +import org.apache.ignite.lang.*; +import org.apache.ignite.schema.ui.*; +import org.gridgain.grid.cache.query.*; +import org.gridgain.grid.util.typedef.*; +import org.w3c.dom.*; + +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.*; +import javax.xml.transform.stream.*; +import java.io.*; +import java.util.*; + +import static org.apache.ignite.schema.ui.MessageBox.Result.*; + +/** + * Generator of XML files for type metadata. + */ +public class XmlGenerator { + /** + * Add bean to XML document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param clazz Bean class. + */ + private static Element addBean(Document doc, Node parent, Class<?> clazz) { + Element elem = doc.createElement("bean"); + + elem.setAttribute("class", clazz.getName()); + + parent.appendChild(elem); + + return elem; + } + + /** + * Add element to XML document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param tagName XML tag name. + * @param attr1 Name for first attr. + * @param val1 Value for first attribute. + * @param attr2 Name for second attr. + * @param val2 Value for second attribute. + */ + private static Element addElement(Document doc, Node parent, String tagName, + String attr1, String val1, String attr2, String val2) { + Element elem = doc.createElement(tagName); + + if (attr1 != null) + elem.setAttribute(attr1, val1); + + if (attr2 != null) + elem.setAttribute(attr2, val2); + + parent.appendChild(elem); + + return elem; + } + + /** + * Add element to XML document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param tagName XML tag name. + */ + private static Element addElement(Document doc, Node parent, String tagName) { + return addElement(doc, parent, tagName, null, null, null, null); + } + + /** + * Add element to XML document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param tagName XML tag name. + */ + private static Element addElement(Document doc, Node parent, String tagName, String attrName, String attrVal) { + return addElement(doc, parent, tagName, attrName, attrVal, null, null); + } + + /** + * Add "property" element to XML document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param name Value for "name" attribute + * @param val Value for "value" attribute + */ + private static Element addProperty(Document doc, Node parent, String name, String val) { + String valAttr = val != null ? "value" : null; + + return addElement(doc, parent, "property", "name", name, valAttr, val); + } + + /** + * Add fields to xml document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param name Property name. + * @param fields Map with fields. + */ + private static void addFields(Document doc, Node parent, String name, Map<String, Class<?>> fields) { + if (!fields.isEmpty()) { + Element prop = addProperty(doc, parent, name, null); + + Element map = addElement(doc, prop, "map"); + + for (Map.Entry<String, Class<?>> item : fields.entrySet()) + addElement(doc, map, "entry", "key", item.getKey(), "value", item.getValue().getName()); + } + } + + /** + * Add type descriptors to XML document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param name Property name. + * @param descs Map with type descriptors. + */ + private static void addTypeDescriptors(Document doc, Node parent, String name, + Collection<GridCacheQueryTypeDescriptor> descs) { + if (!descs.isEmpty()) { + Element prop = addProperty(doc, parent, name, null); + + Element list = addElement(doc, prop, "list"); + + for (GridCacheQueryTypeDescriptor desc : descs) { + Element item = addBean(doc, list, GridCacheQueryTypeDescriptor.class); + + addProperty(doc, item, "javaName", desc.getJavaName()); + addProperty(doc, item, "javaType", desc.getJavaType().getName()); + addProperty(doc, item, "dbName", desc.getDbName()); + addProperty(doc, item, "dbType", String.valueOf(desc.getDbType())); + } + } + } + + /** + * Add text fields to xml document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param textFields Collection with text fields. + */ + private static void addTextFields(Document doc, Node parent, Collection<String> textFields) { + if (!textFields.isEmpty()) { + Element prop = addProperty(doc, parent, "textFields", null); + + Element list = addElement(doc, prop, "list"); + + for (String textField : textFields) + addElement(doc, list, "value").setNodeValue(textField); + } + } + + /** + * Add indexes to xml document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param groups Map with indexes. + */ + private static void addGroups(Document doc, Node parent, + Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> groups) { + if (!F.isEmpty(groups)) { + Element prop = addProperty(doc, parent, "groups", null); + + Element map = addElement(doc, prop, "map"); + + for (Map.Entry<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> group : groups.entrySet()) { + Element entry1 = addElement(doc, map, "entry", "key", group.getKey()); + + Element val1 = addElement(doc, entry1, "map"); + + LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> fields = group.getValue(); + + for (Map.Entry<String, IgniteBiTuple<Class<?>, Boolean>> field : fields.entrySet()) { + Element entry2 = addElement(doc, val1, "entry", "key", field.getKey()); + + Element val2 = addBean(doc, entry2, IgniteBiTuple.class); + + IgniteBiTuple<Class<?>, Boolean> tuple = field.getValue(); + + Class<?> clazz = tuple.get1(); + + assert clazz != null; + + addElement(doc, val2, "constructor-arg", null, null, "value", clazz.getName()); + addElement(doc, val2, "constructor-arg", null, null, "value", String.valueOf(tuple.get2())); + } + } + } + } + + /** + * Add element with type metadata to XML document. + * + * @param doc XML document. + * @param parent Parent XML node. + * @param pkg Package fo types. + * @param meta Meta. + */ + private static void addTypeMetadata(Document doc, Node parent, String pkg, GridCacheQueryTypeMetadata meta) { + Element bean = addBean(doc, parent, GridCacheQueryTypeMetadata.class); + + addProperty(doc, bean, "type", pkg + "." + meta.getType()); + + addProperty(doc, bean, "keyType", pkg + "." + meta.getKeyType()); + + addProperty(doc, bean, "schema", meta.getSchema()); + + addProperty(doc, bean, "tableName", meta.getTableName()); + + addTypeDescriptors(doc, bean, "keyDescriptors", meta.getKeyDescriptors()); + + addTypeDescriptors(doc, bean, "valueDescriptors", meta.getValueDescriptors()); + + addFields(doc, bean, "queryFields", meta.getQueryFields()); + + addFields(doc, bean, "ascendingFields", meta.getAscendingFields()); + + addFields(doc, bean, "descendingFields", meta.getDescendingFields()); + + addTextFields(doc, bean, meta.getTextFields()); + + addGroups(doc, bean, meta.getGroups()); + } + + /** + * Transform metadata into xml. + * + * @param pkg Package fo types. + * @param meta Metadata to transform. + * @param out File to output result. + * @param askOverwrite Callback to ask user to confirm file overwrite. + */ + public static void transform(String pkg, GridCacheQueryTypeMetadata meta, File out, ConfirmCallable askOverwrite) { + transform(pkg, Collections.singleton(meta), out, askOverwrite); + } + + /** + * Transform metadata into xml. + * + * @param pkg Package fo types. + * @param meta Metadata to transform. + * @param out File to output result. + * @param askOverwrite Callback to ask user to confirm file overwrite. + */ + public static void transform(String pkg, Collection<GridCacheQueryTypeMetadata> meta, File out, + ConfirmCallable askOverwrite) { + try { + if (out.exists()) { + MessageBox.Result choice = askOverwrite.confirm(out.getName()); + + if (CANCEL == choice) + throw new IllegalStateException("XML generation was canceled!"); + + if (NO == choice || NO_TO_ALL == choice) + return; + } + + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + + Document doc = docBuilder.newDocument(); + doc.setXmlStandalone(true); + + Element beans = addElement(doc, doc, "beans"); + beans.setAttribute("xmlns", "http://www.springframework.org/schema/beans"); + beans.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + beans.setAttribute("xmlns:util", "http://www.springframework.org/schema/util"); + beans.setAttribute("xsi:schemaLocation", + "http://www.springframework.org/schema/beans " + + "http://www.springframework.org/schema/beans/spring-beans.xsd " + + "http://www.springframework.org/schema/util " + + "http://www.springframework.org/schema/util/spring-util.xsd"); + + for (GridCacheQueryTypeMetadata item : meta) + addTypeMetadata(doc, beans, pkg, item); + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + + Transformer transformer = transformerFactory.newTransformer(); + + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + + transformer.transform(new DOMSource(doc), new StreamResult(out)); + } + catch (ParserConfigurationException | TransformerException e) { + throw new IllegalStateException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java ---------------------------------------------------------------------- diff --git a/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java new file mode 100644 index 0000000..3990496 --- /dev/null +++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import javafx.application.*; +import javafx.stage.*; + +import java.util.concurrent.*; + +import static org.apache.ignite.schema.ui.MessageBox.Result.*; + +/** + * Callable to ask user for confirmation from non EDT thread. + */ +public class ConfirmCallable implements Callable<MessageBox.Result> { + /** Owner window. */ + private final Stage owner; + + /** Message template. */ + private final String template; + + /** Message to show in confirmation dialog. */ + private String msg; + + /** User choice. */ + private MessageBox.Result choice = NO; + + /** + * @param owner Owner window. + * @param template Message template. + */ + public ConfirmCallable(Stage owner, String template) { + this.owner = owner; + this.template = template; + } + + /** {@inheritDoc} */ + @Override public MessageBox.Result call() throws Exception { + choice = MessageBox.confirmRememberChoiceDialog(owner, String.format(template, msg)); + + return choice; + } + + /** + * Execute confirmation in EDT thread. + * + * @return Confirm result. + */ + public MessageBox.Result confirm(String msg) { + this.msg = msg; + + if (choice == YES_TO_ALL || choice == NO_TO_ALL) + return choice; + + FutureTask<MessageBox.Result> fut = new FutureTask<>(this); + + Platform.runLater(fut); + + try { + return fut.get(); + } + catch (Exception ignored) { + return NO; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/410f9e5e/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 new file mode 100644 index 0000000..039b478 --- /dev/null +++ b/modules/schema-load/src/main/java/org/apache/ignite/schema/ui/Controls.java @@ -0,0 +1,377 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import javafx.event.*; +import javafx.geometry.*; +import javafx.scene.*; +import javafx.scene.control.*; +import javafx.scene.control.cell.*; +import javafx.scene.image.*; +import javafx.scene.layout.*; +import javafx.scene.text.*; + +/** + * Utility class to create controls. + */ +public class Controls { + /** */ + public static final Insets DFLT_PADDING = new Insets(10, 10, 10, 10); + + /** + * Create scene with predefined style. + * + * @param root The root node of the scene graph. + * @return New {@code Scene} instance. + */ + public static Scene scene(Parent root) { + Scene scene = new Scene(root); + + scene.getStylesheets().add("media/style.css"); + + return scene; + } + + /** + * Create grid pane with default padding. + * + * @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(double top, double right, double bottom, double left) { + GridPaneEx paneEx = new GridPaneEx(); + + paneEx.setPadding(new Insets(top, right, bottom, left)); + + return paneEx; + } + + /** + * Create new {@code HBox} with default padding. + * + * @param spacing Amount of horizontal space between each child. + * @param dfltPadding If {@code true} than set default padding for pane. + * @return New {@code HBox} instance. + */ + public static HBox hBox(int spacing, boolean dfltPadding) { + HBox hb = new HBox(spacing); + + if (dfltPadding) + hb.setPadding(DFLT_PADDING); + + return hb; + } + + /** + * Create new {@code HBox} with default padding and add controls. + * + * @param spacing Amount of horizontal space between each child. + * @param dfltPadding If {@code true} than set default padding for pane. + * @param controls Controls to add. + * @return New {@code HBox} instance. + */ + public static HBox hBox(int spacing, boolean dfltPadding, Node... controls) { + HBox hb = hBox(spacing, dfltPadding); + + hb.getChildren().addAll(controls); + + return hb; + } + + /** + * Create new {@code VBox} with default padding. + * + * @param spacing Amount of horizontal space between each child. + * @return New {@code VBox} instance. + */ + public static VBox vBox(int spacing) { + VBox vb = new VBox(spacing); + + vb.setPadding(DFLT_PADDING); + + return vb; + } + + /** + * Create new {@code VBox} with default padding and add controls. + * + * @param spacing Amount of horizontal space between each child. + * @param controls Controls to add. + * @return New {@code VBox} instance. + */ + public static VBox vBox(int spacing, Node... controls) { + VBox vb = vBox(spacing); + + vb.getChildren().addAll(controls); + + return vb; + } + + /** + * Create stack pane. + * + * @param controls Controls to add. + * @return New {@code StackPane} instance. + */ + public static StackPane stackPane(Node... controls) { + StackPane sp = new StackPane(); + + sp.getChildren().addAll(controls); + + return sp; + } + + /** + * Create border pane. + * + * @param top Optional top control. + * @param center Optional center control. + * @param bottom Optional bottom control. + * @param left Optional left control. + * @param right Optional right control. + * @return New {@code BorderPane} instance. + */ + public static BorderPane borderPane(Node top, Node center, Node bottom, Node left, Node right) { + BorderPane bp = new BorderPane(); + + bp.setTop(top); + bp.setCenter(center); + bp.setBottom(bottom); + bp.setLeft(left); + bp.setRight(right); + + return bp; + } + + /** + * Sets control tooltip if needed. + * + * @param ctrl Target control. + * @param tip Tooltip text. + * @return Control itself for method chaining. + */ + public static <T extends Control> T tooltip(T ctrl, String tip) { + if (!tip.isEmpty()) + ctrl.setTooltip(new Tooltip(tip)); + + return ctrl; + } + + /** + * Create button with text only. + * + * @param text Button text. + * @param tip Tooltip text. + * @param onAct Button action. + * @return New {@code Button} instance. + */ + public static Button button(String text, String tip, EventHandler<ActionEvent> onAct) { + Button btn = new Button(text); + + btn.setOnAction(onAct); + + tooltip(btn, tip); + + return btn; + } + + /** + * Create button with icon only. + * + * @param icon Button icon. + * @param tip Tooltip text. + * @param onAct Button action. + * @return New {@code Button} instance. + */ + public static Button button(ImageView icon, String tip, EventHandler<ActionEvent> onAct) { + Button btn = new Button(); + + btn.setGraphic(icon); + btn.setOnAction(onAct); + + tooltip(btn, tip); + + return btn; + } + + /** + * Create pane with buttons. + * + * @param alignment Alignment of buttons. + * @param dfltPadding If {@code true} than set default padding for pane. + * @param btns Buttons that will be added to pane. + * @return New {@code HBox} instance with buttons. + */ + public static Pane buttonsPane(Pos alignment, boolean dfltPadding, Button... btns) { + HBox hb = hBox(10, dfltPadding, btns); + + hb.setAlignment(alignment); + + return hb; + } + + /** + * Create checkbox. + * + * @param text Checkbox text. + * @param tip Tooltip tex. + * @param sel Checkbox selected state. + * @return New {@code Checkbox} instance. + */ + public static CheckBox checkBox(String text, String tip, boolean sel) { + CheckBox ch = new CheckBox(text); + + ch.setSelected(sel); + + tooltip(ch, tip); + + return ch; + } + + /** + * Create text field. + * + * @param tip Tooltip text. + * @return New {@code TextField} instance. + */ + public static TextField textField(String tip) { + TextField tf = new TextField(); + + tooltip(tf, tip); + + return tf; + } + + /** + * Create static text. + * + * @param text Text to show. + * @param wrap Text wrapping width. + * @return New {@code Text} instance. + */ + public static Text text(String text, int wrap) { + Text t = new Text(text); + + t.setFont(new Font(14)); + + if (wrap > 0) + t.setWrappingWidth(wrap); + + return t; + } + + /** + * Create password field. + * + * @param tip Tooltip text. + * @return New {@code PasswordField} instance. + */ + public static PasswordField passwordField(String tip) { + PasswordField pf = new PasswordField(); + + tooltip(pf, tip); + + return pf; + } + + /** + * Create split pane for provided nodes. + * + * @param node1 First node. + * @param node2 Second node. + * @param pos Initial divider position. + * @return New {@code SplitPane} instance. + */ + public static SplitPane splitPane(Node node1, Node node2, double pos) { + SplitPane sp = new SplitPane(); + + sp.setOrientation(Orientation.VERTICAL); + sp.getItems().addAll(node1, node2); + sp.setDividerPosition(0, pos); + + return sp; + } + + /** + * Create table column. + * + * @param colName Column name to display. + * @param propName Property name column is bound to. + * @param tip Column tooltip text. + * @param minWidth The minimum width column is permitted to be resized to. + * @param maxWidth The maximum width column is permitted to be resized to. + * @return New {@code TableColumn} instance. + */ + public static <S, T> TableColumn<S, T> tableColumn(String colName, String propName, String tip, + int minWidth, int maxWidth) { + TableColumn<S, T> col = new TableColumn<>(); + + col.setGraphic(tooltip(new Label(colName), tip)); + + col.setSortable(false); + + if (minWidth > 0) + col.setMinWidth(minWidth); + + if (maxWidth > 0) + col.setMaxWidth(maxWidth); + + col.setCellValueFactory(new PropertyValueFactory<S, T>(propName)); + + return col; + } + + /** + * Create progress indicator. + * + * @param sz Indicator diameter. + * @return New {@code ProgressIndicator} instance. + */ + public static ProgressIndicator progressIndicator(int sz) { + ProgressIndicator pi = new ProgressIndicator(); + + pi.setMaxWidth(sz); + pi.setMaxHeight(sz); + + return pi; + } + + /** + * Create image view. + * + * @param imgFileName Image filename. + * @return New {@code ImageView} instance. + */ + public static ImageView imageView(String imgFileName, int sz) { + return new ImageView(image(imgFileName, sz)); + } + + /** + * Gets image by its filename. + * + * @param imgFileName Image filename. + * @return Loaded image. + */ + public static Image image(String imgFileName, int sz) { + return new Image(Controls.class.getClassLoader() + .getResourceAsStream(String.format("media/%1$s_%2$dx%2$d.png", imgFileName, sz))); + } +}