← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20423: All CRUD operations for app data-store. Missing authorities for checking access to namespaces.

 

Merge authors:
  Stian Sandvold (stian-sandvold)
------------------------------------------------------------
revno: 20423 [merge]
committer: Stian Sandvold <stian.sandvold@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2015-10-01 10:24:46 +0200
message:
  All CRUD operations for app data-store. Missing authorities for checking access to namespaces.
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/DefaultKeyJsonValueService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/hibernate/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/hibernate/HibernateKeyJsonValueStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/keyjsonvalue.hibernate/
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/keyjsonvalue.hibernate/KeyJsonValue.hbm.xml
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java
modified:
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/DefaultRenderService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/RenderService.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== added directory 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue'
=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java	2015-10-01 08:20:29 +0000
@@ -0,0 +1,78 @@
+package org.hisp.dhis.keyjsonvalue;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.hisp.dhis.common.BaseIdentifiableObject;
+
+/**
+ * Created by Stian Sandvold on 27.09.2015.
+ */
+public class KeyJsonValue
+    extends BaseIdentifiableObject
+{
+    private String namespace;
+
+    private String key;
+
+    private String value;
+
+    @JsonProperty
+    public String getKey()
+    {
+        return key;
+    }
+
+    public void setKey( String key )
+    {
+        this.key = key;
+    }
+
+    @JsonProperty
+    public String getNamespace()
+    {
+        return namespace;
+    }
+
+    public void setNamespace( String namespace )
+    {
+        this.namespace = namespace;
+    }
+
+    @JsonProperty
+    public String getValue()
+    {
+        return value;
+    }
+
+    public void setValue( String value )
+    {
+        this.value = value;
+    }
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java	2015-10-01 08:20:29 +0000
@@ -0,0 +1,51 @@
+package org.hisp.dhis.keyjsonvalue;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+/**
+ * Created by Stian Sandvold on 27.09.2015.
+ */
+public interface KeyJsonValueService
+{
+    List<String> getNamespaces();
+
+    List<String> getKeysInNamespace( String namespace );
+
+    void deleteNamespace( String namespace );
+
+    KeyJsonValue getKeyJsonValue( String namespace, String key );
+
+    int addKeyJsonValue( KeyJsonValue keyJsonValue );
+
+    void updateKeyJsonValue( KeyJsonValue keyJsonValue );
+
+    void deleteKeyJsonValue( KeyJsonValue keyJsonValue );
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.java	2015-10-01 08:20:29 +0000
@@ -0,0 +1,50 @@
+package org.hisp.dhis.keyjsonvalue;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hisp.dhis.common.GenericIdentifiableObjectStore;
+
+import java.util.List;
+
+/**
+ * Created by Stian Sandvold on 27.09.2015.
+ */
+public interface KeyJsonValueStore
+    extends GenericIdentifiableObjectStore<KeyJsonValue>
+{
+
+    List<String> getNamespaces();
+
+    List<String> getKeysInNamespace( String namespace );
+
+    void deleteKeysInNamespace( String namespace );
+
+    KeyJsonValue getKeyJsonValue( String namespace, String key );
+
+}

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/DefaultKeyJsonValueService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/DefaultKeyJsonValueService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/DefaultKeyJsonValueService.java	2015-10-01 08:20:29 +0000
@@ -0,0 +1,91 @@
+package org.hisp.dhis.keyjsonvalue;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * Created by Stian Sandvold on 27.09.2015.
+ */
+@Transactional
+public class DefaultKeyJsonValueService
+    implements KeyJsonValueService
+{
+
+    private KeyJsonValueStore keyJsonValueStore;
+
+    public void setKeyJsonValueStore( KeyJsonValueStore keyJsonValueStore )
+    {
+        this.keyJsonValueStore = keyJsonValueStore;
+    }
+
+    @Override
+    public List<String> getNamespaces()
+    {
+        return keyJsonValueStore.getNamespaces();
+    }
+
+    @Override
+    public List<String> getKeysInNamespace( String namespace )
+    {
+        return keyJsonValueStore.getKeysInNamespace( namespace );
+    }
+
+    @Override
+    public void deleteNamespace( String namespace )
+    {
+        keyJsonValueStore.deleteKeysInNamespace( namespace );
+    }
+
+    @Override
+    public KeyJsonValue getKeyJsonValue( String namespace, String key )
+    {
+        return keyJsonValueStore.getKeyJsonValue( namespace, key );
+    }
+
+    @Override
+    public int addKeyJsonValue( KeyJsonValue keyJsonValue )
+    {
+        return keyJsonValueStore.save( keyJsonValue );
+    }
+
+    @Override
+    public void updateKeyJsonValue( KeyJsonValue keyJsonValue )
+    {
+        keyJsonValueStore.save( keyJsonValue );
+    }
+
+    @Override
+    public void deleteKeyJsonValue( KeyJsonValue keyJsonValue )
+    {
+        keyJsonValueStore.delete( keyJsonValue );
+    }
+}

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/hibernate'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/hibernate/HibernateKeyJsonValueStore.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/hibernate/HibernateKeyJsonValueStore.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/keyjsonvalue/hibernate/HibernateKeyJsonValueStore.java	2015-10-01 08:20:29 +0000
@@ -0,0 +1,71 @@
+package org.hisp.dhis.keyjsonvalue.hibernate;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hibernate.criterion.Restrictions;
+import org.hisp.dhis.common.hibernate.HibernateIdentifiableObjectStore;
+import org.hisp.dhis.keyjsonvalue.KeyJsonValue;
+import org.hisp.dhis.keyjsonvalue.KeyJsonValueStore;
+
+import java.util.List;
+
+/**
+ * Created by Stian Sandvold on 27.09.2015.
+ */
+public class HibernateKeyJsonValueStore
+    extends HibernateIdentifiableObjectStore<KeyJsonValue>
+    implements KeyJsonValueStore
+{
+    @Override
+    public List<String> getNamespaces()
+    {
+        return getQuery( "SELECT distinct namespace FROM org.hisp.dhis.keyjsonvalue.KeyJsonValue" ).list();
+    }
+
+    @Override
+    public List<String> getKeysInNamespace( String namespace )
+    {
+        return getQuery(
+            "SELECT distinct key FROM org.hisp.dhis.keyjsonvalue.KeyJsonValue WHERE namespace LIKE '" + namespace +
+                "'" ).list();
+    }
+
+    @Override
+    public void deleteKeysInNamespace( String namespace )
+    {
+        getCriteria( Restrictions.eq( "namespace", namespace ) ).list().forEach( o -> delete( (KeyJsonValue) o ) );
+    }
+
+    @Override
+    public KeyJsonValue getKeyJsonValue( String namespace, String key )
+    {
+        return (KeyJsonValue) getCriteria( Restrictions.eq( "namespace", namespace ), Restrictions.eq( "key", key ) )
+            .uniqueResult();
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2015-09-28 02:56:57 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2015-09-29 12:48:45 +0000
@@ -578,6 +578,11 @@
     <property name="locationManager" ref="locationManager" />
   </bean>
 
+  <bean id="org.hisp.dhis.keyjsonvalue.KeyJsonValueStore" class="org.hisp.dhis.keyjsonvalue.hibernate.HibernateKeyJsonValueStore">
+      <property name="clazz" value="org.hisp.dhis.keyjsonvalue.KeyJsonValue" />
+      <property name="sessionFactory" ref="sessionFactory" />
+  </bean>
+
   <!-- Service definitions -->
 
   <bean id="org.hisp.dhis.fileresource.FileResourceService" class="org.hisp.dhis.fileresource.DefaultFileResourceService">
@@ -1240,6 +1245,9 @@
     <property name="eventChartStore" ref="org.hisp.dhis.eventchart.EventChartStore" />
   </bean>
 
+  <bean id="org.hisp.dhis.keyjsonvalue.KeyJsonValueService" class="org.hisp.dhis.keyjsonvalue.DefaultKeyJsonValueService">
+      <property name="keyJsonValueStore" ref="org.hisp.dhis.keyjsonvalue.KeyJsonValueStore" />
+  </bean>
   <!-- SMS services -->
 
   <bean id="org.hisp.dhis.sms.command.SMSCommandService" class="org.hisp.dhis.sms.command.DefaultSMSCommandService">

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/keyjsonvalue.hibernate'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/keyjsonvalue.hibernate/KeyJsonValue.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/keyjsonvalue.hibernate/KeyJsonValue.hbm.xml	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/keyjsonvalue.hibernate/KeyJsonValue.hbm.xml	2015-09-29 12:48:14 +0000
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd";
+        [<!ENTITY identifiableProperties SYSTEM "classpath://org/hisp/dhis/common/identifiableProperties.hbm">]>
+
+<hibernate-mapping>
+    <class name="org.hisp.dhis.keyjsonvalue.KeyJsonValue" table="keyjsonvalue">
+
+        <cache usage="read-write"/>
+
+        <id name="id" column="keyjsonvalueid">
+            <generator class="native"/>
+        </id>
+
+        &identifiableProperties;
+
+        <property name="namespace" column="namespace" type="string" length="255" not-null="true" unique-key="keyjsonvalue_unique_key_in_namespace"/>
+
+        <property name="key" column="key" type="string" length="255" not-null="true" unique-key="keyjsonvalue_unique_key_in_namespace" />
+
+        <property name="value" column="value" type="text"/>
+
+    </class>
+</hibernate-mapping>

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/DefaultRenderService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/DefaultRenderService.java	2015-03-23 05:42:24 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/DefaultRenderService.java	2015-09-30 19:20:36 +0000
@@ -30,10 +30,7 @@
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.util.JSONPObject;
 import com.fasterxml.jackson.dataformat.xml.XmlMapper;
 import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
@@ -48,7 +45,8 @@
  *
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
  */
-public class DefaultRenderService implements RenderService
+public class DefaultRenderService
+    implements RenderService
 {
     private final ObjectMapper jsonMapper = new ObjectMapper();
 
@@ -64,19 +62,22 @@
     //--------------------------------------------------------------------------
 
     @Override
-    public void toJson( OutputStream output, Object value ) throws IOException
+    public void toJson( OutputStream output, Object value )
+        throws IOException
     {
         jsonMapper.writeValue( output, value );
     }
 
     @Override
-    public void toJson( OutputStream output, Object value, Class<?> klass ) throws IOException
+    public void toJson( OutputStream output, Object value, Class<?> klass )
+        throws IOException
     {
         jsonMapper.writerWithView( klass ).writeValue( output, value );
     }
 
     @Override
-    public void toJsonP( OutputStream output, Object value, String callback ) throws IOException
+    public void toJsonP( OutputStream output, Object value, String callback )
+        throws IOException
     {
         if ( StringUtils.isEmpty( callback ) )
         {
@@ -87,7 +88,8 @@
     }
 
     @Override
-    public void toJsonP( OutputStream output, Object value, Class<?> klass, String callback ) throws IOException
+    public void toJsonP( OutputStream output, Object value, Class<?> klass, String callback )
+        throws IOException
     {
         if ( StringUtils.isEmpty( callback ) )
         {
@@ -98,37 +100,43 @@
     }
 
     @Override
-    public <T> T fromJson( InputStream input, Class<T> klass ) throws IOException
-    {
-        return jsonMapper.readValue( input, klass );
-    }
-
-    @Override
-    public <T> T fromJson( String input, Class<T> klass ) throws IOException
-    {
-        return jsonMapper.readValue( input, klass );
-    }
-
-    @Override
-    public <T> void toXml( OutputStream output, T value ) throws IOException
+    public <T> T fromJson( InputStream input, Class<T> klass )
+        throws IOException
+    {
+        return jsonMapper.readValue( input, klass );
+    }
+
+    @Override
+    public <T> T fromJson( String input, Class<T> klass )
+        throws IOException
+    {
+        return jsonMapper.readValue( input, klass );
+    }
+
+    @Override
+    public <T> void toXml( OutputStream output, T value )
+        throws IOException
     {
         xmlMapper.writeValue( output, value );
     }
 
     @Override
-    public <T> void toXml( OutputStream output, T value, Class<?> klass ) throws IOException
+    public <T> void toXml( OutputStream output, T value, Class<?> klass )
+        throws IOException
     {
         xmlMapper.writerWithView( klass ).writeValue( output, value );
     }
 
     @Override
-    public <T> T fromXml( InputStream input, Class<T> klass ) throws IOException
+    public <T> T fromXml( InputStream input, Class<T> klass )
+        throws IOException
     {
         return xmlMapper.readValue( input, klass );
     }
 
     @Override
-    public <T> T fromXml( String input, Class<T> klass ) throws IOException
+    public <T> T fromXml( String input, Class<T> klass )
+        throws IOException
     {
         return xmlMapper.readValue( input, klass );
     }
@@ -149,7 +157,7 @@
 
     private void configureObjectMappers()
     {
-        ObjectMapper[] objectMappers = new ObjectMapper[]{ jsonMapper, xmlMapper };
+        ObjectMapper[] objectMappers = new ObjectMapper[] { jsonMapper, xmlMapper };
 
         for ( ObjectMapper objectMapper : objectMappers )
         {
@@ -174,4 +182,24 @@
         jsonMapper.getFactory().enable( JsonGenerator.Feature.QUOTE_FIELD_NAMES );
         xmlMapper.configure( ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true );
     }
+
+    public boolean isValidJson( String json )
+        throws IOException
+    {
+        try
+        {
+            jsonMapper.readValue( json, Object.class );
+        }
+        catch ( com.fasterxml.jackson.core.JsonParseException e )
+        {
+            return false;
+        }
+        catch ( JsonMappingException e )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/RenderService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/RenderService.java	2015-03-23 05:42:24 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/render/RenderService.java	2015-09-29 16:55:27 +0000
@@ -56,4 +56,6 @@
     <T> T fromXml( InputStream input, Class<T> klass ) throws IOException;
 
     <T> T fromXml( String input, Class<T> klass ) throws IOException;
+
+    boolean isValidJson(String json) throws IOException;
 }

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java	2015-10-01 08:20:29 +0000
@@ -0,0 +1,208 @@
+package org.hisp.dhis.webapi.controller;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hisp.dhis.dxf2.render.RenderService;
+import org.hisp.dhis.dxf2.webmessage.WebMessageException;
+import org.hisp.dhis.keyjsonvalue.KeyJsonValue;
+import org.hisp.dhis.keyjsonvalue.KeyJsonValueService;
+import org.hisp.dhis.webapi.utils.WebMessageUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Created by Stian Sandvold on 27.09.2015.
+ */
+@Controller
+@RequestMapping( "/dataStore" )
+public class KeyJsonValueController
+{
+    @Autowired
+    private KeyJsonValueService keyJsonValueService;
+
+    @Autowired
+    private RenderService renderService;
+
+    @RequestMapping( value = "", method = RequestMethod.GET, produces = "application/json" )
+    public void getNamespaces(
+        HttpServletResponse response
+    )
+        throws IOException
+    {
+        renderService.toJson( response.getOutputStream(), keyJsonValueService.getNamespaces() );
+    }
+
+    @RequestMapping( value = "/{namespace}", method = RequestMethod.GET, produces = "application/json" )
+    public void getKeysInNamespace(
+        @PathVariable String namespace,
+        HttpServletResponse response
+    )
+        throws IOException, WebMessageException
+    {
+
+        if ( !keyJsonValueService.getNamespaces().contains( namespace ) )
+        {
+            throw new WebMessageException(
+                WebMessageUtils.notFound( "The namespace '" + namespace + "' was not found." ) );
+        }
+
+        renderService.toJson( response.getOutputStream(), keyJsonValueService.getKeysInNamespace( namespace ) );
+    }
+
+    @RequestMapping( value = "/{namespace}", method = RequestMethod.DELETE )
+    public void deleteNamespace(
+        @PathVariable String namespace,
+        HttpServletResponse response
+    )
+        throws WebMessageException
+    {
+
+        if ( !keyJsonValueService.getNamespaces().contains( namespace ) )
+        {
+            throw new WebMessageException(
+                WebMessageUtils.notFound( "The namespace '" + namespace + "' was not found." ) );
+        }
+
+        keyJsonValueService.deleteNamespace( namespace );
+
+        throw new WebMessageException( WebMessageUtils.ok( "Namespace '" + namespace + "' deleted." ) );
+    }
+
+    @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.GET, produces = "application/json" )
+    public void getKeyJsonValue(
+        @PathVariable String namespace,
+        @PathVariable String key,
+        HttpServletResponse response )
+        throws IOException, WebMessageException
+    {
+        KeyJsonValue keyJsonValue = keyJsonValueService.getKeyJsonValue( namespace, key );
+
+        if ( keyJsonValue == null )
+        {
+            throw new WebMessageException( WebMessageUtils
+                .notFound( "The key '" + key + "' was not found in the namespace '" + namespace + "'." ) );
+        }
+
+        renderService.toJson( response.getOutputStream(), keyJsonValue );
+    }
+
+    @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.POST, produces = "application/json", consumes = "application/json" )
+    public void addKey(
+        @PathVariable String namespace,
+        @PathVariable String key,
+        @RequestBody String body,
+        HttpServletResponse response )
+        throws IOException, WebMessageException
+    {
+        // Check uniqueness of the key
+        if ( keyJsonValueService.getKeyJsonValue( namespace, key ) != null )
+        {
+            throw new WebMessageException( WebMessageUtils
+                .conflict( "The key '" + key + "' already exists on the namespace '" + namespace + "'." ) );
+        }
+
+        // Check json validity
+        if ( !renderService.isValidJson( body ) )
+        {
+            throw new WebMessageException( WebMessageUtils.badRequest( "The data is not valid JSON." ) );
+        }
+
+        KeyJsonValue keyJsonValue = new KeyJsonValue();
+
+        keyJsonValue.setKey( key );
+        keyJsonValue.setNamespace( namespace );
+        keyJsonValue.setValue( body );
+
+        keyJsonValueService.addKeyJsonValue( keyJsonValue );
+
+        response.setStatus( 201 );
+        renderService.toJson( response.getOutputStream(), keyJsonValue );
+    }
+
+    @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.PUT, produces = "application/json", consumes = "application/json" )
+    public void updateKeyJsonValue(
+        @PathVariable String namespace,
+        @PathVariable String key,
+        @RequestBody String body,
+        HttpServletRequest request,
+        HttpServletResponse response
+    )
+        throws WebMessageException, IOException
+    {
+        KeyJsonValue keyJsonValue = keyJsonValueService.getKeyJsonValue( namespace, key );
+
+        if ( keyJsonValue == null )
+        {
+            throw new WebMessageException( WebMessageUtils
+                .notFound( "The key '" + key + "' was not found in the namespace '" + namespace + "'." ) );
+        }
+
+        // Check json validity
+        if ( !renderService.isValidJson( body ) )
+        {
+            throw new WebMessageException( WebMessageUtils.badRequest( "The data is not valid JSON." ) );
+        }
+
+        keyJsonValue.setValue( body );
+
+        keyJsonValueService.updateKeyJsonValue( keyJsonValue );
+
+        renderService.toJson( response.getOutputStream(), keyJsonValue );
+    }
+
+    @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.DELETE, produces = "application/json" )
+    public void deleteKeyJsonValue(
+        @PathVariable String namespace,
+        @PathVariable String key,
+        HttpServletResponse response
+    )
+        throws WebMessageException
+    {
+        KeyJsonValue keyJsonValue = keyJsonValueService.getKeyJsonValue( namespace, key );
+
+        if ( keyJsonValue == null )
+        {
+            throw new WebMessageException( WebMessageUtils
+                .notFound( "The key '" + key + "' was not found in the namespace '" + namespace + "'." ) );
+        }
+
+        keyJsonValueService.deleteKeyJsonValue( keyJsonValue );
+
+        throw new WebMessageException(
+            WebMessageUtils.ok( "Key '" + key + "' deleted from namespace '" + namespace + "'." ) );
+    }
+}