You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2017/03/17 21:49:39 UTC

svn commit: r1787507 - in /sling/trunk/bundles/extensions/fsresource/src: main/java/org/apache/sling/fsprovider/internal/ main/java/org/apache/sling/fsprovider/internal/mapper/ main/java/org/apache/sling/fsprovider/internal/mapper/jcr/ main/java/org/ap...

Author: sseifert
Date: Fri Mar 17 21:49:38 2017
New Revision: 1787507

URL: http://svn.apache.org/viewvc?rev=1787507&view=rev
Log:
SLING-6440 switch to latest contentparser API

Added:
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java   (with props)
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java   (with props)
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java   (with props)
Modified:
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtil.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileCache.java
    sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java
    sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/ContentFileTest.java
    sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtilTest.java
    sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileCacheTest.java
    sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtilTest.java

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java Fri Mar 17 21:49:38 2017
@@ -30,6 +30,7 @@ import org.apache.jackrabbit.vault.util.
 import org.apache.sling.api.resource.observation.ResourceChange;
 import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
 import org.apache.sling.fsprovider.internal.mapper.ContentFile;
+import org.apache.sling.fsprovider.internal.parser.ContentElement;
 import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
 import org.apache.sling.spi.resource.provider.ObservationReporter;
 import org.apache.sling.spi.resource.provider.ObserverConfiguration;
@@ -258,20 +259,19 @@ public final class FileMonitor extends T
         }
     }
     
-    @SuppressWarnings("unchecked")
     private List<ResourceChange> collectResourceChanges(final Monitorable monitorable, final ChangeType changeType) {
         List<ResourceChange> changes = new ArrayList<>();
         if (monitorable.status instanceof ContentFileStatus) {
             ContentFile contentFile = ((ContentFileStatus)monitorable.status).contentFile;
             if (changeType == ChangeType.CHANGED) {
-                Map<String,Object> content = (Map<String,Object>)contentFile.getContent();
+                ContentElement content = contentFile.getContent();
                 // we cannot easily report the diff of resource changes between two content files
                 // so we simulate a removal of the toplevel node and then add all nodes contained in the current content file again.
                 changes.add(buildContentResourceChange(ChangeType.REMOVED,  transformPath(monitorable.path)));
                 addContentResourceChanges(changes, ChangeType.ADDED, content, transformPath(monitorable.path));
             }
             else {
-                addContentResourceChanges(changes, changeType, (Map<String,Object>)contentFile.getContent(), transformPath(monitorable.path));
+                addContentResourceChanges(changes, changeType, contentFile.getContent(), transformPath(monitorable.path));
             }
         }
         else {
@@ -279,16 +279,13 @@ public final class FileMonitor extends T
         }
         return changes;
     }
-    @SuppressWarnings("unchecked")
     private void addContentResourceChanges(final List<ResourceChange> changes, final ChangeType changeType,
-            final Map<String,Object> content, final String path) {
+            final ContentElement content, final String path) {
         changes.add(buildContentResourceChange(changeType,  path));
         if (content != null) {
-            for (Map.Entry<String,Object> entry : content.entrySet()) {
-                if (entry.getValue() instanceof Map) {
-                    String childPath = path + "/" + entry.getKey();
-                    addContentResourceChanges(changes, changeType, (Map<String,Object>)entry.getValue(), childPath);
-                }
+            for (Map.Entry<String,ContentElement> entry : content.getChildren().entrySet()) {
+                String childPath = path + "/" + entry.getKey();
+                addContentResourceChanges(changes, changeType, entry.getValue(), childPath);
             }
         }
     }

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java Fri Mar 17 21:49:38 2017
@@ -22,10 +22,9 @@ import java.io.File;
 import java.util.Iterator;
 import java.util.Map;
 
-import org.apache.commons.collections.IteratorUtils;
-import org.apache.commons.collections.Predicate;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.fsprovider.internal.mapper.valuemap.ValueMapUtil;
+import org.apache.sling.fsprovider.internal.parser.ContentElement;
 import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
 
 /**
@@ -38,7 +37,7 @@ public final class ContentFile {
     private final String subPath;
     private final ContentFileCache contentFileCache;
     private boolean contentInitialized;
-    private Object content;
+    private ContentElement content;
     private ValueMap valueMap;
     
     /**
@@ -79,10 +78,15 @@ public final class ContentFile {
      * Content object referenced by sub path.
      * @return Map if resource, property value if property.
      */
-    public Object getContent() {
+    public ContentElement getContent() {
         if (!contentInitialized) {
-            Map<String,Object> rootContent = contentFileCache.get(path, file);
-            content = getDeepContent(rootContent, subPath);
+            ContentElement rootContent = contentFileCache.get(path, file);
+            if (subPath == null) {
+                content = rootContent;
+            }
+            else {
+                content = rootContent.getChild(subPath);
+            }
             contentInitialized = true;
         }
         return content;
@@ -96,21 +100,13 @@ public final class ContentFile {
     }
     
     /**
-     * @return true if content references resource map.
-     */
-    public boolean isResource() {
-        return (getContent() instanceof Map);
-    }
-    
-    /**
      * @return ValueMap for resource. Never null.
      */
-    @SuppressWarnings("unchecked")
     public ValueMap getValueMap() {
         if (valueMap == null) {
-            Object currentContent = getContent();
-            if (currentContent instanceof Map) {
-                valueMap = ValueMapUtil.toValueMap((Map<String,Object>)currentContent);
+            ContentElement currentContent = getContent();
+            if (currentContent != null) {
+                valueMap = ValueMapUtil.toValueMap(currentContent.getProperties());
             }
             else {
                 valueMap = ValueMap.EMPTY;
@@ -122,18 +118,8 @@ public final class ContentFile {
     /**
      * @return Child maps.
      */
-    @SuppressWarnings("unchecked")
-    public Iterator<Map.Entry<String,Map<String,Object>>> getChildren() {
-        if (!isResource()) {
-            return IteratorUtils.emptyIterator();
-        }
-        return IteratorUtils.filteredIterator(((Map)getContent()).entrySet().iterator(), new Predicate() {
-            @Override
-            public boolean evaluate(Object object) {
-                Map.Entry<String,Object> entry = (Map.Entry<String,Object>)object;
-                return entry.getValue() instanceof Map;
-            }
-        });
+    public Iterator<Map.Entry<String,ContentElement>> getChildren() {
+        return getContent().getChildren().entrySet().iterator();
     }
     
     /**
@@ -161,30 +147,4 @@ public final class ContentFile {
         return new ContentFile(file, path, absoluteSubPath, contentFileCache);
     }
         
-    @SuppressWarnings("unchecked")
-    private static Object getDeepContent(Object object, String subPath) {
-        if (object == null) {
-            return null;
-        }
-        if (subPath == null) {
-            return object;
-        }
-        if (!(object instanceof Map)) {
-            return null;
-        }
-        String name;
-        String remainingSubPath;
-        int slashIndex = subPath.indexOf('/');
-        if (slashIndex >= 0) {
-            name = subPath.substring(0, slashIndex);
-            remainingSubPath = subPath.substring(slashIndex + 1);
-        }
-        else {
-            name = subPath;
-            remainingSubPath = null;
-        }
-        Object subObject = ((Map<String,Object>)object).get(name);
-        return getDeepContent(subObject, remainingSubPath);
-    }
-    
 }

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java Fri Mar 17 21:49:38 2017
@@ -106,7 +106,7 @@ public final class ContentFileResource e
         else if (type == ValueMap.class) {
             return (AdapterType)contentFile.getValueMap();
         }
-        else if (type == Node.class && contentFile.isResource()) {
+        else if (type == Node.class) {
             // support a subset of JCR API for content file resources
             return (AdapterType)new FsNode(contentFile, getResourceResolver());
         }

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java Fri Mar 17 21:49:38 2017
@@ -32,6 +32,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.fsprovider.internal.ContentFileExtensions;
 import org.apache.sling.fsprovider.internal.FsResourceMapper;
+import org.apache.sling.fsprovider.internal.parser.ContentElement;
 import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
 
 public final class ContentFileResourceMapper implements FsResourceMapper {
@@ -105,10 +106,10 @@ public final class ContentFileResourceMa
 
         // get child resources from content fragments in content file
         List<ContentFile> children = new ArrayList<>();
-        if (parentContentFile.hasContent() && parentContentFile.isResource()) {
-            Iterator<Map.Entry<String,Map<String,Object>>> childMaps = parentContentFile.getChildren();
+        if (parentContentFile.hasContent()) {
+            Iterator<Map.Entry<String,ContentElement>> childMaps = parentContentFile.getChildren();
             while (childMaps.hasNext()) {
-                Map.Entry<String,Map<String,Object>> entry = childMaps.next();
+                Map.Entry<String,ContentElement> entry = childMaps.next();
                 children.add(parentContentFile.navigateToRelative(entry.getKey()));
             }
         }

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java Fri Mar 17 21:49:38 2017
@@ -38,6 +38,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.fsprovider.internal.FsResourceMapper;
+import org.apache.sling.fsprovider.internal.parser.ContentElement;
 import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -94,9 +95,9 @@ public final class FileVaultResourceMapp
         // get children from content resource of parent
         ContentFile parentContentFile = getContentFile(parentPath, null);
         if (parentContentFile != null) {
-            Iterator<Map.Entry<String,Map<String,Object>>> childMaps = parentContentFile.getChildren();
+            Iterator<Map.Entry<String,ContentElement>> childMaps = parentContentFile.getChildren();
             while (childMaps.hasNext()) {
-                Map.Entry<String,Map<String,Object>> entry = childMaps.next();
+                Map.Entry<String,ContentElement> entry = childMaps.next();
                 String childPath = parentPath + "/" + entry.getKey();
                 if (pathMatches(childPath)) {
                     childPaths.add(childPath);

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java Fri Mar 17 21:49:38 2017
@@ -24,10 +24,9 @@ import java.util.Map;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 
-import org.apache.commons.collections.IteratorUtils;
-import org.apache.commons.collections.Predicate;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.fsprovider.internal.mapper.ContentFile;
+import org.apache.sling.fsprovider.internal.parser.ContentElement;
 
 /**
  * Simplified implementation of read-only content access via the JCR API.
@@ -36,20 +35,13 @@ class FsNodeIterator implements NodeIter
     
     private final ContentFile contentFile;
     private final ResourceResolver resolver;
-    private final Iterator<Map.Entry<String,Map<String,Object>>> children;
+    private final Iterator<Map.Entry<String,ContentElement>> children;
 
-    @SuppressWarnings("unchecked")
     public FsNodeIterator(ContentFile contentFile, ResourceResolver resolver) {
         this.contentFile = contentFile;
         this.resolver = resolver;
-        Map<String,Object> content = (Map<String,Object>)contentFile.getContent();
-        this.children = IteratorUtils.filteredIterator(content.entrySet().iterator(), new Predicate() {
-            @Override
-            public boolean evaluate(Object object) {
-                Map.Entry<String,Object> entry = (Map.Entry<String,Object>)object;
-                return (entry.getValue() instanceof Map);
-            }
-        });
+        ContentElement content = contentFile.getContent();
+        this.children = content.getChildren().entrySet().iterator();
     }
 
     public boolean hasNext() {
@@ -62,7 +54,7 @@ class FsNodeIterator implements NodeIter
 
     @Override
     public Node nextNode() {
-        Map.Entry<String,Map<String,Object>> nextEntry = children.next();
+        Map.Entry<String,ContentElement> nextEntry = children.next();
         return new FsNode(contentFile.navigateToRelative(nextEntry.getKey()), resolver);
     }
 

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtil.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtil.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtil.java Fri Mar 17 21:49:38 2017
@@ -38,12 +38,8 @@ public final class ValueMapUtil {
     public static ValueMap toValueMap(Map<String,Object> content) {
         Map<String,Object> props = new HashMap<>();
         
-        for (Map.Entry<String, Object> entry : ((Map<String,Object>)content).entrySet()) {
-            if (entry.getValue() instanceof Map) {
-                // skip child resources
-                continue;
-            }
-            else if (entry.getValue() instanceof Collection) {
+        for (Map.Entry<String, Object> entry : content.entrySet()) {
+            if (entry.getValue() instanceof Collection) {
                 // convert lists to arrays
                 props.put(entry.getKey(), ((Collection)entry.getValue()).toArray());
             }

Added: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java?rev=1787507&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java (added)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java Fri Mar 17 21:49:38 2017
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.fsprovider.internal.parser;
+
+import java.util.Map;
+
+/**
+ * Represents a resource or node in the content hierarchy.
+ */
+public interface ContentElement {
+
+    /**
+     * @return Resource name. The root resource has no name (null).
+     */
+    String getName();
+    
+    /**
+     * Properties of this resource.
+     * @return Properties (keys, values)
+     */
+    Map<String, Object> getProperties();
+    
+    /**
+     * Get children of current resource. The Map preserves the ordering of children.
+     * @return Children (child names, child objects)
+     */
+    Map<String, ContentElement> getChildren();
+    
+    /**
+     * Get child or descendant
+     * @param path Relative path to address child or one of it's descendants (use "/" as hierarchy separator).
+     * @return Child or null if no child found with this path
+     */
+    ContentElement getChild(String path);
+    
+}

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Mar 17 21:49:38 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElement.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java?rev=1787507&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java (added)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java Fri Mar 17 21:49:38 2017
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.fsprovider.internal.parser;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.jcr.contentparser.ContentHandler;
+
+/**
+ * {@link ContentHandler} implementation that produces a tree of {@link ContentElement} items.
+ */
+final class ContentElementHandler implements ContentHandler {
+    
+    private ContentElement root;
+    private Pattern PATH_PATTERN = Pattern.compile("^((/[^/]+)*)(/([^/]+))$"); 
+
+    @Override
+    public void resource(String path, Map<String, Object> properties) {
+        if (StringUtils.equals(path, "/")) {
+            root = new ContentElementImpl(null, properties);
+        }
+        else {
+            if (root == null) {
+                throw new RuntimeException("Root resource not set.");
+            }
+            Matcher matcher = PATH_PATTERN.matcher(path);
+            if (!matcher.matches()) {
+                throw new RuntimeException("Unexpected path:" + path);
+            }
+            String relativeParentPath = StringUtils.stripStart(matcher.group(1), "/");
+            String name = matcher.group(4);
+            ContentElement parent;
+            if (StringUtils.isEmpty(relativeParentPath)) {
+                parent = root;
+            }
+            else {
+                parent = root.getChild(relativeParentPath);
+            }
+            if (parent == null) {
+                throw new RuntimeException("Parent '" + relativeParentPath + "' does not exist.");
+            }
+            parent.getChildren().put(name, new ContentElementImpl(name, properties));
+        }
+    }
+    
+    public ContentElement getRoot() {
+        return root;
+    }
+
+}

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Mar 17 21:49:38 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java?rev=1787507&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java (added)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java Fri Mar 17 21:49:38 2017
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.fsprovider.internal.parser;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+
+final class ContentElementImpl implements ContentElement {
+    
+    private final String name;
+    private final Map<String, Object> properties;
+    private final Map<String, ContentElement> children = new LinkedHashMap<>();
+    
+    public ContentElementImpl(String name, Map<String, Object> properties) {
+        this.name = name;
+        this.properties = properties;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    @Override
+    public Map<String, ContentElement> getChildren() {
+        return children;
+    }
+
+    @Override
+    public ContentElement getChild(String path) {
+        String name = StringUtils.substringBefore(path, "/");
+        ContentElement child = children.get(name);
+        if (child == null) {
+          return null;
+        }
+        String remainingPath = StringUtils.substringAfter(path, "/");
+        if (StringUtils.isEmpty(remainingPath)) {
+          return child;
+        }
+        else {
+          return child.getChild(remainingPath);
+        }
+    }
+
+}

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Mar 17 21:49:38 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileCache.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileCache.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileCache.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileCache.java Fri Mar 17 21:49:38 2017
@@ -29,8 +29,8 @@ import org.apache.commons.collections.ma
  */
 public final class ContentFileCache {
 
-    private final Map<String,Map<String,Object>> contentCache;
-    private final Map<String,Object> NULL_MAP = Collections.emptyMap();
+    private final Map<String,ContentElement> contentCache;
+    private final ContentElement NULL_ELEMENT = new ContentElementImpl(null, Collections.<String,Object>emptyMap());
     
     /**
      * @param maxSize Cache size. 0 = caching disabled.
@@ -51,21 +51,21 @@ public final class ContentFileCache {
      * @param file File
      * @return Content or null
      */
-    public Map<String,Object> get(String path, File file) {
-        Map<String,Object> content = null;
+    public ContentElement get(String path, File file) {
+        ContentElement content = null;
         if (contentCache != null) {
             content = contentCache.get(path);
         }
         if (content == null) {
             content = ContentFileParserUtil.parse(file);
             if (content == null) {
-                content = NULL_MAP;
+                content = NULL_ELEMENT;
             }
             if (contentCache != null) {
                 contentCache.put(path, content);
             }
         }
-        if (content == NULL_MAP) {
+        if (content == NULL_ELEMENT) {
             return null;
         }
         else {

Modified: sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java Fri Mar 17 21:49:38 2017
@@ -26,7 +26,6 @@ import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Map;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.jcr.contentparser.ContentParser;
@@ -65,7 +64,7 @@ class ContentFileParserUtil {
      * @param file File. Type is detected automatically.
      * @return Content or null if content could not be parsed.
      */
-    public static Map<String,Object> parse(File file) {
+    public static ContentElement parse(File file) {
         if (!file.exists()) {
             return null;
         }
@@ -83,10 +82,12 @@ class ContentFileParserUtil {
         return null;
     }
     
-    private static Map<String,Object> parse(ContentParser contentParser, File file) throws IOException {
+    private static ContentElement parse(ContentParser contentParser, File file) throws IOException {
         try (FileInputStream fis = new FileInputStream(file);
                 BufferedInputStream bis = new BufferedInputStream(fis)) {
-            return contentParser.parse(bis);
+            ContentElementHandler handler = new ContentElementHandler();
+            contentParser.parse(handler, bis);
+            return handler.getRoot();
         }
     }
 

Modified: sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/ContentFileTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/ContentFileTest.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/ContentFileTest.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/ContentFileTest.java Fri Mar 17 21:49:38 2017
@@ -24,9 +24,9 @@ import static org.junit.Assert.assertNul
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
-import java.util.Map;
 
 import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.fsprovider.internal.parser.ContentElement;
 import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
 import org.junit.Test;
 
@@ -34,7 +34,6 @@ public class ContentFileTest {
     
     private ContentFileCache contentFileCache = new ContentFileCache(0);
 
-    @SuppressWarnings("unchecked")
     @Test
     public void testRootContent() {
         File file = new File("src/test/resources/fs-test/folder2/content.json");
@@ -45,16 +44,15 @@ public class ContentFileTest {
         
         assertTrue(underTest.hasContent());
 
-        Map<String,Object> content = (Map<String,Object>)underTest.getContent();
-        assertEquals("app:Page", content.get("jcr:primaryType"));
-        assertEquals("app:PageContent", ((Map<String,Object>)content.get("jcr:content")).get("jcr:primaryType"));
+        ContentElement content = underTest.getContent();
+        assertEquals("app:Page", content.getProperties().get("jcr:primaryType"));
+        assertEquals("app:PageContent", content.getChild("jcr:content").getProperties().get("jcr:primaryType"));
 
         ValueMap props = underTest.getValueMap();
         assertEquals("app:Page", props.get("jcr:primaryType"));
         assertNull(props.get("jcr:content"));
     }
 
-    @SuppressWarnings("unchecked")
     @Test
     public void testContentLevel1() {
         File file = new File("src/test/resources/fs-test/folder2/content.json");
@@ -65,14 +63,13 @@ public class ContentFileTest {
         
         assertTrue(underTest.hasContent());
 
-        Map<String,Object> content = (Map<String,Object>)underTest.getContent();
-        assertEquals("app:PageContent", content.get("jcr:primaryType"));
+        ContentElement content = underTest.getContent();
+        assertEquals("app:PageContent", content.getProperties().get("jcr:primaryType"));
 
         ValueMap props = underTest.getValueMap();
         assertEquals("app:PageContent", props.get("jcr:primaryType"));
     }
 
-    @SuppressWarnings("unchecked")
     @Test
     public void testContentLevel5() {
         File file = new File("src/test/resources/fs-test/folder2/content.json");
@@ -83,8 +80,8 @@ public class ContentFileTest {
         
         assertTrue(underTest.hasContent());
 
-        Map<String,Object> content = (Map<String,Object>)underTest.getContent();
-        assertEquals("nt:resource", content.get("jcr:primaryType"));
+        ContentElement content = underTest.getContent();
+        assertEquals("nt:resource", content.getProperties().get("jcr:primaryType"));
 
         ValueMap props = underTest.getValueMap();
         assertEquals("nt:resource", props.get("jcr:primaryType"));
@@ -98,11 +95,7 @@ public class ContentFileTest {
         assertEquals(file, underTest.getFile());
         assertEquals("jcr:content/jcr:title", underTest.getSubPath());
         
-        assertTrue(underTest.hasContent());
-
-        assertEquals("English", underTest.getContent());
-
-        assertTrue(underTest.getValueMap().isEmpty());
+        assertFalse(underTest.hasContent());
     }
 
     @Test

Modified: sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtilTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtilTest.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtilTest.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/mapper/valuemap/ValueMapUtilTest.java Fri Mar 17 21:49:38 2017
@@ -20,7 +20,6 @@ package org.apache.sling.fsprovider.inte
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -29,7 +28,6 @@ import org.apache.sling.api.resource.Val
 import org.junit.Test;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 
 public class ValueMapUtilTest {
 
@@ -38,7 +36,6 @@ public class ValueMapUtilTest {
         Map<String,Object> content = new HashMap<>();
         content.put("stringProp", "abc");
         content.put("intProp", 123);
-        content.put("childNode", ImmutableMap.<String,Object>of());
         content.put("stringArray", new String[] { "a", "b", "c" });
         content.put("stringList", ImmutableList.of("ab", "cd"));
         content.put("intList", ImmutableList.of(12, 34));
@@ -46,7 +43,6 @@ public class ValueMapUtilTest {
         ValueMap props = ValueMapUtil.toValueMap(content);
         assertEquals("abc", props.get("stringProp", String.class));
         assertEquals((Integer)123, props.get("intProp", 0));
-        assertNull(props.get("childNode"));
         assertArrayEquals(new String[] { "a", "b", "c" }, props.get("stringArray", String[].class));
         assertArrayEquals(new String[] { "ab", "cd" }, props.get("stringList", String[].class));
         assertArrayEquals(new Integer[] { 12, 34 }, props.get("intList", Integer[].class));

Modified: sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileCacheTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileCacheTest.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileCacheTest.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileCacheTest.java Fri Mar 17 21:49:38 2017
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertNull;
 
 import java.io.File;
-import java.util.Map;
 
 import org.junit.experimental.theories.DataPoint;
 import org.junit.experimental.theories.Theories;
@@ -44,7 +43,7 @@ public class ContentFileCacheTest {
     public void testCache(int cacheSize) {
         ContentFileCache underTest = new ContentFileCache(cacheSize);
         
-        Map<String,Object> content1 = underTest.get("/fs-test/folder2/content", new File("src/test/resources/fs-test/folder2/content.json"));
+        ContentElement content1 = underTest.get("/fs-test/folder2/content", new File("src/test/resources/fs-test/folder2/content.json"));
         assertNotNull(content1);
         
         switch (cacheSize) {
@@ -57,7 +56,7 @@ public class ContentFileCacheTest {
             break;
         }
 
-        Map<String,Object> content2 = underTest.get("/fs-test/folder1/file1a", new File("src/test/resources/fs-test/folder1/file1a.txt"));
+        ContentElement content2 = underTest.get("/fs-test/folder1/file1a", new File("src/test/resources/fs-test/folder1/file1a.txt"));
         assertNull(content2);
 
         switch (cacheSize) {

Modified: sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtilTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtilTest.java?rev=1787507&r1=1787506&r2=1787507&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtilTest.java (original)
+++ sling/trunk/bundles/extensions/fsresource/src/test/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtilTest.java Fri Mar 17 21:49:38 2017
@@ -23,43 +23,40 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertNull;
 
 import java.io.File;
-import java.util.Map;
 
 import org.junit.Test;
 
 public class ContentFileParserUtilTest {
 
-    @SuppressWarnings("unchecked")
     @Test
     public void testParseJson() {
         File file = new File("src/test/resources/fs-test/folder2/content.json");
-        Map<String,Object> content = ContentFileParserUtil.parse(file);
+        ContentElement content = ContentFileParserUtil.parse(file);
         assertNotNull(content);
-        assertEquals("app:Page", content.get("jcr:primaryType"));
-        assertEquals("app:PageContent", ((Map<String,Object>)content.get("jcr:content")).get("jcr:primaryType"));
+        assertEquals("app:Page", content.getProperties().get("jcr:primaryType"));
+        assertEquals("app:PageContent", content.getChild("jcr:content").getProperties().get("jcr:primaryType"));
     }
 
     @Test
     public void testParseInvalidJson() {
         File file = new File("src/test/resources/invalid-test/invalid.json");
-        Map<String,Object> content = ContentFileParserUtil.parse(file);
+        ContentElement content = ContentFileParserUtil.parse(file);
         assertNull(content);
     }
 
-    @SuppressWarnings("unchecked")
     @Test
     public void testParseJcrXml() {
         File file = new File("src/test/resources/fs-test/folder3/content.jcr.xml");
-        Map<String,Object> content = ContentFileParserUtil.parse(file);
+        ContentElement content = ContentFileParserUtil.parse(file);
         assertNotNull(content);
-        assertEquals("app:Page", content.get("jcr:primaryType"));
-        assertEquals("app:PageContent", ((Map<String,Object>)content.get("jcr:content")).get("jcr:primaryType"));
+        assertEquals("app:Page", content.getProperties().get("jcr:primaryType"));
+        assertEquals("app:PageContent", content.getChild("jcr:content").getProperties().get("jcr:primaryType"));
     }
 
     @Test
     public void testParseInvalidJcrXml() {
         File file = new File("src/test/resources/invalid-test/invalid.jcr.xml");
-        Map<String,Object> content = ContentFileParserUtil.parse(file);
+        ContentElement content = ContentFileParserUtil.parse(file);
         assertNull(content);
     }