You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2019/07/22 09:08:37 UTC

[sling-org-apache-sling-contentparser-api] branch master created (now 1e09d2f)

This is an automated email from the ASF dual-hosted git repository.

radu pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git.


      at 1e09d2f  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

This branch includes the following new commits:

     new 0f58520  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new 7538f20  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new 52c5b28  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new 3b81178  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new f734613  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new af122e9  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new a380889  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new 7d36196  Enhanced readme
     new 9fbd47a  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new 9b33d6a  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
     new 1e09d2f  SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-contentparser-api] 01/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 0f5852061580d94f2482d40cdee7b1f0caa1f2f1
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Wed Jul 10 19:19:43 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * extracted API bundle
    * first attempt at implementing a separate JSON content parser
---
 pom.xml                                            |  61 ++++++++
 .../sling/contentparser/api/ContentHandler.java    |  41 +++++
 .../sling/contentparser/api/ContentParser.java     |  79 ++++++++++
 .../sling/contentparser/api/JsonParserFeature.java |  36 +++++
 .../sling/contentparser/api/ParseException.java    |  49 ++++++
 .../sling/contentparser/api/ParserHelper.java      | 104 +++++++++++++
 .../sling/contentparser/api/ParserOptions.java     | 171 +++++++++++++++++++++
 .../sling/contentparser/api/package-info.java      |  22 +++
 .../sling/contentparser/api/ParserHelperTest.java  |  57 +++++++
 9 files changed, 620 insertions(+)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..799b201
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling-bundle-parent</artifactId>
+        <version>35</version>
+        <relativePath />
+    </parent>
+
+    <artifactId>org.apache.sling.contentparser.api</artifactId>
+    <version>0.9.0-SNAPSHOT</version>
+
+    <name>Apache Sling Content Parser API</name>
+    <description>
+        Parser API Apache Sling Resource trees stored in files (e.g. JSON, FileVault XML, etc.).
+    </description>
+
+    <scm>
+        <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git</connection>
+        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git</developerConnection>
+        <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-contentparser-api.git</url>
+      <tag>HEAD</tag>
+  </scm>
+
+    <build>
+        <plugins>
+            
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.annotation.versioning</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/src/main/java/org/apache/sling/contentparser/api/ContentHandler.java b/src/main/java/org/apache/sling/contentparser/api/ContentHandler.java
new file mode 100644
index 0000000..34103d1
--- /dev/null
+++ b/src/main/java/org/apache/sling/contentparser/api/ContentHandler.java
@@ -0,0 +1,41 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.contentparser.api;
+
+import java.util.Map;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * A {@code ContentHandler} gets notified while parsing content with a {@link ContentParser}. The resources are always reported in the
+ * order in which they are found in the parsed files. Parents are always reported before their children.
+ */
+@ConsumerType
+public interface ContentHandler {
+
+    /**
+     * Resource found in parsed content.
+     *
+     * @param path       the path of the found resource inside the content fragment; the root resource from the content fragment will
+     *                   have the {@code "/"} path
+     * @param properties the resource's properties
+     */
+    void resource(String path, Map<String, Object> properties);
+
+}
diff --git a/src/main/java/org/apache/sling/contentparser/api/ContentParser.java b/src/main/java/org/apache/sling/contentparser/api/ContentParser.java
new file mode 100644
index 0000000..1a684ca
--- /dev/null
+++ b/src/main/java/org/apache/sling/contentparser/api/ContentParser.java
@@ -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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.contentparser.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * A {@code ContentParser} parses Sling resource trees from a file. Implementations have to be thread-safe. A consumer requiring a {@code
+ * ContentParser} reference should filter based on the {@link #SERVICE_PROPERTY_CONTENT_TYPE} in order to get a content type specific
+ * parser.
+ */
+@ProviderType
+public interface ContentParser {
+
+    /**
+     * JSON content descriptor file.
+     *
+     * @see <a href="https://sling.apache.org/documentation/bundles/content-loading-jcr-contentloader.html#json-descriptor-files">JCR
+     * ContentLoader JSON descriptor files</a>
+     */
+    String JSON_CONTENT_TYPE = "json";
+
+    /**
+     * XML content descriptor file.
+     *
+     * @see <a href="https://sling.apache.org/documentation/bundles/content-loading-jcr-contentloader.html#xml-descriptor-files">JCR
+     * ContentLoader XML descriptor files</a>
+     */
+    String XML_CONTENT_TYPE = "xml";
+
+    /**
+     * JCR XML content (FileVault XML),aAlso known as extended document view XML. Extends the regular document view as specified by JCR 2.0
+     * with specifics like multi-value and type information.
+     *
+     * @see <a href="https://docs.adobe.com/content/docs/en/spec/jcr/2.0/7_Export.html#7.3%20Document%20View">JCR 2.0, 7.3 Document View</a>
+     * @see <a href="http://jackrabbit.apache.org/filevault/">Jackrabbit FileVault</a>
+     */
+    String JCR_XML_CONTENT_TYPE = "jcr.xml";
+
+    /**
+     * OSGi service registration property indicating the content type this {@code ContentParser} supports.
+     *
+     * @see #JSON_CONTENT_TYPE
+     * @see #XML_CONTENT_TYPE
+     * @see #JCR_XML_CONTENT_TYPE
+     */
+    String SERVICE_PROPERTY_CONTENT_TYPE = "org.apache.sling.contentparser.content_type";
+
+    /**
+     * Parse content in a "stream-based" way. Each resource that is found in the content is reported to the {@link ContentHandler}.
+     *
+     * @param contentHandler content handler that accepts the parsed content
+     * @param inputStream    stream with serialized content
+     * @param parserOptions  parser options, providing different settings for handling the serialized content
+     * @throws IOException    when an I/O error occurs
+     * @throws ParseException when a parsing error occurs.
+     */
+    void parse(ContentHandler contentHandler, InputStream inputStream, ParserOptions parserOptions) throws IOException, ParseException;
+
+}
diff --git a/src/main/java/org/apache/sling/contentparser/api/JsonParserFeature.java b/src/main/java/org/apache/sling/contentparser/api/JsonParserFeature.java
new file mode 100644
index 0000000..58c3e2b
--- /dev/null
+++ b/src/main/java/org/apache/sling/contentparser/api/JsonParserFeature.java
@@ -0,0 +1,36 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.contentparser.api;
+
+/**
+ * Feature flags for parsing JSON files.
+ */
+public enum JsonParserFeature {
+
+    /**
+     * Support comments (&#47;* ... *&#47;) in JSON files.
+     */
+    COMMENTS,
+
+    /**
+     * Support ticks (') additional to double quotes (") as quoting symbol for JSON names and strings.
+     */
+    QUOTE_TICK
+    
+}
diff --git a/src/main/java/org/apache/sling/contentparser/api/ParseException.java b/src/main/java/org/apache/sling/contentparser/api/ParseException.java
new file mode 100644
index 0000000..4a19711
--- /dev/null
+++ b/src/main/java/org/apache/sling/contentparser/api/ParseException.java
@@ -0,0 +1,49 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.contentparser.api;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Defines a parsing exception encountered by a {@link ContentParser}.
+ */
+@ProviderType
+public final class ParseException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Builds a {@code ParseException}, providing a message.
+     *
+     * @param message the message
+     */
+    public ParseException(String message) {
+        super(message);
+    }
+
+    /**
+     * Builds a {@code ParseException}, providing a message and a cause.
+     *
+     * @param message the message
+     * @param cause   the cause
+     */
+    public ParseException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java b/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
new file mode 100644
index 0000000..7cb1196
--- /dev/null
+++ b/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
@@ -0,0 +1,104 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.contentparser.api;
+
+import java.lang.reflect.Array;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+@ConsumerType
+public final class ParserHelper {
+
+    public static final String ECMA_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z";
+    public static final String ISO_8601_MILLISECONDS_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSVV";
+    public static final Locale DATE_FORMAT_LOCALE = Locale.US;
+    public static final DateTimeFormatter ECMA_DATE_FORMATTER = DateTimeFormatter.ofPattern(ECMA_DATE_FORMAT, DATE_FORMAT_LOCALE);
+    public static final DateTimeFormatter ISO_8601_MILLISECONDS_DATE_FORMATTER =
+            DateTimeFormatter.ofPattern(ISO_8601_MILLISECONDS_DATE_FORMAT,
+                    DATE_FORMAT_LOCALE);
+
+    /**
+     * Attempts to parse a {@code string} using first the {@link #ISO_8601_MILLISECONDS_DATE_FORMAT} format and then the {@link
+     * #ECMA_DATE_FORMAT}.
+     *
+     * @param string the string to parse
+     * @return a {@link Calendar} containing the parsed date or {@code null}, if the parsing failed
+     */
+    public static Calendar parseDate(String string) {
+        Calendar calendar = Calendar.getInstance();
+        try {
+            final OffsetDateTime offsetDateTime = OffsetDateTime.parse(string, ISO_8601_MILLISECONDS_DATE_FORMATTER);
+            final Instant instant = offsetDateTime.toInstant();
+            calendar.setTime(Date.from(instant));
+            calendar.setTimeZone(TimeZone.getTimeZone(offsetDateTime.getOffset()));
+        } catch (DateTimeParseException e) {
+            try {
+                final OffsetDateTime offsetDateTime = OffsetDateTime.parse(string, ECMA_DATE_FORMATTER);
+                final Instant instant = offsetDateTime.toInstant();
+                calendar.setTime(Date.from(instant));
+                calendar.setTimeZone(TimeZone.getTimeZone(offsetDateTime.getOffset()));
+            } catch (DateTimeParseException ee) {
+                calendar = null;
+            }
+        }
+        return calendar;
+    }
+
+    /**
+     * Converts a multi-value property to a single object.
+     *
+     * @param values the multi-value property's values
+     * @return an object representation of the multi-value property
+     */
+    public static Object convertSingleTypeArray(Object[] values) {
+        if (values.length == 0) {
+            return values;
+        }
+        Class<?> itemType = null;
+        for (Object value : values) {
+            if (value == null) {
+                throw new ParseException("Multi-value array must not contain null values.");
+            }
+            if (value instanceof Map) {
+                throw new ParseException("Multi-value array must not contain maps/objects.");
+            }
+            if (itemType == null) {
+                itemType = value.getClass();
+            } else if (itemType != value.getClass()) {
+                throw new ParseException("Multivalue array must not contain values with different types "
+                        + "(" + itemType.getName() + ", " + value.getClass().getName() + ").");
+            }
+        }
+        Object convertedArray = Array.newInstance(itemType, values.length);
+        for (int i = 0; i < values.length; i++) {
+            Array.set(convertedArray, i, values[i]);
+        }
+        return convertedArray;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/contentparser/api/ParserOptions.java b/src/main/java/org/apache/sling/contentparser/api/ParserOptions.java
new file mode 100644
index 0000000..ebf80f0
--- /dev/null
+++ b/src/main/java/org/apache/sling/contentparser/api/ParserOptions.java
@@ -0,0 +1,171 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.contentparser.api;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Options for content parsers.
+ */
+@ProviderType
+public final class ParserOptions {
+
+    /**
+     * Default primary type.
+     */
+    public static final String DEFAULT_PRIMARY_TYPE = "nt:unstructured";
+
+    /**
+     * Default list of prefixes to remove from property names.
+     */
+    public static final Set<String> DEFAULT_REMOVE_PROPERTY_NAME_PREFIXES
+            = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+            "jcr:reference:",
+            "jcr:path:",
+            "jcr:name:",
+            "jcr:uri:"
+    )));
+
+    /**
+     * Default list of resource names that should be ignored.
+     */
+    public static final Set<String> DEFAULT_IGNORE_RESOURCE_NAMES
+            = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+            "security:acl",
+            "security:principals"
+    )));
+
+    /**
+     * List of JSON parser features activated by default.
+     */
+    public static final EnumSet<JsonParserFeature> DEFAULT_JSON_PARSER_FEATURES
+            = EnumSet.of(JsonParserFeature.COMMENTS);
+
+    private String defaultPrimaryType = DEFAULT_PRIMARY_TYPE;
+    private boolean detectCalendarValues;
+    private Set<String> ignorePropertyNames = Collections.emptySet();
+    private Set<String> ignoreResourceNames = DEFAULT_IGNORE_RESOURCE_NAMES;
+    private Set<String> removePropertyNamePrefixes = DEFAULT_REMOVE_PROPERTY_NAME_PREFIXES;
+    private EnumSet<JsonParserFeature> jsonParserFeatures = DEFAULT_JSON_PARSER_FEATURES;
+
+    /**
+     * Default "jcr:primaryType" property for resources that have no explicit value for this value.
+     * If set to null, not default type is applied.
+     *
+     * @param value Default primary type.
+     * @return this
+     */
+    public ParserOptions defaultPrimaryType(String value) {
+        this.defaultPrimaryType = value;
+        return this;
+    }
+
+    public String getDefaultPrimaryType() {
+        return defaultPrimaryType;
+    }
+
+    /**
+     * Some content formats like JSON do not contain information to identify date/time values.
+     * Instead they have to be detected by heuristics by trying to parse every string value.
+     * This mode is disabled by default.
+     *
+     * @param value Activate calendar value detection
+     * @return this
+     */
+    public ParserOptions detectCalendarValues(boolean value) {
+        this.detectCalendarValues = value;
+        return this;
+    }
+
+    public boolean isDetectCalendarValues() {
+        return detectCalendarValues;
+    }
+
+    /**
+     * Set a list of property names that should be ignored when parsing the content file.
+     *
+     * @param value List of property names
+     * @return this
+     */
+    public ParserOptions ignorePropertyNames(Set<String> value) {
+        this.ignorePropertyNames = value;
+        return this;
+    }
+
+    public Set<String> getIgnorePropertyNames() {
+        return ignorePropertyNames;
+    }
+
+    /**
+     * Set a list of resource/node names that should be ignored when parsing the content file.
+     *
+     * @param value List of resource/node names
+     * @return this
+     */
+    public ParserOptions ignoreResourceNames(Set<String> value) {
+        this.ignoreResourceNames = value;
+        return this;
+    }
+
+    public Set<String> getIgnoreResourceNames() {
+        return ignoreResourceNames;
+    }
+
+    /**
+     * Set a list of property name prefixes that should be removed automatically from the property name.
+     *
+     * @param value List of property name prefixes
+     * @return this
+     */
+    public ParserOptions removePropertyNamePrefixes(Set<String> value) {
+        this.removePropertyNamePrefixes = value;
+        return this;
+    }
+
+    public Set<String> getRemovePropertyNamePrefixes() {
+        return removePropertyNamePrefixes;
+    }
+
+    /**
+     * Set set of features the JSON parser should apply when parsing files.
+     *
+     * @param value JSON parser features
+     * @return this
+     */
+    public ParserOptions jsonParserFeatures(EnumSet<JsonParserFeature> value) {
+        this.jsonParserFeatures = value;
+        return this;
+    }
+
+    public ParserOptions jsonParserFeatures(JsonParserFeature... value) {
+        this.jsonParserFeatures = EnumSet.copyOf(Arrays.asList(value));
+        return this;
+    }
+
+    public EnumSet<JsonParserFeature> getJsonParserFeatures() {
+        return jsonParserFeatures;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/contentparser/api/package-info.java b/src/main/java/org/apache/sling/contentparser/api/package-info.java
new file mode 100644
index 0000000..8997911
--- /dev/null
+++ b/src/main/java/org/apache/sling/contentparser/api/package-info.java
@@ -0,0 +1,22 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+@Version("1.0.0")
+package org.apache.sling.contentparser.api;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java b/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
new file mode 100644
index 0000000..2b2da48
--- /dev/null
+++ b/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
@@ -0,0 +1,57 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.contentparser.api;
+
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNull;
+
+public class ParserHelperTest {
+
+    @Test
+    public void parseDate() {
+        Map<String, int[]> formats = new HashMap<>();
+        formats.put("Sun Oct 31 2010 21:48:04 GMT+0100", new int[]{31, 10, 2010, 21, 48, 4, 0, 1});
+        formats.put("Sun Oct 31 2010 21:48", null);
+        formats.put("2014-09-19T21:20:26.812+02:00", new int[]{19, 9, 2014, 21, 20, 26, 812, 2});
+        formats.put("2014-09-19T21:20:26.812", null);
+        for (Map.Entry<String, int[]> entry : formats.entrySet()) {
+            int[] dateAsInts = entry.getValue();
+            Calendar calendar = ParserHelper.parseDate(entry.getKey());
+            if (dateAsInts == null) {
+                assertNull("Expected a null return value for string " + entry.getKey(), calendar);
+            } else {
+                assertEquals(dateAsInts[0], calendar.get(Calendar.DAY_OF_MONTH));
+                assertEquals(dateAsInts[1], calendar.get(Calendar.MONTH) + 1);
+                assertEquals(dateAsInts[2], calendar.get(Calendar.YEAR));
+                assertEquals(dateAsInts[3], calendar.get(Calendar.HOUR_OF_DAY));
+                assertEquals(dateAsInts[4], calendar.get(Calendar.MINUTE));
+                assertEquals(dateAsInts[5], calendar.get(Calendar.SECOND));
+                assertEquals(dateAsInts[6], calendar.get(Calendar.MILLISECOND));
+                assertEquals(dateAsInts[7], calendar.getTimeZone().getRawOffset() / 3600 / 1000);
+
+            }
+        }
+    }
+}


[sling-org-apache-sling-contentparser-api] 02/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 7538f20553a6c7a842fb2edcd64f5c8f806669da
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Thu Jul 11 15:07:22 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * corrected some typos
    * added more unit tests
---
 pom.xml                                            |  2 +-
 .../sling/contentparser/api/ParserHelper.java      |  4 +-
 .../sling/contentparser/api/ParserHelperTest.java  | 47 +++++++++++++++++++++-
 3 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index 799b201..bdb4bab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
 
     <name>Apache Sling Content Parser API</name>
     <description>
-        Parser API Apache Sling Resource trees stored in files (e.g. JSON, FileVault XML, etc.).
+        API for parsing Apache Sling Resource trees stored in files (e.g. JSON, FileVault XML, etc.).
     </description>
 
     <scm>
diff --git a/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java b/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
index 7cb1196..ca7f2ca 100644
--- a/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
+++ b/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
@@ -74,6 +74,8 @@ public final class ParserHelper {
      *
      * @param values the multi-value property's values
      * @return an object representation of the multi-value property
+     * @throws ParseException when the provided {@code values} array contains null values, {@link Map} values, or the values are not of the
+     *                        same type
      */
     public static Object convertSingleTypeArray(Object[] values) {
         if (values.length == 0) {
@@ -90,7 +92,7 @@ public final class ParserHelper {
             if (itemType == null) {
                 itemType = value.getClass();
             } else if (itemType != value.getClass()) {
-                throw new ParseException("Multivalue array must not contain values with different types "
+                throw new ParseException("Multi-value array must not contain values with different types "
                         + "(" + itemType.getName() + ", " + value.getClass().getName() + ").");
             }
         }
diff --git a/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java b/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
index 2b2da48..7f57ff3 100644
--- a/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
+++ b/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
@@ -19,13 +19,17 @@
 package org.apache.sling.contentparser.api;
 
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.junit.Test;
 
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNull;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 public class ParserHelperTest {
 
@@ -54,4 +58,43 @@ public class ParserHelperTest {
             }
         }
     }
+
+    @Test
+    public void convertSingleTypeArray() {
+        Object[] empty = new Object[]{};
+        assertEquals(empty, ParserHelper.convertSingleTypeArray(empty));
+
+        Object[] nullValues = new Object[] {"string", null};
+        ParseException nullValuesException = null;
+        try {
+            ParserHelper.convertSingleTypeArray(nullValues);
+        } catch (ParseException e) {
+            nullValuesException = e;
+        }
+        assertNotNull("Expected a ParseException when the Object array contains multiple types.", nullValuesException);
+
+        Object[] maps = new Object[] {Collections.emptyMap()};
+        ParseException mapsException = null;
+        try {
+            ParserHelper.convertSingleTypeArray(maps);
+        } catch (ParseException e) {
+            mapsException = e;
+        }
+        assertNotNull("Expected a ParseException when the Object array contains Map objects.", mapsException);
+
+        Object[] differentTypes = new Object[] {"string", 1, 1L, 1F, Boolean.TRUE};
+        ParseException differentTypesException = null;
+        try {
+            ParserHelper.convertSingleTypeArray(differentTypes);
+        } catch (ParseException e) {
+            differentTypesException = e;
+        }
+        assertNotNull("Expected a ParseException when the Object array contains multiple types.", differentTypesException);
+
+        Object[] values = new Object[] {1, 2, 3, 4, 5};
+        Object result = ParserHelper.convertSingleTypeArray(values);
+        assertTrue("Expected the resulting object to be an Integer array.", result instanceof Integer[]);
+        Integer[] typedResult = (Integer[]) result;
+        assertArrayEquals("Expected the arrays to be equal.", new Integer[] {1, 2, 3, 4, 5}, typedResult);
+    }
 }


[sling-org-apache-sling-contentparser-api] 10/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 9b33d6ac95cbf5ea432f214eb141efdd9f7dbb3a
Author: Radu Cotescu <co...@adobe.com>
AuthorDate: Mon Jul 22 10:17:49 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * added Jenkinsfile
---
 Jenkinsfile | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..3882176
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,20 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+// please rebuild
+slingOsgiBundleBuild()


[sling-org-apache-sling-contentparser-api] 08/11: Enhanced readme

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 7d3619699b7864d0dc3756b9197251ed97dd9f9b
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Wed Jul 17 10:08:46 2019 +0200

    Enhanced readme
---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 4e1e37b..ab05675 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,6 @@ to select the appropriate file format (see `ContentParser.JSON_CONTENT_TYPE`, `C
 Implementations of the API are made available from separate bundles:
 1. JSON - [`org.apache.sling.contentparser.json`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-json)
 2. XML - [`org.apache.sling.contentparser.xml`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-xml)
-3. JackRabbit FileVault XML - [`org.apache.sling.contentparser.xml-jcr`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-xml-jcr) (the only module depending on the JCR / 
-JackRabbit APIs)
+3. Jackrabbit Filevault XML ([Enhanced JCR 2.0 Document View](https://jackrabbit.apache.org/filevault/docview.html)) - [`org.apache.sling.contentparser.xml-jcr`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-xml-jcr) (the only module depending on the JCR / 
+Jackrabbit APIs)
 


[sling-org-apache-sling-contentparser-api] 05/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit f73461360b045783cdaa28e7e519f4cdbd7932b2
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Jul 15 13:53:24 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * configured bnd-baseline-maven-plugin to not fail the build when
    there's no artifact available for the baseline analysis
---
 pom.xml | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/pom.xml b/pom.xml
index 8ad0b57..27a2821 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,18 @@
         <tag>HEAD</tag>
     </scm>
 
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-baseline-maven-plugin</artifactId>
+                <configuration>
+                    <failOnMissing>false</failOnMissing>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
     <dependencies>
         <dependency>
             <groupId>org.osgi</groupId>


[sling-org-apache-sling-contentparser-api] 04/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 3b811782fc6d0753c37caa1e5efa9a92a0edf922
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Jul 15 12:02:03 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * added parser for JCR-flavoured XML
    * made the ParserHelper compatible with both Java 8 and Java 11
    * reduced the number of dependencies for all modules
---
 .../sling/contentparser/api/ParserHelper.java      | 35 +++++++++++-----------
 .../sling/contentparser/api/ParserHelperTest.java  |  1 +
 2 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java b/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
index ca7f2ca..3d6a973 100644
--- a/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
+++ b/src/main/java/org/apache/sling/contentparser/api/ParserHelper.java
@@ -20,7 +20,7 @@ package org.apache.sling.contentparser.api;
 
 import java.lang.reflect.Array;
 import java.time.Instant;
-import java.time.OffsetDateTime;
+import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.util.Calendar;
@@ -34,11 +34,11 @@ import org.osgi.annotation.versioning.ConsumerType;
 @ConsumerType
 public final class ParserHelper {
 
-    public static final String ECMA_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z";
-    public static final String ISO_8601_MILLISECONDS_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSVV";
-    public static final Locale DATE_FORMAT_LOCALE = Locale.US;
-    public static final DateTimeFormatter ECMA_DATE_FORMATTER = DateTimeFormatter.ofPattern(ECMA_DATE_FORMAT, DATE_FORMAT_LOCALE);
-    public static final DateTimeFormatter ISO_8601_MILLISECONDS_DATE_FORMATTER =
+    private static final String ECMA_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z";
+    private static final String ISO_8601_MILLISECONDS_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSVV";
+    private static final Locale DATE_FORMAT_LOCALE = Locale.US;
+    private static final DateTimeFormatter ECMA_DATE_FORMATTER = DateTimeFormatter.ofPattern(ECMA_DATE_FORMAT, DATE_FORMAT_LOCALE);
+    private static final DateTimeFormatter ISO_8601_MILLISECONDS_DATE_FORMATTER =
             DateTimeFormatter.ofPattern(ISO_8601_MILLISECONDS_DATE_FORMAT,
                     DATE_FORMAT_LOCALE);
 
@@ -50,23 +50,15 @@ public final class ParserHelper {
      * @return a {@link Calendar} containing the parsed date or {@code null}, if the parsing failed
      */
     public static Calendar parseDate(String string) {
-        Calendar calendar = Calendar.getInstance();
         try {
-            final OffsetDateTime offsetDateTime = OffsetDateTime.parse(string, ISO_8601_MILLISECONDS_DATE_FORMATTER);
-            final Instant instant = offsetDateTime.toInstant();
-            calendar.setTime(Date.from(instant));
-            calendar.setTimeZone(TimeZone.getTimeZone(offsetDateTime.getOffset()));
+            return parseDate(string, ISO_8601_MILLISECONDS_DATE_FORMATTER);
         } catch (DateTimeParseException e) {
             try {
-                final OffsetDateTime offsetDateTime = OffsetDateTime.parse(string, ECMA_DATE_FORMATTER);
-                final Instant instant = offsetDateTime.toInstant();
-                calendar.setTime(Date.from(instant));
-                calendar.setTimeZone(TimeZone.getTimeZone(offsetDateTime.getOffset()));
+                return parseDate(string, ECMA_DATE_FORMATTER);
             } catch (DateTimeParseException ee) {
-                calendar = null;
+                return null;
             }
         }
-        return calendar;
     }
 
     /**
@@ -103,4 +95,13 @@ public final class ParserHelper {
         return convertedArray;
     }
 
+    private static Calendar parseDate(String string, DateTimeFormatter formatter) throws DateTimeParseException {
+        final ZonedDateTime zonedDateTime = ZonedDateTime.parse(string, formatter);
+        final Instant instant = zonedDateTime.toInstant();
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(Date.from(instant));
+        calendar.setTimeZone(TimeZone.getTimeZone(zonedDateTime.getOffset()));
+        return calendar;
+    }
+
 }
diff --git a/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java b/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
index 7f57ff3..9477414 100644
--- a/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
+++ b/src/test/java/org/apache/sling/contentparser/api/ParserHelperTest.java
@@ -46,6 +46,7 @@ public class ParserHelperTest {
             if (dateAsInts == null) {
                 assertNull("Expected a null return value for string " + entry.getKey(), calendar);
             } else {
+                assertNotNull("Unexpected parser failure for input " + entry.getKey(), calendar);
                 assertEquals(dateAsInts[0], calendar.get(Calendar.DAY_OF_MONTH));
                 assertEquals(dateAsInts[1], calendar.get(Calendar.MONTH) + 1);
                 assertEquals(dateAsInts[2], calendar.get(Calendar.YEAR));


[sling-org-apache-sling-contentparser-api] 07/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit a3808898239d3dd168160cfbd9f96f9c175e06e1
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Wed Jul 17 10:00:57 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * linked implementation modules
---
 README.md | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 38ebb27..4e1e37b 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,8 @@ to select the appropriate file format (see `ContentParser.JSON_CONTENT_TYPE`, `C
 3. as a consequence of 2., the `ParserOptions` are now passed directly to the `ContentParser#parse` method.
 
 Implementations of the API are made available from separate bundles:
-1. JSON - `org.apache.sling.contentparser.json`
-2. XML - `org.apache.sling.contentparser.xml`
-3. JackRabbit FileVault XML - `org.apache.sling.contentparser.xml-jcr` (the only module depending on the JCR / JackRabbit APIs)
+1. JSON - [`org.apache.sling.contentparser.json`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-json)
+2. XML - [`org.apache.sling.contentparser.xml`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-xml)
+3. JackRabbit FileVault XML - [`org.apache.sling.contentparser.xml-jcr`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-xml-jcr) (the only module depending on the JCR / 
+JackRabbit APIs)
 


[sling-org-apache-sling-contentparser-api] 09/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 9fbd47a5eb3a80ea284112f6a72e961e4dc3ebb1
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Jul 22 09:39:40 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * completely decoupled the API from implementations - the ContentParser API
    doesn't suggest any content types any more
    * removed JSON specific parser options from the ParserOptions class
    * made the ParserOptions class extendable
    * switched exported API packages to version 2.0.0, to eliminate all possible
    confusion with the older org.apache.sling.jcr.contentparser API
---
 README.md                                          |  3 +-
 .../sling/contentparser/api/ContentParser.java     | 38 +++++++---------------
 .../sling/contentparser/api/JsonParserFeature.java | 36 --------------------
 .../sling/contentparser/api/ParserOptions.java     | 31 +++---------------
 .../sling/contentparser/api/package-info.java      |  2 +-
 5 files changed, 18 insertions(+), 92 deletions(-)

diff --git a/README.md b/README.md
index ab05675..b8d102b 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,7 @@ continuation of the one provided by the [Apache Sling JCR Content Parser](https:
 1. the API is now available in the `org.apache.sling.contentparser.api` package;
 2. there is no replacement for the `org.apache.sling.jcr.contentparser.ContentParserFactory`; to obtain a `ContentParser`, given that 
 they are exposed as OSGi services, one has to filter on the `ContentParser.SERVICE_PROPERTY_CONTENT_TYPE` service registration property,
-to select the appropriate file format (see `ContentParser.JSON_CONTENT_TYPE`, `ContentParser.XML_CONTENT_TYPE` and
-`ContentParser.JCR_XML_CONTENT_TYPE`);
+to select the appropriate file format;
 3. as a consequence of 2., the `ParserOptions` are now passed directly to the `ContentParser#parse` method.
 
 Implementations of the API are made available from separate bundles:
diff --git a/src/main/java/org/apache/sling/contentparser/api/ContentParser.java b/src/main/java/org/apache/sling/contentparser/api/ContentParser.java
index 1a684ca..2738088 100644
--- a/src/main/java/org/apache/sling/contentparser/api/ContentParser.java
+++ b/src/main/java/org/apache/sling/contentparser/api/ContentParser.java
@@ -31,37 +31,23 @@ import org.osgi.annotation.versioning.ProviderType;
 @ProviderType
 public interface ContentParser {
 
-    /**
-     * JSON content descriptor file.
-     *
-     * @see <a href="https://sling.apache.org/documentation/bundles/content-loading-jcr-contentloader.html#json-descriptor-files">JCR
-     * ContentLoader JSON descriptor files</a>
-     */
-    String JSON_CONTENT_TYPE = "json";
 
     /**
-     * XML content descriptor file.
+     * OSGi service registration property indicating the content type this {@code ContentParser} supports. The simplest way to retrieve a
+     * {@code ContentParser} for a certain content type is to apply a filter on the service reference:
      *
-     * @see <a href="https://sling.apache.org/documentation/bundles/content-loading-jcr-contentloader.html#xml-descriptor-files">JCR
-     * ContentLoader XML descriptor files</a>
-     */
-    String XML_CONTENT_TYPE = "xml";
-
-    /**
-     * JCR XML content (FileVault XML),aAlso known as extended document view XML. Extends the regular document view as specified by JCR 2.0
-     * with specifics like multi-value and type information.
+     * <pre>
+     *    {@literal @}Reference(target = "(" + ContentParser.SERVICE_PROPERTY_CONTENT_TYPE + "=" + _value_ + ")")
+     *     private ContentParser parser;
+     * </pre>
      *
-     * @see <a href="https://docs.adobe.com/content/docs/en/spec/jcr/2.0/7_Export.html#7.3%20Document%20View">JCR 2.0, 7.3 Document View</a>
-     * @see <a href="http://jackrabbit.apache.org/filevault/">Jackrabbit FileVault</a>
-     */
-    String JCR_XML_CONTENT_TYPE = "jcr.xml";
-
-    /**
-     * OSGi service registration property indicating the content type this {@code ContentParser} supports.
+     * If multiple services are registered for the same content type, the above code snippet will provide you with the service
+     * implementation with the highest ranking. However, if a certain implementation is needed, an additional filter can be added:
      *
-     * @see #JSON_CONTENT_TYPE
-     * @see #XML_CONTENT_TYPE
-     * @see #JCR_XML_CONTENT_TYPE
+     * <pre>
+     *     {@literal @}Reference(target = "(&amp;(" + ContentParser.SERVICE_PROPERTY_CONTENT_TYPE + "=" + _value_ + ")(component.name=" + _class_name_ + "))")
+     *      private ContentParser parser;
+     * </pre>
      */
     String SERVICE_PROPERTY_CONTENT_TYPE = "org.apache.sling.contentparser.content_type";
 
diff --git a/src/main/java/org/apache/sling/contentparser/api/JsonParserFeature.java b/src/main/java/org/apache/sling/contentparser/api/JsonParserFeature.java
deleted file mode 100644
index 58c3e2b..0000000
--- a/src/main/java/org/apache/sling/contentparser/api/JsonParserFeature.java
+++ /dev/null
@@ -1,36 +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.
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.contentparser.api;
-
-/**
- * Feature flags for parsing JSON files.
- */
-public enum JsonParserFeature {
-
-    /**
-     * Support comments (&#47;* ... *&#47;) in JSON files.
-     */
-    COMMENTS,
-
-    /**
-     * Support ticks (') additional to double quotes (") as quoting symbol for JSON names and strings.
-     */
-    QUOTE_TICK
-    
-}
diff --git a/src/main/java/org/apache/sling/contentparser/api/ParserOptions.java b/src/main/java/org/apache/sling/contentparser/api/ParserOptions.java
index ebf80f0..c28ffe7 100644
--- a/src/main/java/org/apache/sling/contentparser/api/ParserOptions.java
+++ b/src/main/java/org/apache/sling/contentparser/api/ParserOptions.java
@@ -20,17 +20,17 @@ package org.apache.sling.contentparser.api;
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Set;
 
 import org.osgi.annotation.versioning.ProviderType;
 
 /**
- * Options for content parsers.
+ * Generic options for content parsers. Parser implementations can extend this class to provide additional options, valid only in the
+ * context of those implementations.
  */
 @ProviderType
-public final class ParserOptions {
+public class ParserOptions {
 
     /**
      * Default primary type.
@@ -57,18 +57,13 @@ public final class ParserOptions {
             "security:principals"
     )));
 
-    /**
-     * List of JSON parser features activated by default.
-     */
-    public static final EnumSet<JsonParserFeature> DEFAULT_JSON_PARSER_FEATURES
-            = EnumSet.of(JsonParserFeature.COMMENTS);
+
 
     private String defaultPrimaryType = DEFAULT_PRIMARY_TYPE;
     private boolean detectCalendarValues;
     private Set<String> ignorePropertyNames = Collections.emptySet();
     private Set<String> ignoreResourceNames = DEFAULT_IGNORE_RESOURCE_NAMES;
     private Set<String> removePropertyNamePrefixes = DEFAULT_REMOVE_PROPERTY_NAME_PREFIXES;
-    private EnumSet<JsonParserFeature> jsonParserFeatures = DEFAULT_JSON_PARSER_FEATURES;
 
     /**
      * Default "jcr:primaryType" property for resources that have no explicit value for this value.
@@ -148,24 +143,6 @@ public final class ParserOptions {
         return removePropertyNamePrefixes;
     }
 
-    /**
-     * Set set of features the JSON parser should apply when parsing files.
-     *
-     * @param value JSON parser features
-     * @return this
-     */
-    public ParserOptions jsonParserFeatures(EnumSet<JsonParserFeature> value) {
-        this.jsonParserFeatures = value;
-        return this;
-    }
-
-    public ParserOptions jsonParserFeatures(JsonParserFeature... value) {
-        this.jsonParserFeatures = EnumSet.copyOf(Arrays.asList(value));
-        return this;
-    }
 
-    public EnumSet<JsonParserFeature> getJsonParserFeatures() {
-        return jsonParserFeatures;
-    }
 
 }
diff --git a/src/main/java/org/apache/sling/contentparser/api/package-info.java b/src/main/java/org/apache/sling/contentparser/api/package-info.java
index 8997911..9368f3a 100644
--- a/src/main/java/org/apache/sling/contentparser/api/package-info.java
+++ b/src/main/java/org/apache/sling/contentparser/api/package-info.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-@Version("1.0.0")
+@Version("2.0.0")
 package org.apache.sling.contentparser.api;
 
 import org.osgi.annotation.versioning.Version;


[sling-org-apache-sling-contentparser-api] 03/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 52c5b287153a77692003fcef7817464b4179e549
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Thu Jul 11 15:23:46 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * pom clean-up
    * replaced a deprecated import and removed an unused one
---
 pom.xml | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/pom.xml b/pom.xml
index bdb4bab..8ad0b57 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,13 +17,14 @@
     specific language governing permissions and limitations
     under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling-bundle-parent</artifactId>
         <version>35</version>
-        <relativePath />
+        <relativePath/>
     </parent>
 
     <artifactId>org.apache.sling.contentparser.api</artifactId>
@@ -31,21 +32,16 @@
 
     <name>Apache Sling Content Parser API</name>
     <description>
-        API for parsing Apache Sling Resource trees stored in files (e.g. JSON, FileVault XML, etc.).
+        API for parsing Apache Sling Resource trees stored in files (e.g. JSON, FileVault XML, etc.)
     </description>
 
     <scm>
         <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git</connection>
         <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git</developerConnection>
         <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-contentparser-api.git</url>
-      <tag>HEAD</tag>
-  </scm>
+        <tag>HEAD</tag>
+    </scm>
 
-    <build>
-        <plugins>
-            
-        </plugins>
-    </build>
     <dependencies>
         <dependency>
             <groupId>org.osgi</groupId>


[sling-org-apache-sling-contentparser-api] 11/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit 1e09d2febd310167311328061264a46f10e807dc
Author: Radu Cotescu <co...@adobe.com>
AuthorDate: Mon Jul 22 10:22:09 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * updated links in README
---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index b8d102b..3c5a453 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,8 @@ to select the appropriate file format;
 3. as a consequence of 2., the `ParserOptions` are now passed directly to the `ContentParser#parse` method.
 
 Implementations of the API are made available from separate bundles:
-1. JSON - [`org.apache.sling.contentparser.json`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-json)
-2. XML - [`org.apache.sling.contentparser.xml`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-xml)
-3. Jackrabbit Filevault XML ([Enhanced JCR 2.0 Document View](https://jackrabbit.apache.org/filevault/docview.html)) - [`org.apache.sling.contentparser.xml-jcr`](https://github.com/apache/sling-whiteboard/tree/master/contentparser/org-apache-sling-contentparser-xml-jcr) (the only module depending on the JCR / 
+1. JSON - [`org.apache.sling.contentparser.json`](https://github.com/apache/sling-org-apache-sling-contentparser-json)
+2. XML - [`org.apache.sling.contentparser.xml`](https://github.com/apache/sling-org-apache-sling-contentparser-xml)
+3. Jackrabbit Filevault XML ([Enhanced JCR 2.0 Document View](https://jackrabbit.apache.org/filevault/docview.html)) - [`org.apache.sling.contentparser.xml-jcr`](https://github.com/apache/sling-org-apache-sling-contentparser-xml-jcr) (the only module depending on the JCR / 
 Jackrabbit APIs)
 


[sling-org-apache-sling-contentparser-api] 06/11: SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-api.git

commit af122e96cc9e0cd2c01eb90bd7bdcb64436be698
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Wed Jul 17 09:59:05 2019 +0200

    SLING-8570 - Extract a generic Content Parser API from org.apache.sling.jcr.contentparser with pluggable implementations
    
    * added README, CODE_OF_CONDUCT, CONTRIBUTING, LICENSE and .gitignore files
    to each module
---
 .gitignore         |  17 +++++
 CODE_OF_CONDUCT.md |  22 ++++++
 CONTRIBUTING.md    |  24 +++++++
 LICENSE            | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 README.md          |  19 +++++
 5 files changed, 284 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5b783ed
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+/target
+.idea
+.classpath
+.metadata
+.project
+.settings
+.externalToolBuilders
+maven-eclipse.xml
+*.swp
+*.iml
+*.ipr
+*.iws
+*.bak
+.vlt
+.DS_Store
+jcr.log
+atlassian-ide-plugin.xml
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..0fa18e5
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,22 @@
+<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~ 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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
+Apache Software Foundation Code of Conduct
+====
+
+Being an Apache project, Apache Sling adheres to the Apache Software Foundation's [Code of Conduct](https://www.apache.org/foundation/policies/conduct.html).
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..ac82a1a
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,24 @@
+<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~ 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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
+Contributing
+====
+
+Thanks for choosing to contribute!
+
+You will find all the necessary details about how you can do this at https://sling.apache.org/contributing.html.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..38ebb27
--- /dev/null
+++ b/README.md
@@ -0,0 +1,19 @@
+Apache Sling Content Parser API
+====
+This module is part of the [Apache Sling](https://sling.apache.org) project.
+
+The Apache Sling Content Parser API provides support for parsing various files capable of abstracting a Sling resource tree. This API is a 
+continuation of the one provided by the [Apache Sling JCR Content Parser](https://github.com/apache/sling-org-apache-sling-jcr-contentparser) bundle. Although very similar, there are some notable changes:
+
+1. the API is now available in the `org.apache.sling.contentparser.api` package;
+2. there is no replacement for the `org.apache.sling.jcr.contentparser.ContentParserFactory`; to obtain a `ContentParser`, given that 
+they are exposed as OSGi services, one has to filter on the `ContentParser.SERVICE_PROPERTY_CONTENT_TYPE` service registration property,
+to select the appropriate file format (see `ContentParser.JSON_CONTENT_TYPE`, `ContentParser.XML_CONTENT_TYPE` and
+`ContentParser.JCR_XML_CONTENT_TYPE`);
+3. as a consequence of 2., the `ParserOptions` are now passed directly to the `ContentParser#parse` method.
+
+Implementations of the API are made available from separate bundles:
+1. JSON - `org.apache.sling.contentparser.json`
+2. XML - `org.apache.sling.contentparser.xml`
+3. JackRabbit FileVault XML - `org.apache.sling.contentparser.xml-jcr` (the only module depending on the JCR / JackRabbit APIs)
+