You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/07/24 07:43:28 UTC

[4/4] git commit: ISIS-468, ISIS-469: change to @MemberGroupLayout, downloading of layouts

ISIS-468,ISIS-469: change to @MemberGroupLayout, downloading of layouts

- @MemberGroupLayout#columnSpans is now a simple int[]
- changes suffix from isis.properties to layout.properties
- changed suffix from isis.json to layout.json
- added guard in case @MemberGroupLayout refers to non-existent groups
- fixed download code of zip of xxx.layout.json (and put into directories following package of each class)


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

Branch: refs/heads/master
Commit: f38fdb92941172eabb12e0943509f239e6d5925f
Parents: 51690aa
Author: Dan Haywood <da...@apache.org>
Authored: Wed Jul 24 06:42:36 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Wed Jul 24 06:42:36 2013 +0100

----------------------------------------------------------------------
 .../applib/annotation/MemberGroupLayout.java    | 146 ++++++++++---------
 .../MemberGroupLayoutColumnSpansTest.java       |  14 +-
 .../json/LayoutMetadataReaderFromJson.java      |  26 ++--
 .../LayoutMetadataReaderFromPropertyFile.java   |   2 +-
 .../DeveloperUtilitiesServiceDefault.java       |  25 ++--
 .../MemberGroupLayoutFacetAbstract.java         |   2 +-
 .../MemberGroupLayoutFacetAnnotation.java       |   3 +-
 .../LayoutMetadataReaderFromJsonTest_read.java  |   2 +-
 .../MemberGroupLayoutFacetFactoryTest.java      |   6 +-
 ...LayoutFacetPropertiesTest_asColumnSpans.java |  10 +-
 .../json/ExampleDomainObject.layout.json        |  79 ++++++++++
 .../json/ExampleDomainObject.layout.properties  |  80 ++++++++++
 .../json/ExampleDomainObject.isis.json          |  79 ----------
 .../json/ExampleDomainObject.isis.properties    |  80 ----------
 .../src/main/java/dom/todo/ToDoItem.isis.json   |  79 ----------
 .../main/java/dom/todo/ToDoItem.isis.properties |  76 ----------
 .../dom/src/main/java/dom/todo/ToDoItem.java    |   1 +
 .../src/main/java/dom/todo/ToDoItem.layout.json |  79 ++++++++++
 18 files changed, 358 insertions(+), 431 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/applib/src/main/java/org/apache/isis/applib/annotation/MemberGroupLayout.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/MemberGroupLayout.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/MemberGroupLayout.java
index 60a097e..b456e52 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/MemberGroupLayout.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/MemberGroupLayout.java
@@ -24,9 +24,19 @@ import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.annotation.MemberGroupLayout.ColumnSpans;
+
 /**
  * A successor to {@link MemberGroups}, specifying the (groups of) members in a page,
  * column by column. 
@@ -51,81 +61,46 @@ public @interface MemberGroupLayout {
 
     /**
      * The relative widths of the columns of members.
-     * 
-     * <p>
-     * Each value of this enum is in the form <tt>_X_Y_Z_W</tt>.  The 
-     * <tt>X</tt>, <tt>Y</tt> and <tt>Z</tt>
-     * indicate the relative widths of (up to) three property columns,
-     * while <tt>W</tt> indicates the relative width of the collection column.
      */
-    public enum ColumnSpans {
-        // two column, with collections
-        _2_0_0_10,
-        _3_0_0_9,
-        _4_0_0_8,
-        _5_0_0_7,
-        _6_0_0_6,
-        
-        // three column, with collections
-        _2_2_0_8,
-        _2_3_0_7,
-        _2_4_0_6,
-        _2_5_0_5,
-        _2_6_0_4,
-        
-        _3_3_0_6,
-        _3_4_0_5,
-        _3_5_0_4,
-        _3_6_0_3,
-        
-        _4_4_0_4,
-        
-        // two column, suppress collections
-        _2_0_10_0,
-        _3_0_9_0,
-        _4_0_8_0,
-        _5_0_7_0,
-        _6_0_6_0,
-        
-        // three column, suppress collections
-        _2_2_8_0,
-        _2_3_7_0,
-        _2_4_6_0,
-        _2_5_5_0,
-        _2_6_4_0,
-        
-        _3_3_6_0,
-        _3_4_5_0,
-        _3_5_4_0,
-        _3_6_3_0,
-        
-        _4_4_4_0,
-        _4_5_3_0,
-        _4_6_2_0,
-        ;
+    public static class ColumnSpans {
         
         private final int left;
         private final int middle;
         private final int right;
         private final int collections;
-                
-        private ColumnSpans() {
-            final Pattern namePattern = Pattern.compile("^_(\\d+)_(\\d+)_(\\d+)_(\\d+)$");
-            final String name = name();
-            Matcher matcher = namePattern.matcher(name);
-            if(!matcher.matches()) {
-                // call to matches is required; Matcher is a state machine
-                throw new IllegalArgumentException("enum constant's name must match " + namePattern.pattern());
-            } 
-            
-            this.left = parseGroup(matcher, 1);
-            this.middle = parseGroup(matcher, 2);
-            this.right = parseGroup(matcher, 3);
-            this.collections = parseGroup(matcher, 4);
+        
+        public static ColumnSpans valueOf(String str) {
+            final Iterable<String> split = Splitter.on(",").split(str);
+            try {
+                final List<Integer> list = Lists.newArrayList(Iterables.transform(split, new Function<String,Integer>() {
+                    @Override
+                    public Integer apply(String input) {
+                        return Integer.parseInt(input);
+                    }
+                }));
+                return asSpans(list);
+            } catch(RuntimeException ex) {
+                return null;
+            }
         }
-
-        private static int parseGroup(Matcher matcher, final int group) {
-            return Integer.parseInt(matcher.group(group));
+        public static ColumnSpans asSpans(int... columnSpans) {
+            List<Integer> list = Lists.<Integer>newArrayList();
+            for (int i : columnSpans) {
+                list.add(i);
+            }
+            return asSpans(list);
+        }
+        private static ColumnSpans asSpans(List<Integer> list) {
+            return new ColumnSpans(list);
+        }
+        private ColumnSpans(List<Integer> list) {
+            this.left = getElse(list,0,4);
+            this.middle = getElse(list,1,0);
+            this.right = getElse(list,2,0);
+            this.collections = getElse(list,3,8);
+        }
+        private static int getElse(List<Integer> list, int i, int dflt) {
+            return list != null && list.size() > i? list.get(i): dflt;
         }
 
         public int getLeft() {
@@ -140,7 +115,38 @@ public @interface MemberGroupLayout {
         public int getCollections() {
             return collections;
         }
-        
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + collections;
+            result = prime * result + left;
+            result = prime * result + middle;
+            result = prime * result + right;
+            return result;
+        }
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            ColumnSpans other = (ColumnSpans) obj;
+            if (collections != other.collections)
+                return false;
+            if (left != other.left)
+                return false;
+            if (middle != other.middle)
+                return false;
+            if (right != other.right)
+                return false;
+            return true;
+        }
+        public String name() {
+            return String.format("[%d,%d,%d,%d]", left, middle, right, collections);
+        }
     }
 
     /**
@@ -149,7 +155,7 @@ public @interface MemberGroupLayout {
      * <p>
      * The sum of the spans is always 12.
      */
-    ColumnSpans columnSpans() default ColumnSpans._4_0_0_8;
+    int[] columnSpans() default {4,0,0,8};
 
     /**
      * Order of groups of properties as they appear in the left-most column of a webpage,

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/applib/src/test/java/org/apache/isis/applib/annotation/MemberGroupLayoutColumnSpansTest.java
----------------------------------------------------------------------
diff --git a/core/applib/src/test/java/org/apache/isis/applib/annotation/MemberGroupLayoutColumnSpansTest.java b/core/applib/src/test/java/org/apache/isis/applib/annotation/MemberGroupLayoutColumnSpansTest.java
index f079480..07a4136 100644
--- a/core/applib/src/test/java/org/apache/isis/applib/annotation/MemberGroupLayoutColumnSpansTest.java
+++ b/core/applib/src/test/java/org/apache/isis/applib/annotation/MemberGroupLayoutColumnSpansTest.java
@@ -24,14 +24,18 @@ import static org.junit.Assert.assertThat;
 
 import org.junit.Test;
 
+import org.apache.isis.applib.annotation.MemberGroupLayout.ColumnSpans;
+
 public class MemberGroupLayoutColumnSpansTest {
 
     @Test
-    public void regex() {
-        assertThat(MemberGroupLayout.ColumnSpans._2_3_0_7.getLeft(), is(2));
-        assertThat(MemberGroupLayout.ColumnSpans._2_3_0_7.getMiddle(), is(3));
-        assertThat(MemberGroupLayout.ColumnSpans._2_3_0_7.getRight(), is(0));
-        assertThat(MemberGroupLayout.ColumnSpans._2_3_0_7.getCollections(), is(7));
+    public void asSpans() {
+        final ColumnSpans spans = MemberGroupLayout.ColumnSpans.asSpans(2,3,0,7);
+        
+        assertThat(spans.getLeft(), is(2));
+        assertThat(spans.getMiddle(), is(3));
+        assertThat(spans.getRight(), is(0));
+        assertThat(spans.getCollections(), is(7));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
index b8f49f5..229efeb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
@@ -23,7 +23,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
+import com.google.common.base.Function;
 import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.gson.Gson;
@@ -58,7 +60,7 @@ public class LayoutMetadataReaderFromJson implements LayoutMetadataReader {
         try {
             metadata = readMetadata(domainClass);
         } catch (Exception e) {
-            throw new ReaderException("Failed to locate/parse " + domainClass.getName() + ".isis.json file (" + e.getMessage() + ")", e);
+            throw new ReaderException("Failed to locate/parse " + domainClass.getName() + ".layout.json file (" + e.getMessage() + ")", e);
         }
         if(metadata.getColumns() == null || metadata.getColumns().size() != 4) {
             throw new ReaderException("JSON metadata must have precisely 4 columns (prop/prop/prop/coll)");
@@ -80,18 +82,11 @@ public class LayoutMetadataReaderFromJson implements LayoutMetadataReader {
 
     private static void setMemberGroupLayoutColumnSpans(LayoutMetadata metadata, final Properties props) {
         final List<ColumnRepr> columns = metadata.getColumns();
-        final StringBuilder buf = new StringBuilder();
-        for (final ColumnRepr columnRepr : columns) {
-            buf.append("_");
-            buf.append(columnRepr.span);
-        }
-        final String columnSpansStr = buf.toString();
-        try {
-            ColumnSpans.valueOf(columnSpansStr);
-        } catch(IllegalArgumentException ex) {
-            throw new ReaderException(
-                "Invalid values for column spans '" + columnSpansStr + "'; when concatenated must be value of the ColumnSpans enum", ex);
-        }
+        final String columnSpansStr = Joiner.on(",").join(Iterables.transform(columns, new Function<ColumnRepr,Integer>(){
+            @Override
+            public Integer apply(ColumnRepr input) {
+                return input.span;
+            }}));
         props.setProperty("memberGroupLayout.columnSpans", columnSpansStr);
     }
 
@@ -173,7 +168,7 @@ public class LayoutMetadataReaderFromJson implements LayoutMetadataReader {
     // //////////////////////////////////////
 
     private LayoutMetadata readMetadata(Class<?> domainClass) throws IOException {
-        final String content = ResourceUtil.contentOf(domainClass, ".isis.json");
+        final String content = ResourceUtil.contentOf(domainClass, ".layout.json");
         return readMetadata(content);
     }
 
@@ -232,6 +227,9 @@ public class LayoutMetadataReaderFromJson implements LayoutMetadataReader {
             columnRepr.memberGroups.put(groupName, memberGroupRepr);
             final List<ObjectAssociation> associationsInGroup = associationsByGroup.get(groupName);
             memberGroupRepr.members = Maps.newLinkedHashMap();
+            if(associationsInGroup == null) {
+                continue;
+            }
             for (ObjectAssociation assoc : associationsInGroup) {
                 final MemberRepr memberRepr = newMemberRepr(objectSpec, assoc);
                 memberGroupRepr.members.put(assoc.getId(), memberRepr);

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
index 5bfd1d7..3906dcc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
@@ -25,7 +25,7 @@ public class LayoutMetadataReaderFromPropertyFile implements LayoutMetadataReade
 
     @Override
     public Properties asProperties(Class<?> domainClass) throws ReaderException {
-        return ResourceUtil.propertiesFor(domainClass, ".isis.properties");
+        return ResourceUtil.propertiesFor(domainClass, ".layout.properties");
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
index 79981b7..6100005 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.services.devutils;
 
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.util.ArrayList;
@@ -166,7 +167,7 @@ public class DeveloperUtilitiesServiceDefault implements DeveloperUtilitiesServi
         final LayoutMetadataReaderFromJson propertiesReader = new LayoutMetadataReaderFromJson();
         final String json = propertiesReader.asJson(objectSpec);
         
-        return new Clob(objectSpec.getShortIdentifier() +".isis.json", mimeTypeApplicationJson, json);
+        return new Clob(objectSpec.getShortIdentifier() +".layout.json", mimeTypeApplicationJson, json);
     }
 
     // //////////////////////////////////////
@@ -188,8 +189,10 @@ public class DeveloperUtilitiesServiceDefault implements DeveloperUtilitiesServi
             ZipOutputStream zos = new ZipOutputStream(baos);
             OutputStreamWriter writer = new OutputStreamWriter(zos);
             for (ObjectSpecification objectSpec : domainObjectSpecs) {
-                zos.putNextEntry(new ZipEntry(objectSpec.getFullIdentifier()));
+                zos.putNextEntry(new ZipEntry(zipEntryNameFor(objectSpec)));
                 writer.write(propertiesReader.asJson(objectSpec));
+                writer.flush();
+                zos.closeEntry();
             }
             writer.close();
             return new Blob("layouts.zip", mimeTypeApplicationZip, baos.toByteArray());
@@ -198,22 +201,12 @@ public class DeveloperUtilitiesServiceDefault implements DeveloperUtilitiesServi
         }
     }
 
-
-    // //////////////////////////////////////
-
-    private List<String> sortedSpecNames() {
-        final Collection<ObjectSpecification> allSpecifications = specificationLoader.allSpecifications();
-        final Iterable<String> classNames = Iterables.transform(allSpecifications, new Function<ObjectSpecification, String>() {
-            @Override
-            public String apply(ObjectSpecification input) {
-                return input.getFullIdentifier();
-            }
-        });
-        final List<String> classNamesList = Lists.newArrayList(classNames);
-        Collections.sort(classNamesList);
-        return classNamesList;
+    private static String zipEntryNameFor(ObjectSpecification objectSpec) {
+        final String fqn = objectSpec.getFullIdentifier();
+        return fqn.replace(".", File.separator)+".layout.json";
     }
 
+
     // //////////////////////////////////////
 
     private SpecificationLoaderSpi specificationLoader;

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAbstract.java
index 8bb9299..5cd4884 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAbstract.java
@@ -54,7 +54,7 @@ public abstract class MemberGroupLayoutFacetAbstract extends FacetAbstract imple
             final List<String> left, final List<String> middle, final List<String> right, 
             FacetHolder holder) {
         super(type(), holder, Derivation.NOT_DERIVED);
-        this.columns = columns != null? columns: ColumnSpans._4_0_0_8;
+        this.columns = columns != null? columns: ColumnSpans.asSpans(4,0,0,8);
         this.left = left;
         this.middle = middle;
         this.right = right;

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAnnotation.java
index 6255264..8198e90 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetAnnotation.java
@@ -20,6 +20,7 @@
 package org.apache.isis.core.progmodel.facets.object.membergroups;
 
 import org.apache.isis.applib.annotation.MemberGroupLayout;
+import org.apache.isis.applib.annotation.MemberGroupLayout.ColumnSpans;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 
 public class MemberGroupLayoutFacetAnnotation extends MemberGroupLayoutFacetAbstract {
@@ -27,7 +28,7 @@ public class MemberGroupLayoutFacetAnnotation extends MemberGroupLayoutFacetAbst
     public MemberGroupLayoutFacetAnnotation(
             final MemberGroupLayout memberGroupLayout,
             FacetHolder holder) {
-        super(memberGroupLayout.columnSpans(), 
+        super(ColumnSpans.asSpans(memberGroupLayout.columnSpans()), 
                 asListWithDefaultGroup(memberGroupLayout.left()), 
                 asList(memberGroupLayout.middle()), 
                 asList(memberGroupLayout.right()), 

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJsonTest_read.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJsonTest_read.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJsonTest_read.java
index 36e63ec..e3e1d2b 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJsonTest_read.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJsonTest_read.java
@@ -43,7 +43,7 @@ public class LayoutMetadataReaderFromJsonTest_read {
         final Properties properties = reader.asProperties(ExampleDomainObject.class);
         assertThat(properties, is(not(nullValue())));
         
-        final Properties expectedProperties = ResourceUtil.propertiesFor(ExampleDomainObject.class, ".isis.properties");
+        final Properties expectedProperties = ResourceUtil.propertiesFor(ExampleDomainObject.class, ".layout.properties");
         for (Object expectedKey : expectedProperties.keySet()) {
             final String key = (String) expectedKey;
             final String expectedValue = expectedProperties.getProperty(key);

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetFactoryTest.java
index b5f7ddb..c030c68 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetFactoryTest.java
@@ -51,7 +51,7 @@ public class MemberGroupLayoutFacetFactoryTest extends AbstractFacetFactoryTest
             left={"General","Foo", "Bar"}, 
             middle={"Baz", "Boz"}, 
             right={"Flip", "Flop"}, 
-            columnSpans=ColumnSpans._2_4_6_0)
+            columnSpans={2,4,6,0})
     public static class ClassWithMemberGroupLayoutAnnotation {
         
     }
@@ -59,7 +59,7 @@ public class MemberGroupLayoutFacetFactoryTest extends AbstractFacetFactoryTest
     @MemberGroupLayout(
             left={"General","Foo", "Bar"}, 
             middle={"Baz", "Boz"}, 
-            columnSpans=ColumnSpans._2_4_0_6)
+            columnSpans={2,4,0,6})
     @MemberGroups({"General","Foo", "Bar"})
     public static class ClassWithMemberGroupLayoutAndMemberGroupsAnnotation {
         
@@ -92,7 +92,7 @@ public class MemberGroupLayoutFacetFactoryTest extends AbstractFacetFactoryTest
         assertEquals(Arrays.asList("General", "Foo", "Bar"), leftNames);
         assertEquals(Arrays.asList("Baz", "Boz"), middleNames);
         assertEquals(Arrays.asList("Flip", "Flop"), rightNames);
-        assertEquals(ColumnSpans._2_4_6_0, columnSpans);
+        assertEquals(ColumnSpans.asSpans(2,4,6,0), columnSpans);
 
         assertNoMethodsRemoved();
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetPropertiesTest_asColumnSpans.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetPropertiesTest_asColumnSpans.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetPropertiesTest_asColumnSpans.java
index 758c66c..c31c845 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetPropertiesTest_asColumnSpans.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/object/membergroups/MemberGroupLayoutFacetPropertiesTest_asColumnSpans.java
@@ -52,19 +52,19 @@ public class MemberGroupLayoutFacetPropertiesTest_asColumnSpans {
 
     @Test
     public void happyCase() throws Exception {
-        properties.put("columnSpans", "_2_3_0_7");
-        assertThat(MemberGroupLayoutFacetProperties.asColumnSpans(properties), is(ColumnSpans._2_3_0_7));
+        properties.put("columnSpans", "2,3,0,7");
+        assertThat(MemberGroupLayoutFacetProperties.asColumnSpans(properties), is(ColumnSpans.asSpans(2,3,0,7)));
     }
     
     @Test
     public void trimmed() throws Exception {
-        properties.put("columnSpans", " _2_3_0_7 ");
-        assertThat(MemberGroupLayoutFacetProperties.asColumnSpans(properties), is(ColumnSpans._2_3_0_7));
+        properties.put("columnSpans", " 2,3,0,7 ");
+        assertThat(MemberGroupLayoutFacetProperties.asColumnSpans(properties), is(ColumnSpans.asSpans(2,3,0,7)));
     }
     
     @Test
     public void invalid() throws Exception {
-        properties.put("columnSpans", "_x_x_x_x");
+        properties.put("columnSpans", "x,x,x,x");
         assertThat(MemberGroupLayoutFacetProperties.asColumnSpans(properties), is(nullValue()));
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.json
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.json b/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.json
new file mode 100644
index 0000000..01debb1
--- /dev/null
+++ b/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.json
@@ -0,0 +1,79 @@
+/**
+ *  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.
+ */
+{
+    columns: [
+    {
+        span: 3,
+        memberGroups: {
+            General: {
+                members: {
+                    description: {},
+                    category: {},
+                    complete: {
+                        actions: {
+                            completed: {},
+                            notYetCompleted: {}
+                        }
+                    }
+                }
+            },
+            Misc: {
+                members: {
+                    versionSequence: {}
+                }
+            }
+        }
+    },
+    {
+        span: 4,
+        memberGroups: {
+            Detail: {
+                members: {
+                    dueBy: {},
+                    cost: {
+                        actions: {
+                            updateCost:{}
+                        }
+                    },
+                    notes: {},
+                    attachment: {}
+                }
+            }
+        }
+    },
+    {
+        span: 0
+    },
+    {
+        span: 5,
+        collections: {
+            dependencies: {
+                actions: {
+                    add:{},
+                    remove: {}
+                }
+            },
+            similarItems: {}
+        }
+    }
+    ],
+    actions: {
+        delete: {},
+        duplicate: {}
+    }
+}
+ 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.properties
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.properties b/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.properties
new file mode 100644
index 0000000..e47e8b4
--- /dev/null
+++ b/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/layoutmetadata/json/ExampleDomainObject.layout.properties
@@ -0,0 +1,80 @@
+#
+#  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.
+#
+
+###########################################
+# MemberGroupLayout
+###########################################
+
+memberGroupLayout.columnSpans=3,4,0,5
+memberGroupLayout.left=General,Misc
+memberGroupLayout.middle=Detail
+memberGroupLayout.right=
+
+
+###########################################
+# MemberOrder
+###########################################
+
+# Properties (General) 
+memberOrder.description.name=General
+memberOrder.category.name=General
+memberOrder.complete.name=General
+
+memberOrder.description.sequence=1
+memberOrder.category.sequence=2
+memberOrder.complete.sequence=3
+
+# Properties (Detail)
+memberOrder.dueBy.name=Detail
+memberOrder.cost.name=Detail
+memberOrder.notes.name=Detail
+memberOrder.attachment.name=Detail
+
+memberOrder.dueBy.sequence=1
+memberOrder.cost.sequence=2
+memberOrder.notes.sequence=3
+memberOrder.attachment.sequence=4
+
+# Properties (Misc)
+memberOrder.versionSequence.name=Misc
+memberOrder.versionSequence.sequence=1
+
+
+#Collections
+memberOrder.dependencies.sequence=1
+memberOrder.similarItems.sequence=2
+
+
+#Actions (freestanding)
+memberOrder.delete.sequence=1
+memberOrder.duplicate.sequence=2
+
+
+#Actions (associated with properties)
+memberOrder.completed.name=complete
+memberOrder.notYetCompleted.name=complete
+
+memberOrder.completed.sequence=1
+memberOrder.notYetCompleted.sequence=2
+
+memberOrder.updateCost.name=cost
+memberOrder.updateCost.sequence=1
+
+#Actions (associated with collections)
+memberOrder.add.name=dependencies
+
+memberOrder.remove.name=dependencies

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.json
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.json b/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.json
deleted file mode 100644
index 0ec3d12..0000000
--- a/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.json
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- *  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.
- */
-{
-    columns: [
-    {
-        span: 3,
-        memberGroups: {
-            General: {
-                members: {
-                    description: {},
-                    category: {},
-                    complete: {
-                        actions: {
-                            completed: {},
-                            notYetCompleted: {}
-                        }
-                    }
-                }
-            },
-            Misc: {
-                members: {
-                    versionSequence: {}
-                }
-            }
-        }
-    },
-    {
-        span: 4,
-        memberGroups: {
-            Detail: {
-                members: {
-                    dueBy: {},
-                    cost: {
-                        actions: {
-                            updateCost:{}
-                        }
-                    },
-                    notes: {},
-                    attachment: {}
-                }
-            }
-        }
-    },
-    {
-        span: 0
-    },
-    {
-        span: 5,
-        collections: {
-            dependencies: {
-                actions: {
-                    add:{},
-                    delete: {}
-                }
-            },
-            similarItems: {}
-        }
-    }
-    ],
-    actions: {
-        delete: {},
-        duplicate: {}
-    }
-}
- 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.properties
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.properties b/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.properties
deleted file mode 100644
index 2a2537f..0000000
--- a/core/metamodel/src/test/resources/org/apache/isis/core/metamodel/properties/json/ExampleDomainObject.isis.properties
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-#  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.
-#
-
-###########################################
-# MemberGroupLayout
-###########################################
-
-memberGroupLayout.columnSpans=_3_4_0_5
-memberGroupLayout.left=General,Misc
-memberGroupLayout.middle=Detail
-memberGroupLayout.right=
-
-
-###########################################
-# MemberOrder
-###########################################
-
-# Properties (General) 
-memberOrder.description.name=General
-memberOrder.category.name=General
-memberOrder.complete.name=General
-
-memberOrder.description.sequence=1
-memberOrder.category.sequence=2
-memberOrder.complete.sequence=3
-
-# Properties (Detail)
-memberOrder.dueBy.name=Detail
-memberOrder.cost.name=Detail
-memberOrder.notes.name=Detail
-memberOrder.attachment.name=Detail
-
-memberOrder.dueBy.sequence=1
-memberOrder.cost.sequence=2
-memberOrder.notes.sequence=3
-memberOrder.attachment.sequence=4
-
-# Properties (Misc)
-memberOrder.versionSequence.name=Misc
-memberOrder.versionSequence.sequence=1
-
-
-#Collections
-memberOrder.dependencies.sequence=1
-memberOrder.similarItems.sequence=2
-
-
-#Actions (freestanding)
-memberOrder.delete.sequence=1
-memberOrder.duplicate.sequence=2
-
-
-#Actions (associated with properties)
-memberOrder.completed.name=complete
-memberOrder.notYetCompleted.name=complete
-
-memberOrder.completed.sequence=1
-memberOrder.notYetCompleted.sequence=2
-
-memberOrder.updateCost.name=cost
-memberOrder.updateCost.sequence=1
-
-#Actions (associated with collections)
-memberOrder.add.name=dependencies
-
-memberOrder.remove.name=dependencies

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.json
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.json b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.json
deleted file mode 100644
index 0ec3d12..0000000
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.json
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- *  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.
- */
-{
-    columns: [
-    {
-        span: 3,
-        memberGroups: {
-            General: {
-                members: {
-                    description: {},
-                    category: {},
-                    complete: {
-                        actions: {
-                            completed: {},
-                            notYetCompleted: {}
-                        }
-                    }
-                }
-            },
-            Misc: {
-                members: {
-                    versionSequence: {}
-                }
-            }
-        }
-    },
-    {
-        span: 4,
-        memberGroups: {
-            Detail: {
-                members: {
-                    dueBy: {},
-                    cost: {
-                        actions: {
-                            updateCost:{}
-                        }
-                    },
-                    notes: {},
-                    attachment: {}
-                }
-            }
-        }
-    },
-    {
-        span: 0
-    },
-    {
-        span: 5,
-        collections: {
-            dependencies: {
-                actions: {
-                    add:{},
-                    delete: {}
-                }
-            },
-            similarItems: {}
-        }
-    }
-    ],
-    actions: {
-        delete: {},
-        duplicate: {}
-    }
-}
- 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.properties b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.properties
deleted file mode 100644
index 3bda693..0000000
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.isis.properties
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-#  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.
-#
-
-
-###########################################
-# MemberGroupLayout
-###########################################
-
-memberGroupLayout.columnSpans=_3_4_0_5
-memberGroupLayout.left=General 
-memberGroupLayout.middle=Detail
-memberGroupLayout.right=
-
-
-###########################################
-# MemberOrder
-###########################################
-
-# Properties 
-memberOrder.description.sequence=1
-memberOrder.category.sequence=2
-memberOrder.complete.sequence=3
-
-# Properties (Detail)
-memberOrder.dueBy.name=Detail
-memberOrder.cost.name=Detail
-memberOrder.notes.name=Detail
-memberOrder.attachment.name=Detail
-
-memberOrder.dueBy.sequence=1
-memberOrder.cost.sequence=2
-memberOrder.notes.sequence=3
-memberOrder.attachment.sequence=4
-
-# Properties (Misc)
-memberOrder.versionSequence.name=Misc
-memberOrder.versionSequence.sequence=99
-
-
-#Collections
-memberOrder.dependencies.sequence=1
-memberOrder.similarItems.sequence=2
-
-
-#Actions (freestanding)
-memberOrder.delete.sequence=1
-memberOrder.duplicate.sequence=2
-
-
-#Actions (associated with properties)
-memberOrder.completed.name=complete
-memberOrder.notYetCompleted.name=complete
-
-memberOrder.completed.sequence=1
-memberOrder.notYetCompleted.sequence=2
-
-memberOrder.updateCost.name=cost
-
-#Actions (associated with collections)
-memberOrder.add.name=dependencies
-
-memberOrder.remove.name=dependencies

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index b94d8ea..3cb9236 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -44,6 +44,7 @@ import org.apache.isis.applib.annotation.Bulk;
 import org.apache.isis.applib.annotation.CssClass;
 import org.apache.isis.applib.annotation.Disabled;
 import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.MemberGroupLayout;
 import org.apache.isis.applib.annotation.MinLength;
 import org.apache.isis.applib.annotation.MultiLine;
 import org.apache.isis.applib.annotation.Named;

http://git-wip-us.apache.org/repos/asf/isis/blob/f38fdb92/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json
new file mode 100644
index 0000000..0ec3d12
--- /dev/null
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json
@@ -0,0 +1,79 @@
+/**
+ *  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.
+ */
+{
+    columns: [
+    {
+        span: 3,
+        memberGroups: {
+            General: {
+                members: {
+                    description: {},
+                    category: {},
+                    complete: {
+                        actions: {
+                            completed: {},
+                            notYetCompleted: {}
+                        }
+                    }
+                }
+            },
+            Misc: {
+                members: {
+                    versionSequence: {}
+                }
+            }
+        }
+    },
+    {
+        span: 4,
+        memberGroups: {
+            Detail: {
+                members: {
+                    dueBy: {},
+                    cost: {
+                        actions: {
+                            updateCost:{}
+                        }
+                    },
+                    notes: {},
+                    attachment: {}
+                }
+            }
+        }
+    },
+    {
+        span: 0
+    },
+    {
+        span: 5,
+        collections: {
+            dependencies: {
+                actions: {
+                    add:{},
+                    delete: {}
+                }
+            },
+            similarItems: {}
+        }
+    }
+    ],
+    actions: {
+        delete: {},
+        duplicate: {}
+    }
+}
+ 
\ No newline at end of file