From 8d601bd15e9046c7e4a716e0681f110cce876fb0 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Wed, 14 Mar 2018 14:50:53 +0100
Subject: [PATCH] structures for plugin data

---
 .../lcsb/mapviewer/model/plugin/Plugin.java   | 102 ++++++++++++++++++
 .../model/plugin/PluginDataEntry.java         |  90 ++++++++++++++++
 ...ix_db_20180206.sql => fix_db_20180311.sql} |   0
 .../src/db/12.0.0~alpha.2/fix_db_20180314.sql |  49 +++++++++
 .../lcsb/mapviewer/persist/dao/BaseDao.java   |  10 +-
 .../persist/dao/plugin/PluginDao.java         |  20 ++++
 .../dao/plugin/PluginDataEntryDao.java        |  43 ++++++++
 .../resources/applicationContext-persist.xml  |   5 +
 .../mapviewer/persist/dao/AllDaoTests.java    |  16 +--
 .../persist/dao/plugin/AllPluginTests.java    |  12 +++
 .../persist/dao/plugin/PluginDaoTest.java     |  32 ++++++
 .../dao/plugin/PluginDataEntryDaoTest.java    |  65 +++++++++++
 12 files changed, 435 insertions(+), 9 deletions(-)
 create mode 100644 model/src/main/java/lcsb/mapviewer/model/plugin/Plugin.java
 create mode 100644 model/src/main/java/lcsb/mapviewer/model/plugin/PluginDataEntry.java
 rename persist/src/db/12.0.0~alpha.1/{fix_db_20180206.sql => fix_db_20180311.sql} (100%)
 create mode 100644 persist/src/db/12.0.0~alpha.2/fix_db_20180314.sql
 create mode 100644 persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDao.java
 create mode 100644 persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDao.java
 create mode 100644 persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/AllPluginTests.java
 create mode 100644 persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDaoTest.java
 create mode 100644 persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDaoTest.java

diff --git a/model/src/main/java/lcsb/mapviewer/model/plugin/Plugin.java b/model/src/main/java/lcsb/mapviewer/model/plugin/Plugin.java
new file mode 100644
index 0000000000..ad3fd50c8e
--- /dev/null
+++ b/model/src/main/java/lcsb/mapviewer/model/plugin/Plugin.java
@@ -0,0 +1,102 @@
+package lcsb.mapviewer.model.plugin;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Table;
+
+/**
+ * Meta data of the plugin used in the system.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+@Entity
+@Table(name = "plugin_table")
+public class Plugin implements Serializable {
+
+  /**
+  	* 
+    */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Unique database identifier.
+   */
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  @Column(name = "idDb", unique = true, nullable = false)
+  private int id;
+
+  /**
+   * Hash of the plugin code used as identifier to distinguish between plugins.
+   */
+  private String hash;
+
+  /**
+   * Name of the plugin.
+   */
+  private String name;
+
+  /**
+   * Version of the plugin.
+   */
+  private String version;
+
+  /**
+   * List of urls from which plugin can be downloaded.
+   */
+  @ElementCollection
+  @CollectionTable(name = "plugin_urls", joinColumns = @JoinColumn(name = "plugin_iddb"))
+  @Column(name = "url")
+  private Set<String> urls = new HashSet<>();
+
+  public String getHash() {
+    return hash;
+  }
+
+  public void setHash(String hash) {
+    this.hash = hash;
+  }
+
+  public Set<String> getUrls() {
+    return urls;
+  }
+
+  public void setUrls(Set<String> urls) {
+    this.urls = urls;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  public int getId() {
+    return id;
+  }
+
+  public void setId(int id) {
+    this.id = id;
+  }
+}
diff --git a/model/src/main/java/lcsb/mapviewer/model/plugin/PluginDataEntry.java b/model/src/main/java/lcsb/mapviewer/model/plugin/PluginDataEntry.java
new file mode 100644
index 0000000000..3f661f5284
--- /dev/null
+++ b/model/src/main/java/lcsb/mapviewer/model/plugin/PluginDataEntry.java
@@ -0,0 +1,90 @@
+package lcsb.mapviewer.model.plugin;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import lcsb.mapviewer.model.user.User;
+
+/**
+ * Single entry of data stored by the plugin.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+@Entity
+@Table(name = "plugin_data_entry")
+public class PluginDataEntry implements Serializable {
+
+  /**
+  	* 
+    */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Unique database identifier.
+   */
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  @Column(name = "idDb", unique = true, nullable = false)
+  private int id;
+
+  @ManyToOne(fetch = FetchType.LAZY, optional = true)
+  private User user;
+
+  @ManyToOne(fetch = FetchType.LAZY, optional = false)
+  private Plugin plugin;
+
+  @Column(name = "entry_key", nullable = false)
+  private String key;
+
+  @Column(name = "entry_value", nullable = false)
+  private String value;
+
+  public int getId() {
+    return id;
+  }
+
+  public void setId(int id) {
+    this.id = id;
+  }
+
+  public User getUser() {
+    return user;
+  }
+
+  public void setUser(User user) {
+    this.user = user;
+  }
+
+  public Plugin getPlugin() {
+    return plugin;
+  }
+
+  public void setPlugin(Plugin plugin) {
+    this.plugin = plugin;
+  }
+
+  public String getKey() {
+    return key;
+  }
+
+  public void setKey(String key) {
+    this.key = key;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(String value) {
+    this.value = value;
+  }
+}
diff --git a/persist/src/db/12.0.0~alpha.1/fix_db_20180206.sql b/persist/src/db/12.0.0~alpha.1/fix_db_20180311.sql
similarity index 100%
rename from persist/src/db/12.0.0~alpha.1/fix_db_20180206.sql
rename to persist/src/db/12.0.0~alpha.1/fix_db_20180311.sql
diff --git a/persist/src/db/12.0.0~alpha.2/fix_db_20180314.sql b/persist/src/db/12.0.0~alpha.2/fix_db_20180314.sql
new file mode 100644
index 0000000000..b5fc165fc1
--- /dev/null
+++ b/persist/src/db/12.0.0~alpha.2/fix_db_20180314.sql
@@ -0,0 +1,49 @@
+CREATE SEQUENCE plugin_table_iddb_seq
+  INCREMENT 1
+  MINVALUE 1
+  MAXVALUE 9223372036854775807
+  START 1
+  CACHE 1;
+  
+CREATE TABLE plugin_table
+(
+  iddb integer NOT NULL DEFAULT nextval('plugin_table_iddb_seq'::regclass),
+  hash character varying(255) NOT NULL,
+  name character varying(255) NOT NULL,
+  version character varying(255) NOT NULL,
+  CONSTRAINT plugin_pkey PRIMARY KEY (iddb),
+  CONSTRAINT plugin_hash_unique UNIQUE (hash)
+);
+
+CREATE TABLE plugin_urls
+(
+  plugin_iddb integer NOT NULL,
+  url character varying(1024) NOT NULL,
+  CONSTRAINT plugin_urls_pkey PRIMARY KEY (plugin_iddb, url),
+  CONSTRAINT plugin_urls_fk FOREIGN KEY (plugin_iddb)
+      REFERENCES public.plugin_table (iddb) MATCH SIMPLE
+      ON UPDATE CASCADE ON DELETE CASCADE
+);
+
+CREATE SEQUENCE plugin_data_entry_iddb_seq
+  INCREMENT 1
+  MINVALUE 1
+  MAXVALUE 9223372036854775807
+  START 1
+  CACHE 1;
+
+CREATE TABLE plugin_data_entry
+(
+  iddb integer NOT NULL DEFAULT nextval('plugin_table_iddb_seq'::regclass),
+  plugin_iddb integer NOT NULL,
+  user_iddb integer,
+  entry_key character varying(1024) NOT NULL,
+  entry_value character varying(2048) NOT NULL,
+  CONSTRAINT plugin_data_entry_pkey PRIMARY KEY (iddb),
+  CONSTRAINT plugin_data_entry_plugin_fk FOREIGN KEY (plugin_iddb)
+      REFERENCES public.plugin_table (iddb) MATCH SIMPLE
+      ON UPDATE CASCADE ON DELETE CASCADE,
+  CONSTRAINT plugin_data_entry_user_fk FOREIGN KEY (user_iddb)
+      REFERENCES public.user_table (iddb) MATCH SIMPLE
+      ON UPDATE CASCADE ON DELETE CASCADE
+);
diff --git a/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java b/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java
index c6b2da5579..ff6e427890 100644
--- a/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java
+++ b/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java
@@ -220,7 +220,11 @@ public abstract class BaseDao<T> {
       if (!firstParam) {
         queryString += " AND ";
       }
-      queryString += key + " = :param_val_" + key + " ";
+      if (param.getRight() == null) {
+        queryString += key + " is null ";
+      } else {
+        queryString += key + " = :param_val_" + key + " ";
+      }
 
       firstParam = false;
     }
@@ -229,7 +233,9 @@ public abstract class BaseDao<T> {
     for (Pair<String, Object> param : params) {
       String key = param.getLeft();
       Object value = param.getRight();
-      query = query.setParameter("param_val_" + key, value);
+      if (value != null) {
+        query = query.setParameter("param_val_" + key, value);
+      }
     }
     List<?> list = query.list();
     return (List<T>) list;
diff --git a/persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDao.java b/persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDao.java
new file mode 100644
index 0000000000..d76e95bc25
--- /dev/null
+++ b/persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDao.java
@@ -0,0 +1,20 @@
+package lcsb.mapviewer.persist.dao.plugin;
+
+import lcsb.mapviewer.model.plugin.Plugin;
+import lcsb.mapviewer.persist.dao.BaseDao;
+
+/**
+ * Data access object class for {@link Plugin} objects.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public class PluginDao extends BaseDao<Plugin> {
+  /**
+   * Default constructor.
+   */
+  public PluginDao() {
+    super(Plugin.class);
+  }
+
+}
diff --git a/persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDao.java b/persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDao.java
new file mode 100644
index 0000000000..34eaed2a25
--- /dev/null
+++ b/persist/src/main/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDao.java
@@ -0,0 +1,43 @@
+package lcsb.mapviewer.persist.dao.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lcsb.mapviewer.common.Pair;
+import lcsb.mapviewer.model.plugin.Plugin;
+import lcsb.mapviewer.model.plugin.PluginDataEntry;
+import lcsb.mapviewer.model.user.User;
+import lcsb.mapviewer.persist.dao.BaseDao;
+
+/**
+ * Data access object class for {@link PluginDataEntry} objects.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public class PluginDataEntryDao extends BaseDao<PluginDataEntry> {
+  /**
+   * Default constructor.
+   */
+  public PluginDataEntryDao() {
+    super(PluginDataEntry.class);
+  }
+
+  public PluginDataEntry getByKey(Plugin plugin, String key, User user) {
+    List<Pair<String, Object>> params = new ArrayList<>();
+    params.add(new Pair<String, Object>("plugin_iddb", plugin.getId()));
+    params.add(new Pair<String, Object>("entry_key", key));
+    if (user == null) {
+      params.add(new Pair<String, Object>("user_iddb", null));
+    } else {
+      params.add(new Pair<String, Object>("user_iddb", user.getId()));
+    }
+    List<PluginDataEntry> entries = getElementsByParameters(params);
+    if (entries.size() > 0) {
+      return entries.get(0);
+    } else {
+      return null;
+    }
+  }
+
+}
diff --git a/persist/src/main/resources/applicationContext-persist.xml b/persist/src/main/resources/applicationContext-persist.xml
index 7743d71430..623cbfdb71 100644
--- a/persist/src/main/resources/applicationContext-persist.xml
+++ b/persist/src/main/resources/applicationContext-persist.xml
@@ -25,6 +25,9 @@
 	<bean id="DataMiningSetDao" class="lcsb.mapviewer.persist.dao.map.graph.DataMiningSetDao" parent="BaseDao"/>
 
 	<bean id="ElementDao" class="lcsb.mapviewer.persist.dao.map.species.ElementDao" parent="BaseDao"/>
+
+	<bean id="PluginDao" class="lcsb.mapviewer.persist.dao.plugin.PluginDao" parent="BaseDao"/>
+	<bean id="PluginDataEntryDao" class="lcsb.mapviewer.persist.dao.plugin.PluginDataEntryDao" parent="BaseDao"/>
 	
 	<bean id="ReferenceGenomeDao" class="lcsb.mapviewer.persist.dao.map.layout.ReferenceGenomeDao" parent="BaseDao"/>
 	<bean id="ReferenceGenomeGeneMappingDao" class="lcsb.mapviewer.persist.dao.map.layout.ReferenceGenomeGeneMappingDao" parent="BaseDao"/>
@@ -49,6 +52,8 @@
 		<property name="dataSource" ref="DataSource" />
 		<property name="annotatedClasses">
 			<list>
+				<value>lcsb.mapviewer.model.plugin.Plugin</value>
+				<value>lcsb.mapviewer.model.plugin.PluginDataEntry</value>
 
 				<value>lcsb.mapviewer.model.map.graph.DataMining</value>
 				<value>lcsb.mapviewer.model.map.graph.DataMiningSet</value>
diff --git a/persist/src/test/java/lcsb/mapviewer/persist/dao/AllDaoTests.java b/persist/src/test/java/lcsb/mapviewer/persist/dao/AllDaoTests.java
index f289c4e122..50e07ae2b1 100644
--- a/persist/src/test/java/lcsb/mapviewer/persist/dao/AllDaoTests.java
+++ b/persist/src/test/java/lcsb/mapviewer/persist/dao/AllDaoTests.java
@@ -7,17 +7,19 @@ import lcsb.mapviewer.persist.dao.cache.AllCacheDbTests;
 import lcsb.mapviewer.persist.dao.graphics.AllGraphicsDaoTests;
 import lcsb.mapviewer.persist.dao.log.AllLogTests;
 import lcsb.mapviewer.persist.dao.map.AllMapDaoTests;
+import lcsb.mapviewer.persist.dao.plugin.AllPluginTests;
 import lcsb.mapviewer.persist.dao.user.AllUserTests;
 
 @RunWith(Suite.class)
 @Suite.SuiteClasses({ AllCacheDbTests.class, //
-		AllGraphicsDaoTests.class, //
-		AllLogTests.class, //
-		AllMapDaoTests.class, //
-		AllUserTests.class, //
-		BaseDaoTest.class, //
-		ConfigurationDaoTest.class, //
-		ProjectDaoTest.class, //
+    AllGraphicsDaoTests.class, //
+    AllLogTests.class, //
+    AllMapDaoTests.class, //
+    AllPluginTests.class, //
+    AllUserTests.class, //
+    BaseDaoTest.class, //
+    ConfigurationDaoTest.class, //
+    ProjectDaoTest.class, //
 
 })
 public class AllDaoTests {
diff --git a/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/AllPluginTests.java b/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/AllPluginTests.java
new file mode 100644
index 0000000000..75664e9ccb
--- /dev/null
+++ b/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/AllPluginTests.java
@@ -0,0 +1,12 @@
+package lcsb.mapviewer.persist.dao.plugin;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({ PluginDaoTest.class, //
+    PluginDataEntryDaoTest.class })
+public class AllPluginTests {
+
+}
diff --git a/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDaoTest.java b/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDaoTest.java
new file mode 100644
index 0000000000..571c4dc906
--- /dev/null
+++ b/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDaoTest.java
@@ -0,0 +1,32 @@
+package lcsb.mapviewer.persist.dao.plugin;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import lcsb.mapviewer.model.plugin.Plugin;
+import lcsb.mapviewer.persist.PersistTestFunctions;
+
+public class PluginDaoTest extends PersistTestFunctions {
+
+  @Autowired
+  PluginDao pluginDao;
+
+  @Test
+  public void testGetPlugins() {
+    assertTrue(pluginDao.getAll().size() >= 0);
+  }
+  
+  @Test
+  public void testAddPlugin() {
+    Plugin plugin =new Plugin();
+    plugin.setHash("x");
+    plugin.setName("Plugin name");
+    plugin.setVersion("0.0.1");
+    plugin.getUrls().add("htpp://google.pl/");
+    pluginDao.add(plugin);
+    assertTrue(pluginDao.getAll().size() > 0);
+  }
+
+}
diff --git a/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDaoTest.java b/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDaoTest.java
new file mode 100644
index 0000000000..ca4893275e
--- /dev/null
+++ b/persist/src/test/java/lcsb/mapviewer/persist/dao/plugin/PluginDataEntryDaoTest.java
@@ -0,0 +1,65 @@
+package lcsb.mapviewer.persist.dao.plugin;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import lcsb.mapviewer.model.plugin.Plugin;
+import lcsb.mapviewer.model.plugin.PluginDataEntry;
+import lcsb.mapviewer.persist.PersistTestFunctions;
+
+public class PluginDataEntryDaoTest extends PersistTestFunctions {
+
+  @Autowired
+  PluginDataEntryDao pluginDataEntryDao;
+
+  @Autowired
+  PluginDao pluginDao;
+
+  @Test
+  public void testGetByKeyForGlobalParam() {
+    Plugin plugin =new Plugin();
+    plugin.setHash("x");
+    plugin.setName("Plugin name");
+    plugin.setVersion("0.0.1");
+    pluginDao.add(plugin);
+    
+    PluginDataEntry entry = new PluginDataEntry();
+    entry.setPlugin(plugin);
+    entry.setKey("x");
+    entry.setValue("y");
+    
+    pluginDataEntryDao.add(entry);
+
+    PluginDataEntry entry2 = pluginDataEntryDao.getByKey(entry.getPlugin(), entry.getKey(), entry.getUser());
+    assertEquals(entry, entry2);
+    assertNull(pluginDataEntryDao.getByKey(entry.getPlugin(), "blabla", entry.getUser()));
+  }
+
+  @Test
+  public void testGetByKeyForUserParam() {
+    createUser();
+    Plugin plugin =new Plugin();
+    plugin.setHash("x");
+    plugin.setName("Plugin name");
+    plugin.setVersion("0.0.1");
+    pluginDao.add(plugin);
+    
+    PluginDataEntry entry = new PluginDataEntry();
+    entry.setPlugin(plugin);
+    entry.setUser(user);
+    entry.setKey("x");
+    entry.setValue("y");
+    
+    pluginDataEntryDao.add(entry);
+
+    PluginDataEntry entry2 = pluginDataEntryDao.getByKey(entry.getPlugin(), entry.getKey(), user);
+    assertEquals(entry, entry2);
+    
+    assertNull(pluginDataEntryDao.getByKey(entry.getPlugin(), "blabla", user));
+    assertNull(pluginDataEntryDao.getByKey(entry.getPlugin(), entry.getKey(), null));
+  }
+
+}
-- 
GitLab