You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2015/08/24 16:53:18 UTC

svn commit: r1697419 [1/2] - in /sling/trunk/contrib/extensions/hapi: ./ core/ core/src/ core/src/main/ core/src/main/java/ core/src/main/java/org/ core/src/main/java/org/apache/ core/src/main/java/org/apache/sling/ core/src/main/java/org/apache/sling/...

Author: bdelacretaz
Date: Mon Aug 24 14:53:16 2015
New Revision: 1697419

URL: http://svn.apache.org/r1697419
Log:
SLING-4513 - import donated HApi tools

Added:
    sling/trunk/contrib/extensions/hapi/   (with props)
    sling/trunk/contrib/extensions/hapi/README.md
    sling/trunk/contrib/extensions/hapi/core/   (with props)
    sling/trunk/contrib/extensions/hapi/core/.gitignore
    sling/trunk/contrib/extensions/hapi/core/pom.xml
    sling/trunk/contrib/extensions/hapi/core/src/
    sling/trunk/contrib/extensions/hapi/core/src/main/
    sling/trunk/contrib/extensions/hapi/core/src/main/java/
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiException.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiProperty.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiType.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUse.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUtil.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/MicrodataAttributeHelper.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/TypeView.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/AbstractHapiTypeImpl.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java
    sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/package-info.java
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/components/
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/components/type/
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html
    sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/types.json
    sling/trunk/contrib/extensions/hapi/pics/   (with props)
    sling/trunk/contrib/extensions/hapi/pics/browser1.png   (with props)
    sling/trunk/contrib/extensions/hapi/pics/browser2.png   (with props)
    sling/trunk/contrib/extensions/hapi/pics/python1.png   (with props)
    sling/trunk/contrib/extensions/hapi/pics/python2.png   (with props)
    sling/trunk/contrib/extensions/hapi/pics/python3.png   (with props)
    sling/trunk/contrib/extensions/hapi/pics/python4.png   (with props)
    sling/trunk/contrib/extensions/hapi/samplecontent/   (with props)
    sling/trunk/contrib/extensions/hapi/samplecontent/.gitignore
    sling/trunk/contrib/extensions/hapi/samplecontent/pom.xml
    sling/trunk/contrib/extensions/hapi/samplecontent/src/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/java/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/components/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/components/details/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/components/details/DetailsView.java
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/components/details/details.html
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/components/sample1/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/components/sample1/Sample1.java
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/components/sample1/sample1.html
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/site/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/site/assets/
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/site/assets/preview-small-album.png   (with props)
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/site/assets/preview-small.png   (with props)
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/site/assets/preview1.png   (with props)
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/site/details.json
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/site/site.json
    sling/trunk/contrib/extensions/hapi/samplecontent/src/main/resources/SLING-INF/apps/sling/hapi_sample/types.json

Propchange: sling/trunk/contrib/extensions/hapi/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Aug 24 14:53:16 2015
@@ -0,0 +1,14 @@
+target
+bin
+derby.log
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+
+
+

Added: sling/trunk/contrib/extensions/hapi/README.md
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/README.md?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/README.md (added)
+++ sling/trunk/contrib/extensions/hapi/README.md Mon Aug 24 14:53:16 2015
@@ -0,0 +1,213 @@
+# <a name="section-1">HApi - Hypermedia API tools</a>
+
+The hypermedia API tools are a way to enable sling component developers to add metadata information to their HTML components and easily define an API using the html markup generated by the components. 
+
+HApi tools work with [sightly](http://docs.adobe.com/docs/en/aem/6-0/develop/sightly.html), JSP or any scripting language that can call java code. For understanding how microdata works, read the next section, [Hypermedia API with Microdata](#section-2).
+
+To see how the HApi implemetation works, read [How HApi works, by example](#section-3)
+
+# <a name="section-install">Installation</a>
+  The two bundles, core and samplecontent need sightly installed on the sling instance.
+
+  You can then install both with _mvn clean install sling:install_
+
+  After that, to check the sample page go to http://localhost:8080/apps/sling/hapi_sample/site/site.html and check out the sample page.
+
+  See below for consuming the API with a generic client.
+
+
+# <a name="section-2">Hypermedia API with Microdata</a>
+There is a lot of confusion surrounding this term, but shortly put, it's an API having content with links. We can use it a way of defining a protocol-agnostic API for our resources, designing it from the client-side, using the html markup as the media type. This means the requested resource representation would be displayed in browsers out-of-the-box, but also understood by any user or automaton which understands the API. Such APIs can be defined for XML, HTML, JSON and becomes a hypermedia API by adding links to the content. One way of defining an API over html is using the [microdata specification](http://schema.org/docs/gs.html) (reading the examples provides a lot of insight). The links are already semantically defined in HTML, so that fullfills the requirements for a hypermedia API.
+
+For us out there in a hurry, let's take the following short example from the [schema.org](http://schema.org/docs/gs.html) page:
+
+```html
+    <div itemscope itemtype="http://schema.org/Movie">
+       <h1 itemprop="name">Avatar</h1>
+       <span itemprop="genre">Science fiction</span>
+       <a href="../movies/avatar-theatrical-trailer.html" itemprop="trailer">Trailer</a>
+
+       <div itemprop="director" itemscope itemtype="http://schema.org/Person"> 
+           Director: <span itemprop="name">James Cameron</span> (born <span itemprop="birthDate">August16, 1954)</span>
+       </div>
+    </div>
+```
+
+The attribute _itemscope_ defines a scope for an object. The (optional) _itemtype_ links to a description of the type of the object. Inside an element with an _itemscope_ attribute, we have descendant elements with a property _itemprop_. This means the _name_  property will point to the enclosed object, which is the simple text "Avatar". Similarly, the _genre_ property is "Science Fiction". 
+
+The _director_ property is not a simple type, so it defines a new _itemscope_. Also, the _itemtype_ shows it's a Person. Now, the schema for Person defines the _name_ and the _birthDate_ properties, which are pointed to the same way as above.
+
+# <a name="section-3">How HApi works, by example</a>
+
+In order to see how HApi works, the best way is to check an example. In the sample content module, we have a demo app that defines an API and uses that in the sightly components. The best way to start is to analyze the end result and acknowledge it's usefuleness:
+
+## <a name="section-3a">Consuming the API</a>
+
+The app looks like this in the browser:
+![Page in the browser](pics/browser1.png)
+
+The generated content looks something like this for the first card:
+
+```html
+            <div itemtype="/apps/sling/hapi_sample/types/album_card.html" itemscope="itemscope" class="card-asset">
+                <a href="details.html" rel="self">
+                    <img itemprop="thumbnail" itemtype="/libs/sling/hapi/types/image.html" alt="" src="assets/preview-small-album.png" class="show-grid">
+
+                    <div>
+                        <h4 itemprop="title" itemtype="/libs/sling/hapi/types/text.html">PIC 001</h4>
+
+                        <p class="type">album</p>
+
+                        <p itemprop="cards" itemtype="/libs/sling/hapi/types/number.html" class="size">5</p>
+                        <meta itemprop="disabled" itemtype="/libs/sling/hapi/types/boolean.html" content="false">
+                        <div class="myinfo">
+                            <p class="mymodified">
+                                <i>Modified</i>
+                                <span itemprop="modified" itemtype="/libs/sling/hapi/types/text.html" class="date">2 days ago</span>
+                                <span>Admin</span>
+                            </p>
+                        </div>
+                    </div>
+                </a>
+            </div>
+```
+
+The entities that have semantic meaning to us (e.g. Are part of the API) are the elements annotated with microdata, links and forms: 
+ * `<div itemtype="/apps/sling/hapi_sample/types/album_card.html" itemscope="itemscope" class="card-asset">`
+ * `<a href="details.html" rel="self">`
+ * `<link ...>`
+ * `<form ... >`
+
+ Because the API is defined using the generated HTML (same consumed by the browser), we can consume the _real_ content using any microdata thin, application-agnostic client.
+ A simple example is using [a simple html python client](https://github.com/dulvac/htmlapi-client-python/blob/master/htmlapi_client.py), but any client can be used. Here's what it can do:
+ 
+![Enter example](pics/python1.png)
+
+We can see that we have two objects in the page/ resource (because I've chosen to expose just two), one of type **pic_card** and one of type **album_card**. The types are URLs resolvable in sling. They look something like this in the browser:
+ 
+![Type in browser](pics/browser2.png)
+
+Let's continue using the html client to consume our API:
+
+![Properties example](pics/python2.png)
+![Properties example](pics/python3.png)
+
+For a hypermedia API, we use links as a way to change the state of the application, like it happens in the browser:
+
+![Links example](pics/python4.png)
+
+So navigating/ changing state works by using the semantic meaning of links in html. Except the enter() function, there is no http url needed to use the sling web application. If you define your links and link relations correctly, any microdata client like this can change the state, in addition to consuming the content defined through the microdata hypermedia API.
+
+As you've probably noticed, we use some domain-specific types for _itemtype_. This is how you define the types:
+
+## Defining the types
+
+The types are defined as nt:unstructured nodes in the repository with a certain _sling:resourceType_ configurable in the OSGi config of the HApiUtil service:
+
+```json
+{
+
+    "fqdn": "org.apache.sling.hapi_sample.album_card",
+    "description": "A demo card type for HApi",
+    "name": "album_card",
+    "sling:resourceType": "sling/hapi/components/type",
+    "parameters": [ ],
+    "extends": "/apps/sling/hapi_sample/types/demo_card",
+    "jcr:primaryType": "nt:unstructured",
+    "thumbnail": 
+
+{
+
+    "description": "The thumbnail of the demo pic card",
+    "type": "org.apache.sling.hapi.common.Image",
+    "multiple": true,
+    "jcr:primaryType": "nt:unstructured"
+
+},
+"disabled":
+{
+
+    "description": "Whether this album is disabled or not",
+    "type": "org.apache.sling.hapi.common.Boolean",
+    "multiple": false,
+    "jcr:primaryType": "nt:unstructured"
+
+},
+"modified":
+{
+
+    "description": "When was the pic last modified",
+    "type": "org.apache.sling.hapi.common.Text",
+    "multiple": false,
+    "jcr:primaryType": "nt:unstructured"
+
+},
+"cards":
+{
+
+    "description": "The number of pictures in this album",
+    "type": "org.apache.sling.hapi.common.Number",
+    "multiple": false,
+    "jcr:primaryType": "nt:unstructured"
+
+},
+"users":
+
+    {
+        "description": "The numbers of users for this album",
+        "type": "org.apache.sling.hapi.common.Number",
+        "multiple": false,
+        "jcr:primaryType": "nt:unstructured"
+    }
+
+}
+```
+
+## Using the sightly HApiUse class
+
+After defining the types needed for the component in question, you can immediately benefit from the HApi tools and add the microdata annotations. There is also validation for the properties and the itemtype for properties is added automatically by the tools. 
+
+This is how a sightly component using it looks like:
+
+```html
+<div data-sly-use.card="${'org.apache.sling.hapi.HApiUse' @type='/apps/sling/hapi_sample/types/pic_card'}"
+                 data-sly-attribute="${card.itemtype}" class="card-asset">
+                <a rel="self" href="details.html">
+                    <img data-sly-attribute="${card.itemprop.thumbnail}" class="show-grid" src="assets/preview-small.png" alt="">
+
+                    <div>
+                        <h4 data-sly-attribute="${card.itemprop['title']}">PIC 001</h4>
+
+                        <p class="type">PSD</p>
+
+                        <p data-sly-attribute="${card.itemprop.resolution}"
+                           data-sly-use.resolution="${'org.apache.sling.hapi.HApiUse' @type=card.proptype.resolution}" class="resolution">
+                            <span data-sly-attribute="${resolution.itemprop.width}">1620</span> x <span
+                                data-sly-attribute="${resolution.itemprop.height}">670</span>
+                        </p>
+
+                        <p data-sly-attribute="${card.itemprop.size}" class="size">249KB</p>
+                        <meta data-sly-attribute="${card.itemprop.disabled}" content="false"/>
+                        <div class="myinfo">
+                            <p class="mymodified">
+                                <i>Modified</i>
+                                <span data-sly-attribute="${card.itemprop.modified}" class="date">2 days ago</span>
+                                <span>Admin</span>
+                            </p>
+                        </div>
+                    </div>
+                </a>
+            </div>
+```
+
+
+The sightly script snippet above produces the html we saw in the section [Consuming the API](#section-3a).
+You only need to parameterize the use object once with the type identifier and the tool can validate the properties and infer the property type and automatically add the required itemtype attribute. Were we to try the following attribute on the pic_card markup, we'd get a runtime exception:
+
+```html
+<img data-sly-attribute="${card.itemprop.inexistent_property}" class="show-grid" src="assets/preview-small.png" alt=""></span>           
+```
+
+```
+org.apache.sling.hapi.HApiException: Property inexistent_property does not exist for type /apps/hapi-sample/types/pic_card
+```

Propchange: sling/trunk/contrib/extensions/hapi/core/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Aug 24 14:53:16 2015
@@ -0,0 +1,14 @@
+target
+bin
+derby.log
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+
+
+

Added: sling/trunk/contrib/extensions/hapi/core/.gitignore
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/.gitignore?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/.gitignore (added)
+++ sling/trunk/contrib/extensions/hapi/core/.gitignore Mon Aug 24 14:53:16 2015
@@ -0,0 +1,15 @@
+target/
+.project
+.classpath
+.settings/
+/sling/
+derby.log
+*.iml
+*.ipr
+*.iws
+coverage.em
+coverage.ec
+coverage/
+.DS_Store
+.idea/
+bundles/extensions/models/integration-tests/sling

Added: sling/trunk/contrib/extensions/hapi/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/pom.xml?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/pom.xml (added)
+++ sling/trunk/contrib/extensions/hapi/core/pom.xml Mon Aug 24 14:53:16 2015
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+~ 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/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>20</version>
+        <relativePath/>
+    </parent>
+
+    <artifactId>org.apache.sling.hapi</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>HApi - Sling Hypermedia API tools</name>
+    <description>Sling tools for adding support for defining, maintaining and consuming a Hypermedia API in sling components</description>
+
+    <properties>
+        <sling.java.version>6</sling.java.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.sling</groupId>
+                <artifactId>maven-sling-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Category>sling</Bundle-Category>
+                        <Sling-Initial-Content>SLING-INF;overwrite=true</Sling-Initial-Content>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.3.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.scripting.api</artifactId>
+            <version>2.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.json</artifactId>
+            <version>2.0.6</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>1.9.6</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+            <version>2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.scripting.sightly</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiException.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiException.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiException.java Mon Aug 24 14:53:16 2015
@@ -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.hapi;
+
+/**
+ * A Hypermedia API exception
+ */
+public class HApiException extends RuntimeException {
+    public HApiException() {
+    }
+
+    /**
+     *
+     * @param message
+     */
+    public HApiException(String message) {
+        super(message);
+    }
+
+    /**
+     *
+     * @param message
+     * @param cause
+     */
+    public HApiException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     *
+     * @param cause
+     */
+    public HApiException(Throwable cause) {
+        super(cause);
+    }
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiProperty.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiProperty.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiProperty.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiProperty.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.hapi;
+
+/**
+ * A Hypermedia API property for a {@link HApiType}
+ */
+public interface HApiProperty {
+
+    /**
+     * Get the name of this property
+     * @return
+     */
+    String getName();
+
+    /**
+     * Set the name of this property
+     * @param name
+     */
+    void setName(String name);
+
+    /**
+     * Get the description of this property
+     * @return
+     */
+    String getDescription();
+
+    /**
+     * Set the description of this property
+     * @return
+     */
+    void setDescription(String description);
+
+    /**
+     * Get the type of this property
+     * @return
+     */
+    HApiType getType();
+
+    /**
+     * Set the type of this property
+     * @return
+     */
+    void setType(HApiType type);
+
+    /**
+     * Whether this property is a multiple value
+     * @return
+     */
+    Boolean getMultiple();
+
+    /**
+     * Set the boolean value for multiple
+     * @param multiple
+     */
+    void setMultiple(Boolean multiple);
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiType.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiType.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiType.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiType.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.hapi;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A Hypermedia API type.
+ */
+public interface HApiType {
+
+    /**
+     * The name of this type
+     * @return
+     */
+    String getName();
+
+
+    /**
+     * The description of this type
+     * @return
+     */
+    String getDescription();
+
+    /**
+     * The JCR path of the node representing this type
+     * @return
+     */
+    String getPath();
+
+    /**
+     * The URL of the node representing this type
+     * @return
+     */
+    String getUrl();
+
+    /**
+     * The fully qualified domain name of this type
+     * @return
+     */
+    String getFqdn();
+
+    /**
+     * A list of {@link String} representing java-like generic types that can be used as types for the properties belonging to this type
+     * @return
+     */
+    List<String> getParameters();
+
+    /**
+     * A map with the names of the properties as keys and the HApiProperty object as values defined for this type
+     * <p>This list does not include properties inherited from the parent type</p>
+     * @return
+     */
+    Map<String, HApiProperty> getProperties();
+
+    /**
+     * A map with the names of the properties as keys and the HApiProperty object as values defined for this type,
+     * including the properties inherited from the parent type
+     * @return
+     */
+    Map<String, HApiProperty> getAllProperties();
+
+    /**
+     * Returns the parent type object
+     * @return
+     */
+    HApiType getParent();
+
+    /**
+     * Whether this type is abstract or not.
+     * An abstract type is an identifier that does not map to a jcr node as a path or as a FQDN
+     * @return
+     */
+    boolean isAbstract();
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUse.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUse.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUse.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUse.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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.hapi;
+
+import org.apache.sling.scripting.sightly.pojo.Use;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.script.Bindings;
+import java.util.Map;
+
+/**
+ * Sightly use class helper to provide the hypermedia API microdata attributes for the type configured throught the 'type' binding.
+ * <p>The type can be a JCR path or a fully qualified domain name like in
+ * {@link HApiUtil#getTypeNode(org.apache.sling.api.resource.ResourceResolver, String)}</p>
+ * <p>The convenience get methods are meant to be used in the 'data-sly-attribute' in the sightly script.</p>
+ */
+public class HApiUse implements Use {
+    private static final Logger LOG = LoggerFactory.getLogger(HApiUse.class);
+
+    private HApiUtil hapi;
+    private MicrodataAttributeHelper helper;
+    private SlingHttpServletRequest request;
+    private SlingScriptHelper sling;
+    private Resource resource;
+    private ResourceResolver resourceResolver;
+    private String typeId;
+    private Map<String, String> itemTypeAttr;
+    private Map<String, Map<String, String>> itemPropAttrs;
+    private Map<String, String> itemPropTypes;
+
+    /**
+     * {@inheritDoc}
+     * @param bindings
+     */
+    public void init(Bindings bindings) {
+        request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+        sling = (SlingScriptHelper) bindings.get(SlingBindings.SLING);
+        resource = (Resource)bindings.get(SlingBindings.RESOURCE);
+        resourceResolver = request.getResourceResolver();
+        typeId = (String) bindings.get("type");
+        LOG.debug("init type: {}", typeId);
+
+        try {
+            activate();
+        } catch (Exception e) {
+            LOG.error("Failed to activate Use class", e);
+        }
+    }
+
+    /**
+     * Initializes the helper and the attribute maps for the given type though the bindings
+     * @throws Exception
+     */
+    public void activate() throws Exception {
+        hapi = sling.getService(HApiUtil.class);
+        helper = hapi.getHelper(resourceResolver, typeId);
+        itemTypeAttr = helper.itemtypeMap();
+        itemPropAttrs = helper.allItemPropMap();
+        itemPropTypes = helper.allPropTypesMap();
+    }
+
+    /**
+     * Get the itemtype html attributes map for the type
+     * @return
+     */
+    public Map<String, String> getItemtype() {
+        LOG.debug("itemtype attrs: {}", itemTypeAttr);
+        return itemTypeAttr;
+    }
+
+    /**
+     * Get the itemprop attributes map for the type, for each property.
+     * The key is the property name and the value is a map of html attributes for the property
+     * @return
+     */
+    public Map<String, Map<String, String>> getItemprop() {
+        LOG.debug("itemprop attrs: {}", itemPropAttrs);
+        return itemPropAttrs;
+    }
+
+    /**
+     * Get a map of the type for each property name of the type
+     * The key is the property name and the value is the type path in JCR
+     * @return
+     */
+    public Map<String, String> getProptype() {
+        LOG.debug("property type attrs: {}", itemPropTypes);
+        return itemPropTypes;
+    }
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUtil.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUtil.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/HApiUtil.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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.hapi;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+public interface HApiUtil {
+    public static final Logger LOG = LoggerFactory.getLogger(HApiUtil.class);
+
+    public static final String DEFAULT_RESOURCE_TYPE = "sling/hapi/components/type";
+
+    /**
+     * <p>Get a HApi type object from a type identifier.</p>
+     * <p>The JCR node must be [nt:unstructured], a descendant of any of the HAPi search path defined by the
+     * {@see HAPI_PATHS} config and the sling:resourceType should be set to the value defined by the {@see HAPI_RESOURCE_TYPE} config</p>
+     * <p>The first result is returned</p>
+     * @param resolver The sling resource resolver object
+     * @param type The type identifier, which is either in the form of a jcr path,
+     *             same as the path for {@link: ResourceResolver#getResource(String)}. If the path cannot be resolved, type is treated like
+     *             a fully qualified domain name, which has to match the "fqdn" property on the JCR node which represents the type.
+     * @return The first node that matches that type or null if none is found.
+     * @throws RepositoryException
+     */
+    public Node getTypeNode(ResourceResolver resolver, String type) throws RepositoryException;
+
+
+    /**
+     * <p>Get a HApi type object from a type identifier.</p>
+     * <p>The type identifier is resolved to a {@link javax.jcr.Node} and then
+     * {@link #fromNode(org.apache.sling.api.resource.ResourceResolver, javax.jcr.Node)} is called.</p>
+     * <p>For restrictions on the {@link javax.jcr.Node}
+     * see {@link HApiUtil#getTypeNode(org.apache.sling.api.resource.ResourceResolver, String)}</p>
+     * @param resolver The sling resource resolver object
+     * @param type The type identifier, which is either in the form of a jcr path,
+     *             same as the path for{@link: ResourceResolver#getResource(String)}. If the path cannot be resolved, type is treated like
+     *             a fully qualified domain name, which has to match the "fqdn" property on the JCR node which represents the type.
+     * @return The HApiType resolved from the type identifier
+     * @throws javax.jcr.RepositoryException
+     */
+    public HApiType fromPath(ResourceResolver resolver, String type) throws RepositoryException;
+
+    /**
+     * <p>Get a HApi type object from the {@link javax.jcr.Node}.</p>
+     * The Node has the following properties:
+     * <ul>
+     *     <li>name: A 'Name' of the type (mandatory)</li>
+     *     <li>description: A 'String' with the description text for this type (mandatory)</li>
+     *     <li>fqdn: A 'String' with the fully qualified domain name; A namespace like a java package (mandatory)</li>
+     *     <li>extends: A type identifier (either a path or a fqdn); (optional). This defines the parent type of this type</li>
+     *     <li>parameter: A multivalue property to define a list of java-like generic types
+     *     that can be used as types for properties; (optional)</li>
+     * </ul>
+     *
+     * <p>The properties of this type are defined as children nodes.</p>
+     * <p>The name of property node defines the name of the property for this type. </p>
+     * The children property nodes have the following properties:
+     * <ul>
+     *     <li>type: The type identifier (mandatory). Can be of type 'Name' or 'Path'
+     *      See {@link HApiUtil#getTypeNode(org.apache.sling.api.resource.ResourceResolver, String)}
+     *      for the format of this value</li>
+     *     <li>description: A 'String' with the description for this property (mandatory)</li>
+     *     <li>multiple: A 'Boolean' that defines whether this property can exist multiple times on an object of this type (optional)</li>
+     * </ul>
+     *
+     * @param resolver The resource resolver
+     * @param typeNode The jcr node of the HApi type
+     * @return The HApiType
+     * @throws RepositoryException
+     */
+    public HApiType fromNode(ResourceResolver resolver, Node typeNode) throws RepositoryException;
+
+    /**
+     * Get a new instance of AttributeHelper for the type identified by 'type'
+     * @param resolver
+     * @param type See {@link #getTypeNode(org.apache.sling.api.resource.ResourceResolver, String)}
+     *             for the format of the type identifier
+     * @return
+     * @throws RepositoryException
+     */
+    public MicrodataAttributeHelper getHelper(ResourceResolver resolver, String type) throws RepositoryException;
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/MicrodataAttributeHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/MicrodataAttributeHelper.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/MicrodataAttributeHelper.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/MicrodataAttributeHelper.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.hapi;
+
+import org.apache.sling.api.resource.ResourceResolver;
+
+import java.util.Map;
+
+public interface MicrodataAttributeHelper {
+
+    /**
+     * Calls {@link #itemtypeMap()} and normalizes the map into a String of the form 'attr1="val1" attr2="val2"'
+     * @return
+     */
+    String itemtype();
+
+    /**
+     * Get a map with the HTMl attributes for a new item of the type defined through
+     * a new {@link MicrodataAttributeHelper} object
+     * <p>The key is the HTMl attribute name and the value is the HTML attribute value</p>
+     * @return
+     */
+    Map<String, String> itemtypeMap();
+
+    /**
+     * Calls {@link #itemprop(String, boolean)} with 'withType' true
+     * @param propName
+     * @return
+     */
+    String itemprop(String propName);
+
+    /**
+     * Calls {@link #itempropMap(String, boolean)} and normalizes the map into a String of the form 'attr1="val1" attr2="val2"'
+     * @param propName
+     * @param withType
+     * @return
+     */
+    String itemprop(String propName, boolean withType);
+
+    /**
+     * Get a map with the HTMl attributes for the given property of the type defined through
+     * a new {@link MicrodataAttributeHelper}
+     * <p>The key is the HTMl attribute name and the value is the HTML attribute value</p>
+     * <p> Will through a {@link HApiException}
+     * runtime exception if the property propName does not exist for the type</p>
+     * @param propName the name of the property
+     * @param withType whether to include the 'itemtype' attribute
+     * @return
+     */
+    Map<String, String> itempropMap(String propName, boolean withType);
+
+    /**
+     *  Get a map of maps with the HTMl attributes for each property of the type defined through
+     *  a new {@link MicrodataAttributeHelper}
+     *  <p>The key is the property name and the value is a map of attributes like the one returned
+     *  by {@link #itempropMap(String, boolean)}</p>
+     * @return
+     */
+    Map<String, Map<String, String>> allItemPropMap();
+
+    /**
+     * Get a map of types for each type property.
+     * <p> The key is the property name and the value is the type path identifier of that property</p>
+     * @return
+     */
+    Map<String, String> allPropTypesMap();
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/TypeView.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/TypeView.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/TypeView.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/TypeView.java Mon Aug 24 14:53:16 2015
@@ -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.hapi;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.scripting.sightly.pojo.Use;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.script.Bindings;
+import java.util.*;
+
+public class TypeView implements Use {
+    private static final Logger LOG = LoggerFactory.getLogger(TypeView.class);
+
+    private HApiUtil hapi;
+    private HApiType me;
+    private HApiType parent;
+
+    private String description;
+    private SlingHttpServletRequest request;
+    private SlingScriptHelper sling;
+    private Resource resource;
+    private ResourceResolver resourceResolver;
+
+    public void init(Bindings bindings) {
+        request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+        sling =   (SlingScriptHelper) bindings.get(SlingBindings.SLING);
+        resource = (Resource)bindings.get(SlingBindings.RESOURCE);
+        resourceResolver = request.getResourceResolver();
+
+        try {
+            activate();
+        } catch (Exception e) {
+            LOG.error("Failed to activate Use class", e);
+        }
+    }
+
+    public void activate() throws Exception {
+        hapi = sling.getService(HApiUtil.class);
+        me = hapi.fromPath(resourceResolver, resource.getPath());
+        LOG.debug("me: {}  resource: {}", me, resource.getPath());
+        description = me.getDescription();
+        parent = me.getParent();
+    }
+
+    public String getTitle() {
+        return me.getFqdn();
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public String getParentUrl() {
+        if (null != parent) {
+            return parent.getUrl();
+        } else {
+            return null;
+        }
+    }
+
+    public String getParentFqdn() {
+        if (null != parent) {
+            return parent.getFqdn();
+        } else {
+            return null;
+        }
+    }
+
+    public List<String> getParameters() {
+        return me.getParameters();
+    }
+
+    public List<HApiProperty> getProps() {
+        List<HApiProperty> props = new ArrayList<HApiProperty>(me.getAllProperties().values());
+        LOG.debug("props: ", props);
+        return props;
+    }
+
+    public boolean getHasProps() {
+        return getProps().size() > 0;
+    }
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/AbstractHapiTypeImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/AbstractHapiTypeImpl.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/AbstractHapiTypeImpl.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/AbstractHapiTypeImpl.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * ADOBE CONFIDENTIAL
+ * __________________
+ *
+ *  Copyright 2014 Adobe Systems Incorporated
+ *  All Rights Reserved.
+ *
+ * NOTICE:  All information contained herein is, and remains
+ * the property of Adobe Systems Incorporated and its suppliers,
+ * if any.  The intellectual and technical concepts contained
+ * herein are proprietary to Adobe Systems Incorporated and its
+ * suppliers and may be covered by U.S. and Foreign Patents,
+ * patents in process, and are protected by trade secret or copyright law.
+ * Dissemination of this information or reproduction of this material
+ * is strictly forbidden unless prior written permission is obtained
+ * from Adobe Systems Incorporated.
+ **************************************************************************/
+package org.apache.sling.hapi.impl;
+
+import org.apache.sling.hapi.HApiProperty;
+import org.apache.sling.hapi.HApiType;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AbstractHapiTypeImpl implements HApiType {
+
+    public static final String ABSTRACT = "Abstract";
+    private final String name;
+
+    public AbstractHapiTypeImpl(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getDescription() {
+        return ABSTRACT;
+    }
+
+    @Override
+    public String getPath() {
+        return null;
+    }
+
+    @Override
+    public String getUrl() {
+        return null;
+    }
+
+    @Override
+    public String getFqdn() {
+        return null;
+    }
+
+    @Override
+    public List<String> getParameters() {
+        return null;
+    }
+
+    @Override
+    public Map<String, HApiProperty> getProperties() {
+        return new HashMap<String, HApiProperty>();
+    }
+
+    @Override
+    public Map<String, HApiProperty> getAllProperties() {
+        return getProperties();
+    }
+
+    @Override
+    public HApiType getParent() {
+        return null;
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return true;
+    }
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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.hapi.impl;
+
+import org.apache.sling.hapi.HApiType;
+import org.apache.sling.hapi.HApiProperty;
+
+/**
+ * {@inheritDoc}
+ */
+public class HApiPropertyImpl implements HApiProperty {
+    private String name;
+    private String description;
+    private HApiType type;
+    private Boolean multiple;
+
+    /**
+     *
+     * @param name
+     * @param description
+     * @param type
+     * @param multiple
+     */
+    public HApiPropertyImpl(String name, String description, HApiType type, Boolean multiple) {
+        this.name = name;
+        this.description = description;
+        this.type = type;
+        this.multiple = multiple;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public HApiType getType() {
+        return type;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setType(HApiType type) {
+        this.type = type;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean getMultiple() {
+        return multiple;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setMultiple(Boolean multiple) {
+        this.multiple = multiple;
+    }
+
+    @Override
+    public String toString() {
+        return "HApiProperty{" +
+                "name='" + name + '\'' +
+                ", description='" + description + '\'' +
+                ", type=" + type +
+                ", multiple=" + multiple +
+                '}';
+    }
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * 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.hapi.impl;
+
+import org.apache.sling.hapi.HApiProperty;
+import org.apache.sling.hapi.HApiType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.*;
+
+/**
+ * {@inheritDoc}
+ */
+public class HApiTypeImpl implements HApiType {
+
+    public static final Logger LOG = LoggerFactory.getLogger(HApiTypeImpl.class);
+
+    private final HApiType parent;
+
+    private String name;
+
+    private String description;
+    private String path;
+    private String fqdn;
+    private List<String> parameters;
+    private Map<String, HApiProperty> properties;
+    private boolean isAbstract;
+
+    /**
+     * A new HApiType
+     * @param name
+     * @param description
+     * @param path
+     * @param fqdn
+     * @param parameters
+     * @param properties
+     * @param parent
+     */
+    public HApiTypeImpl(String name, String description, String path, String fqdn, List<String> parameters, Map<String,
+            HApiProperty> properties, HApiType parent, boolean isAbstract) {
+        this.name = name;
+        this.description = description;
+        this.path = path;
+        this.fqdn = fqdn;
+        this.parameters = parameters;
+        this.properties = properties;
+        this.parent = parent;
+        this.isAbstract = isAbstract;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getUrl() {
+        return getPath() + ".html";
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getFqdn() {
+        return fqdn;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public List<String> getParameters() {
+        return parameters;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Map<String, HApiProperty> getProperties() {
+        return properties;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Map<String, HApiProperty> getAllProperties() {
+        Map<String, HApiProperty> allProps = new HashMap<String, HApiProperty>();
+        LOG.debug("parent: {}", parent);
+        if (null != parent) {
+            Map<String, HApiProperty> parentProps = parent.getAllProperties();
+            LOG.debug("parent props: {}", parentProps);
+            allProps.putAll(parentProps);
+        }
+        allProps.putAll(getProperties());
+        return allProps;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public HApiType getParent() {
+        return parent;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAbstract() {
+        return isAbstract;
+    }
+
+}

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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.hapi.impl;
+
+import org.apache.sling.hapi.HApiProperty;
+import org.apache.sling.hapi.HApiType;
+import org.apache.sling.hapi.MicrodataAttributeHelper;
+import org.apache.sling.hapi.HApiUtil;
+import org.apache.felix.scr.annotations.*;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.*;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import java.util.*;
+
+
+@Component(label = "Apache Sling Hypermedia API tools", metatype = true)
+@Service()
+
+public class HApiUtilImpl implements HApiUtil {
+
+    @Property(label = "HApi Resource Type", cardinality = 0, value = DEFAULT_RESOURCE_TYPE)
+    public static final String HAPI_RESOURCE_TYPE = "org.apache.sling.hapi.tools.resourcetype";
+
+
+    @Property(label = "HApi Types Search Paths", cardinality=50, value = {"/libs/sling/hapi/types"})
+    public static final String HAPI_PATHS = "org.apache.sling.hapi.tools.searchpaths";
+
+    public static String resourceType;
+    public static String[] hApiPaths;
+
+
+    @Activate
+    private void activate(ComponentContext context, Map<String, Object> configuration) {
+        resourceType = PropertiesUtil.toString(configuration.get(HAPI_RESOURCE_TYPE), DEFAULT_RESOURCE_TYPE);
+        hApiPaths = PropertiesUtil.toStringArray(configuration.get(HAPI_PATHS));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Node getTypeNode(ResourceResolver resolver, String type) throws RepositoryException {
+        Session session = resolver.adaptTo(Session.class);
+
+        // Try to resolve the resource as a path
+        Resource res = resolver.getResource(type);
+        if (null != res) {
+            LOG.debug("res = " + res.getName() + " " + res.getPath());
+            return res.adaptTo(Node.class);
+        } else {
+            for (String path : new HashSet<String>(Arrays.asList(hApiPaths))) {
+                // Remove trailing slash from path
+                path = (path.endsWith("/")) ? path.substring(0,path.length() - 1) : path;
+
+                // Get the query manager for the session
+                QueryManager queryManager = session.getWorkspace().getQueryManager();
+
+                // Build query for the search paths
+                StringBuilder queryString = new StringBuilder("SELECT * FROM [nt:unstructured] WHERE ");
+                queryString.append(String.format("ISDESCENDANTNODE([%s]) ", path));
+                queryString.append(String.format("AND [sling:resourceType]='%s' AND fqdn = '%s'", resourceType, type));
+
+                // Execute query
+                Query query = queryManager.createQuery(queryString.toString(), Query.JCR_SQL2);
+                LOG.debug("Querying HAPi: {}", queryString.toString());
+                QueryResult result = query.execute();
+
+                NodeIterator nodeIter = result.getNodes();
+                if (nodeIter.hasNext()) {
+                    return nodeIter.nextNode();
+                } else {
+                    // continue
+                }
+            }
+
+            // Type has to be abstract
+            return null;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public HApiType fromPath(ResourceResolver resolver, String type) throws RepositoryException {
+        Node typeNode = this.getTypeNode(resolver, type);
+        LOG.debug("typeNode=" + typeNode);
+        if (null == typeNode) {
+            return new AbstractHapiTypeImpl(type);
+        } else {
+            return fromNode(resolver, typeNode);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public HApiType fromNode(ResourceResolver resolver, Node typeNode) throws RepositoryException {
+        if (null == typeNode) return null;
+        String name = typeNode.getProperty("name").getValue().getString();
+        String description = typeNode.getProperty("description").getValue().getString();
+        String path = typeNode.getPath();
+        String fqdn = typeNode.getProperty("fqdn").getValue().getString();
+
+        // get parent if it exists
+        HApiType parent = null;
+        String parentPath = typeNode.hasProperty("extends") ? typeNode.getProperty("extends").getString() : null;
+        if (null != parentPath) {
+            parent = this.fromPath(resolver, parentPath);
+        }
+
+        // get parameters
+        Value[] parameterValues = typeNode.hasProperty("parameters") ? typeNode.getProperty("parameters").getValues() : new Value[]{};
+        List<String> parameters = new ArrayList<String>(parameterValues.length);
+
+        for (Value p : Arrays.asList(parameterValues)) {
+            parameters.add(p.getString());
+        }
+
+        // Get properties
+        Map<String, HApiProperty> properties = new HashMap<String, HApiProperty>();
+
+        // Add the properties from this node
+        Iterator<Node> it = typeNode.getNodes();
+        while (it.hasNext()) {
+            Node propNode = it.next();
+            String propName  = propNode.getName();
+            String propDescription = propNode.hasProperty("description") ? propNode.getProperty("description").getString() : "";
+
+            // TODO: maybe create adapter and use adaptTo()
+            // TODO: this could be slow, the types can be instantiated externally in a service activate()
+            String type = propNode.getProperty("type").getValue().getString();
+            HApiType propType = this.fromPath(resolver, type);
+            Boolean propMultiple = propNode.hasProperty("multiple") ? propNode.getProperty("multiple").getBoolean() : false;
+
+            HApiProperty prop = new HApiPropertyImpl(propName, propDescription, propType, propMultiple);
+            properties.put(prop.getName(), prop);
+        }
+        return new HApiTypeImpl(name, description, path, fqdn, parameters, properties, parent, false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MicrodataAttributeHelper getHelper(ResourceResolver resolver, String type) throws RepositoryException {
+        return new MicrodataAttributeHelperImpl(resolver, TypesCache.getInstance(this).getType(resolver, type));
+    }
+}
+
+/**
+ * <p>Cache for types</p>
+ *
+ */
+class TypesCache {
+    private static final Logger LOG = LoggerFactory.getLogger(TypesCache.class);
+    Map<String, HApiType> types;
+    private static TypesCache singleton = null;
+    private HApiUtil hApiUtil;
+
+    public static TypesCache getInstance(HApiUtil hApiUtil) {
+        if (null == singleton) {
+            singleton = new TypesCache(hApiUtil);
+        }
+        LOG.debug("singleton: {}", singleton);
+        return singleton;
+    }
+
+    private TypesCache(HApiUtil hApiUtil) {
+        this.types = new HashMap<String, HApiType>();
+        this.hApiUtil = hApiUtil;
+    }
+
+    public HApiType getType(ResourceResolver resolver, String typePath) throws RepositoryException {
+        if (types.containsKey(typePath)) {
+            return this.types.get(typePath);
+        } else {
+
+            HApiType type = hApiUtil.fromPath(resolver, typePath);
+            types.put(type.getPath(), type);
+            return type;
+        }
+    }
+
+    public void addType(HApiType type) {
+        this.types.put(type.getPath(), type);
+    }
+}
+

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * 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.hapi.impl;
+
+import org.apache.sling.hapi.HApiProperty;
+import org.apache.sling.hapi.HApiType;
+import org.apache.sling.hapi.MicrodataAttributeHelper;
+import org.apache.sling.hapi.HApiException;
+import org.apache.sling.api.resource.ResourceResolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Helper class for HTML microdata attributes
+ */
+public class MicrodataAttributeHelperImpl implements MicrodataAttributeHelper {
+    private final ResourceResolver resolver;
+    HApiType type;
+
+    /**
+     * Get a new microdata html attributes helper for the given HApiType object.
+     * <p>Provides convenience methods to get the html attributes needed for instrumenting the markup with a Hypermedia API</p>
+     * @param resolver
+     * @param type
+     */
+    public MicrodataAttributeHelperImpl(ResourceResolver resolver, HApiType type) {
+        this.resolver = resolver;
+        this.type = type;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String itemtype() {
+        return itemtypeMap().toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Map<String, String> itemtypeMap() {
+        Map<String, String> attrMap = new AttrMap(2);
+        attrMap.put("itemtype", type.getPath() + ".html");
+        attrMap.put("itemscope", !type.getAllProperties().isEmpty());
+        
+        return attrMap;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String itemprop(String propName) {
+        return itemprop(propName, true);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String itemprop(String propName, boolean withType) {
+        return itempropMap(propName, withType).toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Map<String, String> itempropMap(String propName, boolean withType) {
+        HApiProperty prop = this.type.getAllProperties().get(propName);
+        if (null == prop) throw new HApiException("Property " + propName + " does not exist for type " + type.getPath());
+
+        Map<String, String> attrMap = new AttrMap(3);
+        attrMap.put("itemprop", propName);
+        if (withType) {
+            attrMap.putAll(new MicrodataAttributeHelperImpl(resolver, prop.getType()).itemtypeMap());
+        }
+        return attrMap;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Map<String, Map<String, String>> allItemPropMap() {
+        Map<String, Map<String, String>> m = new PropMap(type);
+        for (String prop: type.getAllProperties().keySet()) {
+            m.put(prop, itempropMap(prop, true));
+        }
+        return m;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Map<String, String> allPropTypesMap() {
+        Map<String, HApiProperty> props = type.getAllProperties();
+        Map<String, String> types = new HashMap<String, String>(props.size());
+        for (String propName : props.keySet()) {
+            types.put(propName, props.get(propName).getType().getPath());
+        }
+        return types;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    private class PropMap extends HashMap<String, Map<String, String>> {
+
+        private final HApiType type;
+
+        public PropMap(HApiType type) {
+            super();
+            this.type = type;
+        }
+
+        @Override
+        public Map<String, String> get(Object key) {
+            Map<String, String> val = super.get(key);
+            if (null == val) {
+                throw new HApiException("Property " + key + " does not exist for type " + type.getPath());
+            }
+            return val;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    private class AttrMap extends HashMap<String, String> {
+
+        public AttrMap(int i) {
+            super(i);
+        }
+
+        public AttrMap() {
+            super();
+        }
+
+        public AttrMap(int initialCapacity, float loadFactor) {
+            super(initialCapacity, loadFactor);
+        }
+
+        @Override
+        public String toString() {
+            String norm = "";
+            for (Map.Entry<String, String> entry : this.entrySet()) {
+                norm += entry.getKey() + "=\"" + entry.getValue() + "\"" + " ";
+            }
+            return norm;
+        }
+    }
+}
+

Added: sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/package-info.java?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/package-info.java (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/java/org/apache/sling/hapi/package-info.java Mon Aug 24 14:53:16 2015
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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.hapi;
+
+import aQute.bnd.annotation.Version;

Added: sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html Mon Aug 24 14:53:16 2015
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~ 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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<html data-sly-use.type="org.apache.sling.hapi.TypeView" lang="${type.lang}">
+
+    <head>
+        <meta charset="utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+
+        <!-- Bootstrap -->
+        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
+
+        <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+        <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+        <!--[if lt IE 9]>
+          <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+          <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+        <![endif]-->
+
+        <title>${type.title}</title>
+
+    </head>
+    <body>
+        <div class="container">
+
+            <h1>${type.title}</h1>
+            <div>
+                <p>${type.description}</p>
+            </div>
+            <h2 data-sly-test.parentUrl="${type.parentUrl}"> extends
+                <a href="${parentUrl}" >${type.parentFqdn}</a>
+            </h2>
+            <h3 data-sly-test="${type.parameters}">Parameters: </h3>
+                <ul data-sly-list.param="${type.parameters}" title="Parameters" class="list-inline">
+                <li>${param}</li>
+            </ul>
+            <h3>Properties: </h3>
+            <table class="table" data-sly-test.props="${type.props}">
+                <thead>
+                    <tr>
+                        <th>Property</th>
+                        <th>Expected Type</th>
+                        <th>Multiple</th>
+                        <th>Description</th>
+                    </tr>
+                </thead>
+                <tbody data-sly-list.prop="${type.props}">
+                    <tr>
+                        <th>${prop.name}</th>
+                        <td>
+                            <a href="${prop.type.url}">${prop.type.name}</a>
+                        </td>
+                        <td>${prop.multiple}</td>
+                        <td>${prop.description}</td>
+                    </tr>
+                </tbody>
+            </table>
+            <div data-sly-test="${!props}">None</div>
+        </div>
+    </body>
+</html>

Added: sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/types.json
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/types.json?rev=1697419&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/types.json (added)
+++ sling/trunk/contrib/extensions/hapi/core/src/main/resources/SLING-INF/libs/sling/hapi/types.json Mon Aug 24 14:53:16 2015
@@ -0,0 +1,110 @@
+{
+  "jcr:primaryType": "sling:Folder",
+  "image": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "An image src",
+    "fqdn": "org.apache.sling.hapi.common.Image",
+    "name": "Image",
+    "sling:resourceType": "sling/hapi/components/type"
+  },
+  "date": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "a date value; format has to be described in each property of this type",
+    "fqdn": "org.apache.sling.hapi.common.Date",
+    "name": "Date",
+    "sling:resourceType": "sling/hapi/components/type"
+  },
+  "text": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "A text value",
+    "fqdn": "org.apache.sling.hapi.common.Text",
+    "name": "Text",
+    "sling:resourceType": "sling/hapi/components/type"
+  },
+  "collection": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "Generic collection type. Can be parameterized with a generic type.",
+    "fqdn": "org.apache.sling.hapi.common.collection",
+    "name": "collection",
+    "parameters": [
+      "T"
+    ],
+    "sling:resourceType": "sling/hapi/components/type",
+    "item": {
+      "jcr:primaryType": "nt:unstructured",
+      "description": "",
+      "type": "T",
+      "multiple": true
+    }
+  },
+  "boolean": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "true or false",
+    "fqdn": "org.apache.sling.hapi.common.Boolean",
+    "name": "Boolean",
+    "sling:resourceType": "sling/hapi/components/type"
+  },
+  "pair": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "The key-value pair. Usually used to indicate a Map entry.",
+    "fqdn": "org.apache.sling.hapi.common.pair",
+    "name": "pair",
+    "parameters": [
+      "K",
+      "V"
+    ],
+    "sling:resourceType": "sling/hapi/components/type",
+    "key": {
+      "jcr:primaryType": "nt:unstructured",
+      "description": "The key of the pair",
+      "type": "K",
+      "multiple": false
+    },
+    "value": {
+      "jcr:primaryType": "nt:unstructured",
+      "description": "The value of the pair",
+      "type": "V",
+      "multiple": false
+    }
+  },
+  "number": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "A number value",
+    "fqdn": "org.apache.sling.hapi.common.Number",
+    "name": "Number",
+    "sling:resourceType": "sling/hapi/components/type"
+  },
+  "demo_type": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "A demo HApi type to show a more advanced structure",
+    "demo_description": {
+      "jcr:primaryType": "nt:unstructured",
+      "description": "The description of the demo object",
+      "type": "org.apache.sling.hapi.common.Text",
+      "multiple": false
+    },
+    "fqdn": "org.apache.sling.hapi.common.collection",
+    "name": "collection",
+    "parameters": [],
+    "sling:resourceType": "sling/hapi/components/type",
+    "title": {
+      "jcr:primaryType": "nt:unstructured",
+      "description": "The title of the demo object",
+      "type": "org.apache.sling.hapi.common.Text",
+      "multiple": false
+    },
+    "entries": {
+      "jcr:primaryType": "nt:unstructured",
+      "description": "An entry of type pair in the demo object",
+      "type": "org.apache.sling.hapi.common.pair",
+      "multiple": true
+    }
+  },
+  "url": {
+    "jcr:primaryType": "nt:unstructured",
+    "description": "A URL value type",
+    "fqdn": "org.apache.sling.hapi.common.URL",
+    "name": "URL",
+    "sling:resourceType": "sling/hapi/components/type"
+  }
+}

Propchange: sling/trunk/contrib/extensions/hapi/pics/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Aug 24 14:53:16 2015
@@ -0,0 +1,14 @@
+target
+bin
+derby.log
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+
+
+

Added: sling/trunk/contrib/extensions/hapi/pics/browser1.png
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/pics/browser1.png?rev=1697419&view=auto
==============================================================================
Binary file - no diff available.

Propchange: sling/trunk/contrib/extensions/hapi/pics/browser1.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: sling/trunk/contrib/extensions/hapi/pics/browser2.png
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/pics/browser2.png?rev=1697419&view=auto
==============================================================================
Binary file - no diff available.

Propchange: sling/trunk/contrib/extensions/hapi/pics/browser2.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: sling/trunk/contrib/extensions/hapi/pics/python1.png
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/pics/python1.png?rev=1697419&view=auto
==============================================================================
Binary file - no diff available.

Propchange: sling/trunk/contrib/extensions/hapi/pics/python1.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: sling/trunk/contrib/extensions/hapi/pics/python2.png
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/pics/python2.png?rev=1697419&view=auto
==============================================================================
Binary file - no diff available.

Propchange: sling/trunk/contrib/extensions/hapi/pics/python2.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: sling/trunk/contrib/extensions/hapi/pics/python3.png
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/hapi/pics/python3.png?rev=1697419&view=auto
==============================================================================
Binary file - no diff available.

Propchange: sling/trunk/contrib/extensions/hapi/pics/python3.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream