SLING-5810 [HApi] Add support for a collection of types
SLING-5807 [HApi] Annotate the html rendering a type with HApi
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1750096 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/hapi/HApiType.java b/src/main/java/org/apache/sling/hapi/HApiType.java
index e562187..a8f647a 100644
--- a/src/main/java/org/apache/sling/hapi/HApiType.java
+++ b/src/main/java/org/apache/sling/hapi/HApiType.java
@@ -41,13 +41,13 @@
String getDescription();
/**
- * The JCR path of the node representing this type
+ * The path of the Resource representing this type
* @return
*/
String getPath();
/**
- * The URL of the node representing this type
+ * The external URL of the node representing this type
* @return
*/
String getUrl();
diff --git a/src/main/java/org/apache/sling/hapi/HApiTypesCollection.java b/src/main/java/org/apache/sling/hapi/HApiTypesCollection.java
new file mode 100644
index 0000000..c995d97
--- /dev/null
+++ b/src/main/java/org/apache/sling/hapi/HApiTypesCollection.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.Collection;
+
+public interface HApiTypesCollection extends Collection<HApiType> {
+ /**
+ * The name of this type collection
+ * @return
+ */
+ String getName();
+
+
+ /**
+ * The description of this type collection
+ * @return
+ */
+ String getDescription();
+
+ /**
+ * The Resource path of this type collection
+ * @return
+ */
+ String getPath();
+
+ /**
+ * The external URL of the type collection
+ * @return
+ */
+ String getUrl();
+
+ /**
+ * The fully qualified domain name of this type collection
+ * @return
+ */
+ String getFqdn();
+
+}
diff --git a/src/main/java/org/apache/sling/hapi/HApiUtil.java b/src/main/java/org/apache/sling/hapi/HApiUtil.java
index 822c52d..c2b336a 100644
--- a/src/main/java/org/apache/sling/hapi/HApiUtil.java
+++ b/src/main/java/org/apache/sling/hapi/HApiUtil.java
@@ -28,6 +28,15 @@
public interface HApiUtil {
String DEFAULT_RESOURCE_TYPE = "sling/hapi/components/type";
+ String RESOURCE_TYPE = "org.apache.sling.hapi.tools.resourcetype";
+
+ String DEFAULT_COLLECTION_RESOURCE_TYPE = "sling/hapi/components/typescollection";
+ String COLLECTION_RESOURCE_TYPE = "org.apache.sling.hapi.tools.collectionresourcetype";
+
+ String SEARCH_PATHS = "org.apache.sling.hapi.tools.searchpaths";
+
+ String DEFAULT_SERVER_URL = "http://localhost:8080";
+ String EXTERNAL_URL = "org.apache.sling.hapi.tools.externalurl";
/**
* <p>Get a HApi type jcr node from a type identifier.</p>
@@ -48,7 +57,8 @@
/**
* <p>Get a HApi type Resource from a type identifier.</p>
* <p>The Resource 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>
+ * {@see HAPI_PATHS} config and the sling:resourceType should be set to the value defined by the {@see HapiUtil#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,
@@ -60,6 +70,22 @@
Resource getTypeResource(ResourceResolver resolver, String type) throws RepositoryException;
/**
+ * <p>Get a HApi type collection Resource from a collection identifier.</p>
+ * <p>The Resource 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 HapiUtil#COLLECTION_RESOURCE_TYPE} config</p>
+ * <p>The first result is returned</p>
+ * @param resolver The sling resource resolver object
+ * @param collection The collection 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, collection is
+ * treated like a fully qualified domain name, which has to match the "fqdn" property on the Resource which
+ * represents the type.
+ * @return The first Resource that matches that collection or null if none is found.
+ * @throws RepositoryException
+ */
+ Resource getTypeCollectionResource(ResourceResolver resolver, String collection) 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>
@@ -136,6 +162,36 @@
HApiType fromResource(ResourceResolver resolver, Resource typeResource) throws RepositoryException;
/**
+ * <p>Get a {@link HApiTypesCollection} object from a {@link org.apache.sling.api.resource.Resource}.</p>
+ * The Resource has the following properties:
+ * <ul>
+ * <li>name: A 'Name' of the type collection (mandatory)</li>
+ * <li>description: A 'String' with the description text for this type collection (mandatory)</li>
+ * <li>fqdn: A 'String' with the fully qualified domain name; A namespace like a java package (mandatory)</li>
+ * </ul>
+ *
+ * <p> The types collection will be populated with direct child Resources of the {{collectionResource}},
+ * which have the resourceType equal to the value of the {@link HApiUtil#RESOURCE_TYPE} property
+ *
+ * @param resolver The resource resolver
+ * @param collectionResource The sling Resource of the HApi type collection
+ * @return The HApiTypesCollection
+ * @throws RepositoryException
+ */
+ HApiTypesCollection collectionFromResource(ResourceResolver resolver, Resource collectionResource) throws RepositoryException;
+
+ /**
+ * <p>Get a {@link HApiTypesCollection} object from a path String.</p>
+ * <p>{@see HApiUtil#collectionFromResource}</p>
+ *
+ * @param resolver The resource resolver
+ * @param collectionPath The sling resource path of the HApi type collection
+ * @return The HApiTypesCollection
+ * @throws RepositoryException
+ */
+ HApiTypesCollection collectionFromPath(ResourceResolver resolver, String collectionPath) 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)}
diff --git a/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java b/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java
index cb3a280..8ea4267 100644
--- a/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java
+++ b/src/main/java/org/apache/sling/hapi/impl/HApiPropertyImpl.java
@@ -105,7 +105,7 @@
return "HApiProperty{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
- ", type=" + type +
+ ", type=" + type.getPath() +
", multiple=" + multiple +
'}';
}
diff --git a/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java b/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java
index f0ec536..516229b 100644
--- a/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java
+++ b/src/main/java/org/apache/sling/hapi/impl/HApiTypeImpl.java
@@ -169,6 +169,6 @@
@Override
public String toString() {
- return this.getName() + ": Properties: " + this.getProperties();
+ return this.getName() + "(" + this.getPath() + "): Properties: " + this.getProperties();
}
}
diff --git a/src/main/java/org/apache/sling/hapi/impl/HApiTypesCollectionImpl.java b/src/main/java/org/apache/sling/hapi/impl/HApiTypesCollectionImpl.java
new file mode 100644
index 0000000..a9cb23e
--- /dev/null
+++ b/src/main/java/org/apache/sling/hapi/impl/HApiTypesCollectionImpl.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.HApiTypesCollection;
+
+import java.util.ArrayList;
+
+public class HApiTypesCollectionImpl extends ArrayList<HApiType> implements HApiTypesCollection {
+
+ private final String name;
+ private final String description;
+ private final String path;
+ private final String serverUrl;
+ private final String fqdn;
+
+ /**
+ *
+ * @param name The name of the collection.
+ * @param description The description of the collection
+ * @param path The path of the resource describing the collection
+ */
+ public HApiTypesCollectionImpl(String name, String description, String serverUrl, String path, String fqdn) {
+ this.name = name;
+ this.description = description;
+ this.serverUrl = serverUrl.substring(0, serverUrl.length() - (serverUrl.endsWith("/") ? 1 : 0));
+ this.path = path;
+ this.fqdn = fqdn;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getUrl() {
+ return this.serverUrl + getPath() + ".html";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getFqdn() {
+ return fqdn;
+ }
+}
diff --git a/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java b/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java
index d657710..f3d5e33 100644
--- a/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java
+++ b/src/main/java/org/apache/sling/hapi/impl/HApiUtilImpl.java
@@ -42,10 +42,7 @@
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.apache.sling.hapi.HApiProperty;
-import org.apache.sling.hapi.HApiType;
-import org.apache.sling.hapi.HApiUtil;
-import org.apache.sling.hapi.MicrodataAttributeHelper;
+import org.apache.sling.hapi.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,17 +54,19 @@
private final Logger LOG = LoggerFactory.getLogger(HApiUtil.class);
@Property(label = "HApi Resource Type", cardinality = 0, value = DEFAULT_RESOURCE_TYPE)
- public static final String HAPI_RESOURCE_TYPE = "org.apache.sling.hapi.tools.resourcetype";
+ public static final String HAPI_RESOURCE_TYPE = RESOURCE_TYPE;
+
+ @Property(label = "HApi Collection Resource Type", cardinality = 0, value = DEFAULT_COLLECTION_RESOURCE_TYPE)
+ private static final String HAPI_COLLECTION_RESOURCE_TYPE = COLLECTION_RESOURCE_TYPE;
@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 final String HAPI_PATHS = SEARCH_PATHS;
-
- private static final String DEFAULT_SERVER_URL = "http://localhost:8080";
@Property(label = "External server URL", cardinality = 0, value = DEFAULT_SERVER_URL)
- public static final String HAPI_EXTERNAL_URL = "org.apache.sling.hapi.tools.externalurl";
+ public static final String HAPI_EXTERNAL_URL = EXTERNAL_URL;
public static String resourceType;
+ private String collectionResourceType;
public static String[] hApiPaths;
public static String serverContextPath;
@@ -75,6 +74,8 @@
@Activate
private void activate(Map<String, Object> configuration) {
resourceType = PropertiesUtil.toString(configuration.get(HAPI_RESOURCE_TYPE), DEFAULT_RESOURCE_TYPE);
+ collectionResourceType = PropertiesUtil.toString(configuration.get(HAPI_COLLECTION_RESOURCE_TYPE),
+ DEFAULT_COLLECTION_RESOURCE_TYPE);
hApiPaths = PropertiesUtil.toStringArray(configuration.get(HAPI_PATHS));
serverContextPath = PropertiesUtil.toString(configuration.get(HAPI_EXTERNAL_URL), DEFAULT_SERVER_URL);
}
@@ -93,10 +94,24 @@
*/
@Override
public Resource getTypeResource(ResourceResolver resolver, String type) throws RepositoryException {
+ return getFqdnResource(resolver, type, resourceType);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Resource getTypeCollectionResource(ResourceResolver resolver, String collection) throws RepositoryException {
+ return getFqdnResource(resolver, collection, collectionResourceType);
+ }
+
+
+
+ private Resource getFqdnResource(ResourceResolver resolver, String fqdn, String resType) throws RepositoryException {
Session session = resolver.adaptTo(Session.class);
// Try to resolve the resource as a path
- Resource res = resolver.getResource(type);
+ Resource res = resolver.getResource(fqdn);
if (null != res) {
LOG.debug("res = " + res.getName() + " " + res.getPath());
return res;
@@ -111,11 +126,11 @@
// 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));
+ queryString.append(String.format("AND [sling:resourceType]='%s' AND fqdn = '%s'", resType, fqdn));
// Execute query
Query query = queryManager.createQuery(queryString.toString(), Query.JCR_SQL2);
- LOG.debug("Querying HAPi: {}", queryString.toString());
+ LOG.debug("Querying HApi: {}", queryString.toString());
QueryResult result = query.execute();
NodeIterator nodeIter = result.getNodes();
@@ -177,6 +192,7 @@
}
HApiTypeImpl newType = new HApiTypeImpl(name, description, serverContextPath, path, fqdn, parameters, null, null, false);
TypesCache.getInstance(this).addType(newType);
+ LOG.debug("Inserted type {} to cache: {}", newType, TypesCache.getInstance(this));
try {
@@ -184,7 +200,7 @@
HApiType parent = null;
String parentPath = resProps.get("extends", (String) null);
if (null != parentPath) {
- parent = TypesCache.getInstance(this).getType(resolver, parentPath);
+ parent = TypesCache.getInstance(this).getType(resolver, getTypeResource(resolver, parentPath));
}
// Get properties
@@ -194,8 +210,12 @@
String propName = res.getName();
String propDescription = resValueMap.get("description", "");
- String typePath = resValueMap.get("type", (String) null);
- HApiType propType = TypesCache.getInstance(this).getType(resolver, typePath);
+ String typeFqdnOrPath = resValueMap.get("type", (String) null);
+ Resource propTypeResource = getTypeResource(resolver, typeFqdnOrPath);
+ HApiType propType = (null != propTypeResource)
+ ? TypesCache.getInstance(this).getType(resolver, propTypeResource)
+ : new AbstractHapiTypeImpl(typeFqdnOrPath);
+ LOG.debug("Fetched type {} from cache", propType);
Boolean propMultiple = resValueMap.get("multiple", false);
HApiProperty prop = new HApiPropertyImpl(propName, propDescription, propType, propMultiple);
@@ -223,8 +243,43 @@
* {@inheritDoc}
*/
@Override
+ public HApiTypesCollection collectionFromResource(ResourceResolver resolver, Resource collectionResource) throws RepositoryException {
+ if (null == collectionResource) return null;
+ ValueMap resProps = collectionResource.adaptTo(ValueMap.class);
+ String name = resProps.get("name", (String) null);
+ String description = resProps.get("description", (String) null);
+ String path = collectionResource.getPath();
+ String fqdn = resProps.get("fqdn", (String) null);
+ HApiTypesCollection collection = new HApiTypesCollectionImpl(name, description, serverContextPath, path, fqdn); // no types yet
+
+ // iterate the children of the resource and add to the collection
+ for (Resource typeRes : collectionResource.getChildren()) {
+ if (typeRes.isResourceType(resourceType)) {
+ // child resource if a hapi type, add it to the collection
+ LOG.debug("Trying to add type from resource: {} to the collection", typeRes);
+ HApiType type = fromResource(resolver, typeRes);
+ collection.add(type);
+ LOG.debug("Added type {} to the collection.", type);
+ }
+ }
+ LOG.debug("Collection: {}", collection);
+ return collection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public HApiTypesCollection collectionFromPath(ResourceResolver resolver, String collectionPath) throws RepositoryException {
+ return collectionFromResource(resolver, this.getTypeCollectionResource(resolver, collectionPath));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public MicrodataAttributeHelper getHelper(ResourceResolver resolver, String type) throws RepositoryException {
- return new MicrodataAttributeHelperImpl(resolver, TypesCache.getInstance(this).getType(resolver, type));
+ return new MicrodataAttributeHelperImpl(resolver, TypesCache.getInstance(this).getType(resolver, getTypeResource(resolver, type)));
}
}
@@ -234,15 +289,20 @@
*/
class TypesCache {
private static final Logger LOG = LoggerFactory.getLogger(TypesCache.class);
- Map<String, HApiType> types;
private static TypesCache singleton = null;
+
private HApiUtil hApiUtil;
+ Map<String, HApiType> types;
public static TypesCache getInstance(HApiUtil hApiUtil) {
if (null == singleton) {
singleton = new TypesCache(hApiUtil);
+ LOG.debug("Created new cache instance");
+ } else {
+ singleton.hApiUtil = hApiUtil;
}
- LOG.debug("singleton: {}", singleton);
+
+ LOG.debug("type cache singleton: {}", singleton);
return singleton;
}
@@ -251,13 +311,18 @@
this.hApiUtil = hApiUtil;
}
- public HApiType getType(ResourceResolver resolver, String typePath) throws RepositoryException {
- if (types.containsKey(typePath)) {
+ public HApiType getType(ResourceResolver resolver, Resource typeResource) throws RepositoryException {
+ if (null == typeResource) return new AbstractHapiTypeImpl("Abstract");
+
+ String typePath = typeResource.getPath();
+ LOG.debug("Trying to get type {}; cache: {}", typePath, types);
+ if (this.types.containsKey(typePath)) {
+ LOG.debug("Returning type {} from cache", typePath);
return this.types.get(typePath);
} else {
-
+ LOG.debug("Creating type {} in cache", typePath);
HApiType type = hApiUtil.fromPath(resolver, typePath);
- types.put(type.getPath(), type);
+ this.types.put(type.getPath(), type);
return type;
}
}
@@ -269,5 +334,11 @@
public void removeType(String path) {
this.types.remove(path);
}
+
+ @Override
+ public String toString() {
+ return "TypesCache{" +
+ "types=" + types + "}";
+ }
}
diff --git a/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java b/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java
index 85ae13d..b78ef5d 100644
--- a/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java
+++ b/src/main/java/org/apache/sling/hapi/impl/MicrodataAttributeHelperImpl.java
@@ -23,6 +23,8 @@
import org.apache.sling.hapi.MicrodataAttributeHelper;
import org.apache.sling.hapi.HApiException;
import org.apache.sling.api.resource.ResourceResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
@@ -32,6 +34,7 @@
* Helper class for HTML microdata attributes
*/
public class MicrodataAttributeHelperImpl implements MicrodataAttributeHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(MicrodataAttributeHelperImpl.class);
private final ResourceResolver resolver;
HApiType type;
@@ -134,6 +137,7 @@
public Map<String, String> get(Object key) {
Map<String, String> val = super.get(key);
if (null == val) {
+ LOG.debug("type = {}", type);
throw new HApiException("Property " + key + " does not exist for type " + type.getPath());
}
return val;
diff --git a/src/main/java/org/apache/sling/hapi/sightly/TypesCollectionView.java b/src/main/java/org/apache/sling/hapi/sightly/TypesCollectionView.java
new file mode 100644
index 0000000..3916cfc
--- /dev/null
+++ b/src/main/java/org/apache/sling/hapi/sightly/TypesCollectionView.java
@@ -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.sightly;
+
+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.hapi.HApiType;
+import org.apache.sling.hapi.HApiTypesCollection;
+import org.apache.sling.hapi.HApiUtil;
+import org.apache.sling.scripting.sightly.pojo.Use;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.script.Bindings;
+import java.util.Collection;
+
+public class TypesCollectionView implements Use {
+ private static final Logger LOG = LoggerFactory.getLogger(TypesCollectionView.class);
+
+ private HApiUtil hapi;
+ private HApiTypesCollection me;
+
+ 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.collectionFromPath(resourceResolver, resource.getPath());
+ LOG.debug("me: {} resource: {}", me, resource.getPath());
+ description = me.getDescription();
+ }
+
+ public String getTitle() {
+ return me.getFqdn();
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Collection<HApiType> getTypes() {
+ return me;
+ }
+
+ public boolean getHasTypes() {
+ return getTypes().size() > 0;
+ }
+}
diff --git a/src/main/java/org/apache/sling/hapi/sightly/package-info.java b/src/main/java/org/apache/sling/hapi/sightly/package-info.java
index 45c370c..0e07165 100644
--- a/src/main/java/org/apache/sling/hapi/sightly/package-info.java
+++ b/src/main/java/org/apache/sling/hapi/sightly/package-info.java
@@ -17,7 +17,7 @@
* under the License.
******************************************************************************/
-@Version("1.0.0")
+@Version("1.1.0")
package org.apache.sling.hapi.sightly;
import aQute.bnd.annotation.Version;
diff --git a/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html b/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html
index 39d8f18..dd95a5d 100644
--- a/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html
+++ b/src/main/resources/SLING-INF/libs/sling/hapi/components/type/type.html
@@ -17,7 +17,8 @@
~ specific language governing permissions and limitations
~ under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<html data-sly-use.type="org.apache.sling.hapi.sightly.TypeView" lang="${type.lang}">
+<html data-sly-use.type="org.apache.sling.hapi.sightly.TypeView"
+ data-sly-use.hapitype="${'org.apache.sling.hapi.sightly.HApiUse' @type='org.apache.sling.hapi.common.hapi_type'}" lang="${type.lang}">
<head>
<meta charset="utf-8">
@@ -38,18 +39,18 @@
</head>
<body>
- <div class="container">
+ <div class="container" data-sly-attribute="${hapitype.itemtype}">
- <h1>${type.title}</h1>
+ <h1 data-sly-attribute="${hapitype.itemprop.hapi_name}">${type.title}</h1>
<div>
- <p>${type.description}</p>
+ <p data-sly-attribute="${hapitype.itemprop.hapi_description}">${type.description}</p>
</div>
<h2 data-sly-test.parentUrl="${type.parentUrl}"> extends
- <a href="${parentUrl}" >${type.parentFqdn}</a>
+ <a data-sly-attribute="${hapitype.itemprop.hapi_parent}" 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>
+ <li data-sly-attribute="${hapitype.itemprop.hapi_parameter}">${param}</li>
</ul>
<h3>Properties: </h3>
<table class="table" data-sly-test.props="${type.props}">
@@ -62,13 +63,17 @@
</tr>
</thead>
<tbody data-sly-list.prop="${type.props}">
- <tr>
- <th>${prop.name}</th>
+ <tr data-sly-attribute="${hapitype.itemprop.hapi_property}"
+ data-sly-use.hapi_type_prop="${'org.apache.sling.hapi.sightly.HApiUse' @type=hapitype.proptype.hapi_property}">
+
+ <th data-sly-attribute="${hapi_type_prop.itemprop.hapi_name}">${prop.name}</th>
<td>
- <a href="${prop.type.url}">${prop.type.name}</a>
+ <a data-sly-attribute="${hapi_type_prop.itemprop.hapi_property_type}" href="${prop.type.url}">
+ ${prop.type.name}
+ </a>
</td>
- <td>${prop.multiple}</td>
- <td>${prop.description}</td>
+ <td data-sly-attribute="${hapi_type_prop.itemprop.hapi_multiple}">${prop.multiple}</td>
+ <td data-sly-attribute="${hapi_type_prop.itemprop.hapi_description}">${prop.description}</td>
</tr>
</tbody>
</table>
diff --git a/src/main/resources/SLING-INF/libs/sling/hapi/components/typescollection/typescollection.html b/src/main/resources/SLING-INF/libs/sling/hapi/components/typescollection/typescollection.html
new file mode 100644
index 0000000..ea8427f
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/hapi/components/typescollection/typescollection.html
@@ -0,0 +1,73 @@
+<!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.collection="org.apache.sling.hapi.sightly.TypesCollectionView"
+ data-sly-use.hapicollection="${'org.apache.sling.hapi.sightly.HApiUse' @type='org.apache.sling.hapi.common.hapi_typescollection'}"
+ 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>${collection.title}</title>
+
+ </head>
+ <body>
+ <div class="container">
+
+ <h1 data-sly-attribute="${hapicollection.itemprop.hapi_name}">${collection.title}</h1>
+ <div>
+ <p data-sly-attribute="${hapicollection.itemprop.hapi_description}">${collection.description}</p>
+ </div>
+
+ <h3>Types: </h3>
+ <table class="table" data-sly-test.types="${collection.types}">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody data-sly-list.type="${collection.types}">
+ <tr data-sly-attribute="${hapicollection.itemprop.hapi_type}"
+ data-sly-use.hapi_type="${'org.apache.sling.hapi.sightly.HApiUse' @type=hapicollection.proptype.hapi_type}">
+ <td>
+ <a rel="hapi_type" data-sly-attribute="${hapi_type.itemprop.hapi_url}" href="${type.url}">
+ <span data-sly-attribute="${hapi_type.itemprop.hapi_name}">${type.fqdn}</span>
+ </a>
+ </td>
+ <td data-sly-attribute="${hapi_type.itemprop.hapi_description}">${type.description}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div data-sly-test="${!types}">None</div>
+ </div>
+ </body>
+</html>
diff --git a/src/main/resources/SLING-INF/libs/sling/hapi/types.json b/src/main/resources/SLING-INF/libs/sling/hapi/types.json
index 7984006..012c6c9 100644
--- a/src/main/resources/SLING-INF/libs/sling/hapi/types.json
+++ b/src/main/resources/SLING-INF/libs/sling/hapi/types.json
@@ -1,110 +1,215 @@
{
- "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
+ "fqdn": "org.apache.sling.hapi.common",
+ "description": "Common HApi types collection",
+ "name": "common",
+ "sling:resourceType": "sling/hapi/components/typescollection",
+ "image": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "An image src",
+ "fqdn": "org.apache.sling.hapi.common.Image",
+ "name": "Image",
+ "sling:resourceType": "sling/hapi/components/type"
},
- "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
+ "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"
},
- "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
+ "text": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "A text value",
+ "fqdn": "org.apache.sling.hapi.common.Text",
+ "name": "Text",
+ "sling:resourceType": "sling/hapi/components/type"
},
- "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"
- }
+ "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"
+ },
+ "hapi_type": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The representation of the structure of the HApi type. This is used to annotate the html page describing any type",
+ "hapi_name": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The FQDN of the HApi Type",
+ "type": "org.apache.sling.hapi.common.Text",
+ "multiple": false
+ },
+ "hapi_description": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The description of the HApi Type",
+ "type": "org.apache.sling.hapi.common.Text",
+ "multiple": false
+ },
+ "hapi_parent": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The parent type of the HApi Type",
+ "type": "org.apache.sling.hapi.common.hapi_type",
+ "multiple": false
+ },
+ "hapi_url": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The external URL of the type",
+ "type": "org.apache.sling.hapi.common.URL",
+ "multiple": false
+ },
+ "hapi_parameter": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "A parameter of this type, inc ase it's a parameterized type",
+ "type": "org.apache.sling.hapi.common.Text",
+ "multiple": true
+ },
+ "hapi_property": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "A property of the HApi type",
+ "type": "org.apache.sling.hapi.common.hapi_type_property",
+ "multiple": true
+ },
+ "fqdn": "org.apache.sling.hapi.common.hapi_type",
+ "name": "hapi_type",
+ "parameters": [],
+ "sling:resourceType": "sling/hapi/components/type"
+ },
+ "hapi_type_property": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The representation of the structure of a property for a HApi type. This is used to annotate the html page describing any type",
+ "hapi_name": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The name of the HApi Type Property",
+ "type": "org.apache.sling.hapi.common.Text",
+ "multiple": false
+ },
+ "hapi_description": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The description of the HApi Type property",
+ "type": "org.apache.sling.hapi.common.Text",
+ "multiple": false
+ },
+ "hapi_property_type": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "A link to the type of the property",
+ "type": "org.apache.sling.hapi.common.hapi_type",
+ "multiple": false
+ },
+ "hapi_multiple": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "Whether the property can occur multiple times in an object of the type that this property belongs to",
+ "type": "org.apache.sling.hapi.common.Boolean",
+ "multiple": false
+ },
+ "fqdn": "org.apache.sling.hapi.common.hapi_type_property",
+ "name": "hapi_type_property",
+ "parameters": [],
+ "sling:resourceType": "sling/hapi/components/type"
+ },
+ "hapi_typescollection": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The representation of the structure of a HApi typescollection. This is used to annotate the html page describing any types collection",
+ "hapi_name": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The name of the HApi Types Collection",
+ "type": "org.apache.sling.hapi.common.Text",
+ "multiple": false
+ },
+ "hapi_description": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "The description of the HApi Types Collection",
+ "type": "org.apache.sling.hapi.common.Text",
+ "multiple": false
+ },
+ "hapi_type": {
+ "jcr:primaryType": "nt:unstructured",
+ "description": "A type in the typescollection",
+ "type": "org.apache.sling.hapi.common.hapi_type",
+ "multiple": true
+ },
+ "fqdn": "org.apache.sling.hapi.common.hapi_typescollection",
+ "name": "hapi_typescollection",
+ "sling:resourceType": "sling/hapi/components/type"
+ },
}