user data dao and tests
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
index 38e0834..cab2d4c 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
@@ -67,6 +67,7 @@
         }
     }
 
+    //todo: uniqueness constraints on usersettings and details (every user only one entry for data and settings)
     @Override
     public int updateSettings(UserSettings settings) throws KustvaktException {
         final String sql =
diff --git a/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java b/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java
index 4321def..50d22b9 100644
--- a/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java
+++ b/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java
@@ -73,7 +73,7 @@
     }
 
     @Deprecated
-    public static final void setProvgiders(PolicyHandlerIface policyHandler,
+    public static final void setProviders(PolicyHandlerIface policyHandler,
             EncryptionIface crypto, Collection<ResourceOperationIface> ifaces) {
         SecurityManager.policydao = policyHandler;
         SecurityManager.crypto = crypto;
diff --git a/src/main/java/de/ids_mannheim/korap/user/UserDataDbIface.java b/src/main/java/de/ids_mannheim/korap/user/UserDataDbIface.java
new file mode 100644
index 0000000..2d2f231
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/user/UserDataDbIface.java
@@ -0,0 +1,21 @@
+package de.ids_mannheim.korap.user;
+
+/**
+ * @author hanl
+ * @date 27/01/2016
+ */
+public interface UserDataDbIface<T extends Userdata> {
+
+    public int store(T data);
+
+    public int update(T data);
+
+    public T get(Integer id);
+
+    public T get(User user);
+
+    public int delete(T data);
+
+    public int deleteAll();
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/user/UserDetailsDao.java b/src/main/java/de/ids_mannheim/korap/user/UserDetailsDao.java
new file mode 100644
index 0000000..4e16bed
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/user/UserDetailsDao.java
@@ -0,0 +1,134 @@
+package de.ids_mannheim.korap.user;
+
+import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+
+/**
+ * @author hanl
+ * @date 27/01/2016
+ */
+public class UserDetailsDao implements UserDataDbIface<Userdetails2> {
+
+    private NamedParameterJdbcTemplate jdbcTemplate;
+
+    public UserDetailsDao(PersistenceClient client) {
+        this.jdbcTemplate = (NamedParameterJdbcTemplate) client.getSource();
+    }
+
+    @Override
+    public int store(Userdetails2 data) {
+        String sql = "INSERT INTO user_details2 (user_id, data) VALUES (:userid, :data);";
+        MapSqlParameterSource source = new MapSqlParameterSource();
+        source.addValue("userid", data.getUserID());
+        source.addValue("data", data.data());
+
+        GeneratedKeyHolder gen = new GeneratedKeyHolder();
+        try {
+            this.jdbcTemplate.update(sql, source, gen);
+            int id = gen.getKey().intValue();
+            data.setId(id);
+            return id;
+        }catch (DataAccessException e) {
+            e.printStackTrace();
+            return -1;
+        }
+    }
+
+    @Override
+    public int update(Userdetails2 data) {
+        String sql = "UPDATE user_details2 SET data = :data WHERE user_id=:userid;";
+        MapSqlParameterSource source = new MapSqlParameterSource();
+        source.addValue("userid", data.getUserID());
+        source.addValue("data", data.data());
+
+        try {
+            return this.jdbcTemplate.update(sql, source);
+        }catch (DataAccessException e) {
+            return -1;
+        }
+    }
+
+    @Override
+    public Userdetails2 get(Integer id) {
+        String sql = "SELECT * FROM user_details2 WHERE id=:id;";
+        MapSqlParameterSource source = new MapSqlParameterSource();
+        source.addValue("id", id);
+
+        try {
+            return this.jdbcTemplate
+                    .queryForObject(sql, source, new RowMapper<Userdetails2>() {
+
+                        @Override
+                        public Userdetails2 mapRow(ResultSet rs, int rowNum)
+                                throws SQLException {
+                            Userdetails2 details = new Userdetails2(
+                                    rs.getInt("user_id"));
+                            details.setId(rs.getInt("id"));
+                            details.setData(rs.getString("data"));
+                            return details;
+                        }
+                    });
+
+        }catch (DataAccessException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public Userdetails2 get(User user) {
+        String sql = "SELECT * FROM user_details2 WHERE user_id=:userid;";
+        MapSqlParameterSource source = new MapSqlParameterSource();
+        source.addValue("userid", user.getId());
+
+        try {
+            return this.jdbcTemplate
+                    .queryForObject(sql, source, new RowMapper<Userdetails2>() {
+
+                        @Override
+                        public Userdetails2 mapRow(ResultSet rs, int rowNum)
+                                throws SQLException {
+                            Userdetails2 details = new Userdetails2(
+                                    rs.getInt("user_id"));
+                            details.setId(rs.getInt("id"));
+                            details.setData(rs.getString("data"));
+                            return details;
+                        }
+                    });
+
+        }catch (DataAccessException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public int delete(Userdetails2 data) {
+        String sql = "DELETE FROM user_details2 WHERE id=:id";
+        MapSqlParameterSource source = new MapSqlParameterSource();
+        source.addValue("id", data.getId());
+        try {
+            return this.jdbcTemplate.update(sql, source);
+        }catch (DataAccessException e) {
+            return -1;
+        }
+    }
+
+    @Override
+    public int deleteAll() {
+        String sql = "DELETE FROM user_details2;";
+        try {
+            return this.jdbcTemplate.update(sql, new HashMap<String, Object>());
+        }catch (DataAccessException e) {
+            e.printStackTrace();
+            return -1;
+        }
+    }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/user/Userdata.java b/src/main/java/de/ids_mannheim/korap/user/Userdata.java
new file mode 100644
index 0000000..63fac27
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/user/Userdata.java
@@ -0,0 +1,87 @@
+package de.ids_mannheim.korap.user;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import lombok.AccessLevel;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.*;
+
+/**
+ * @author hanl
+ * @date 22/01/2016
+ */
+@Data
+public abstract class Userdata {
+
+    private Integer id;
+    @Getter(AccessLevel.PRIVATE)
+    @Setter(AccessLevel.PRIVATE)
+    private Map<String, Object> fields;
+    @Setter(AccessLevel.PRIVATE)
+    private Integer userID;
+
+    public Userdata(Integer userid) {
+        this.fields = new HashMap<>();
+        this.userID = userid;
+        this.id = -1;
+    }
+
+    public void setData(Map<String, Object> map) throws KustvaktException {
+        Set missing = missing(map);
+        if (!missing.isEmpty())
+            throw new KustvaktException(StatusCodes.MISSING_ARGUMENTS,
+                    missing.toString());
+        this.fields.clear();
+        this.fields.putAll(map);
+    }
+
+    private Set<String> missing(Map<String, Object> map) {
+        Set<String> missing = new HashSet<>();
+        for (String key : requiredFields()) {
+            if (!map.containsKey(key))
+                missing.add(key);
+        }
+        return missing;
+    }
+
+    public int size() {
+        return this.fields.size();
+    }
+
+    public Object get(String key) {
+        return this.fields.get(key);
+    }
+
+    public boolean isValid() {
+        return this.missing(this.fields).isEmpty() && this.userID != -1;
+    }
+
+    public Set<String> keys() {
+        return this.fields.keySet();
+    }
+
+    public Collection<Object> values() {
+        return this.fields.values();
+    }
+
+    public void setData(String data) {
+        Map m = JsonUtils.readSimple(data, Map.class);
+        if (m != null)
+            this.fields.putAll(m);
+    }
+
+    public String data() {
+        return JsonUtils.toJSON(this.fields);
+    }
+
+    public void addField(String key, Object value) {
+        this.fields.put(key, value);
+    }
+
+    public abstract String[] requiredFields();
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/user/Userdetails2.java b/src/main/java/de/ids_mannheim/korap/user/Userdetails2.java
new file mode 100644
index 0000000..141b9b1
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/user/Userdetails2.java
@@ -0,0 +1,20 @@
+package de.ids_mannheim.korap.user;
+
+/**
+ * @author hanl
+ * @date 22/01/2016
+ * persistence issue with query request
+ */
+public class Userdetails2 extends Userdata {
+
+    public Userdetails2(Integer userid) {
+        super(userid);
+    }
+
+    @Override
+    public String[] requiredFields() {
+        return new String[] { Attributes.EMAIL, Attributes.ADDRESS,
+                Attributes.LASTNAME, Attributes.FIRSTNAME };
+    }
+
+}
diff --git a/src/main/resources/db/sqlite/V1__Initial_version.sql b/src/main/resources/db/sqlite/V1__Initial_version.sql
index edbf4ee..c26fce3 100644
--- a/src/main/resources/db/sqlite/V1__Initial_version.sql
+++ b/src/main/resources/db/sqlite/V1__Initial_version.sql
@@ -65,6 +65,18 @@
 on delete cascade
 );
 
+CREATE TABLE IF NOT EXISTS user_details2 (
+id INTEGER PRIMARY KEY AUTOINCREMENT,
+user_id INTEGER UNIQUE NOT NULL,
+data BLOB NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS user_settings2 (
+id INTEGER PRIMARY KEY AUTOINCREMENT,
+user_id INTEGER UNIQUE NOT NULL,
+data BLOB NOT NULL
+);
+
 
 CREATE TABLE IF NOT EXISTS user_queries (
 id INTEGER PRIMARY KEY,
diff --git a/src/test/java/UserdataTest.java b/src/test/java/UserdataTest.java
new file mode 100644
index 0000000..fc9e27e
--- /dev/null
+++ b/src/test/java/UserdataTest.java
@@ -0,0 +1,61 @@
+import de.ids_mannheim.korap.config.BeanConfiguration;
+import de.ids_mannheim.korap.user.KorAPUser;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.user.UserDetailsDao;
+import de.ids_mannheim.korap.user.Userdetails2;
+import org.junit.*;
+
+/**
+ * @author hanl
+ * @date 27/01/2016
+ */
+public class UserdataTest {
+
+    @BeforeClass
+    public static void init() {
+        BeanConfiguration.loadClasspathContext("default-config.xml");
+    }
+
+    @AfterClass
+    public static void drop() {
+        BeanConfiguration.closeApplication();
+    }
+
+    @Before
+    public void clear() {
+        UserDetailsDao dao = new UserDetailsDao(
+                BeanConfiguration.getBeans().getPersistenceClient());
+        assert dao.deleteAll() != -1;
+    }
+
+    @Test
+    public void testDataStore() {
+        User user = new KorAPUser();
+        user.setId(1);
+        UserDetailsDao dao = new UserDetailsDao(
+                BeanConfiguration.getBeans().getPersistenceClient());
+        Userdetails2 d = new Userdetails2(1);
+        d.addField("key_1", "value is a value");
+        assert dao.store(d) != -1;
+    }
+
+    @Test
+    public void testDataGet() {
+        User user = new KorAPUser();
+        user.setId(1);
+        UserDetailsDao dao = new UserDetailsDao(
+                BeanConfiguration.getBeans().getPersistenceClient());
+        Userdetails2 d = new Userdetails2(1);
+        d.addField("key_1", "value is a value");
+        assert dao.store(d) != -1;
+
+        d = dao.get(d.getId());
+        assert d != null;
+        assert "value is a value".equals(d.get("key_1"));
+
+        d = dao.get(user);
+        assert d != null;
+        assert "value is a value".equals(d.get("key_1"));
+    }
+
+}