This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.resourcecollection-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourcecollection.git
commit 15a8f7caa51ce8808f1e1f59f052fdc4b084367b Author: Felix Meschberger <[email protected]> AuthorDate: Mon May 6 07:30:46 2013 +0000 SLING-2853 Commit patch 4 by Amit Gupta (Thanks alot) git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/collection@1479479 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 155 +++++++++++ .../resource/collection/ResourceCollection.java | 130 +++++++++ .../collection/ResourceCollectionManager.java | 93 +++++++ .../impl/ResourceCollectionAdapterFactory.java | 103 +++++++ .../collection/impl/ResourceCollectionImpl.java | 309 +++++++++++++++++++++ .../impl/ResourceCollectionManagerImpl.java | 138 +++++++++ .../impl/util/ResourceCollectionUtil.java | 49 ++++ .../impl/ResourceCollectionImplTest.java | 221 +++++++++++++++ .../resource/collection/test/MockResource.java | 104 +++++++ .../collection/test/MockResourceResolver.java | 249 +++++++++++++++++ 10 files changed, 1551 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100755 index 0000000..2b066af --- /dev/null +++ b/pom.xml @@ -0,0 +1,155 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <!-- ======================================================================= --> + <!-- P A R E N T P R O J E C T --> + <!-- ======================================================================= --> + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling</artifactId> + <version>15</version> + <relativePath>../../../parent/pom.xml</relativePath> + </parent> + + <!-- ======================================================================= --> + <!-- P R O J E C T --> + <!-- ======================================================================= --> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.resourcecollection</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>Apache Sling Resource Collection API</name> + <description> + The Apache sling resource collection bundle provides an api to create collections of resources. + </description> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/resourcecollection</connection> + <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/resourcecollection</developerConnection> + <url>http://svn.apache.org/viewvc/sling/trunk/bundles/resourcecollection</url> + </scm> + + <!-- ======================================================================= --> + <!-- B U I L D --> + <!-- ======================================================================= --> + <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> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + + </plugin> + </plugins> + </build> + + <!-- ======================================================================= --> + <!-- D E P E N D E N C I E S --> + <!-- ======================================================================= --> + <dependencies> + + + <!-- sling --> + <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.jcr.api</artifactId> + <version>2.1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.jcr.resource</artifactId> + <version>2.2.6</version> + <scope>provided</scope> + </dependency> + + <!-- OSGI --> + <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> + + <!-- Felix --> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.scr.annotations</artifactId> + <scope>provided</scope> + </dependency> + + <!-- Testing --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + </dependency> + <dependency> + <groupId>junit-addons</groupId> + <artifactId>junit-addons</artifactId> + <version>1.4</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.framework</artifactId> + <version>3.0.8</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.4</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + +</project> diff --git a/src/main/java/org/apache/sling/resource/collection/ResourceCollection.java b/src/main/java/org/apache/sling/resource/collection/ResourceCollection.java new file mode 100755 index 0000000..b1a4f6f --- /dev/null +++ b/src/main/java/org/apache/sling/resource/collection/ResourceCollection.java @@ -0,0 +1,130 @@ +/* + * 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.resource.collection; +import java.util.Iterator; +import java.util.Map; + +import org.apache.sling.api.resource.ModifiableValueMap; +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.Resource; + +/** + * ResourceCollection is an ordered collection of resources. Actual resources are not stored inside the collection. + * + * Each entry in a collection is represented as a resource, which contain a reference to original resource + * and it can have additional properties i.e. creationDate. + */ +public interface ResourceCollection { + + /** + * Sling resource type for resource representing a </code>ResourceCollection<code> + */ + public static final String RESOURCE_TYPE = "sling/collection"; + + /** + * Returns name of the collection. + * + * @return name of the collection. + */ + public String getName(); + + /** + * Returns path of the collection. + * + * @return path of the collection. + */ + public String getPath(); + + /** + * Returns an iterator over resources referred in the collection in the specified order. + * + * @return iterator over resources referred in collection. + */ + Iterator<Resource> getResources(); + + /** + * Returns additional properties for a particular resource in Collection entry. + * + * @return properties of the Collection entry as <code>ModifiableValueMap</code>, returns null if entry found. + */ + ModifiableValueMap getProperties(Resource resource); + + /** + * Returns true if resource reference is part of the collection. + * + * @param resource resource to be checked + * @return true if resource is part of the collection. + * false otherwise + */ + boolean contains(Resource resource); + + + /** + * Creates a new entry in the collection at the last position and add a reference to resource + * in the entry. + * Changes are transient & have to be saved by calling resolver.commit() + * + * @param resource resource to be added + * @param properties The additional properties to be stored with the collection entry (can be null). + * @return true if addition of resource to collection was successful or + * false if collection already contained the resource or resource is null. + * + * @throws {@link PersistenceException} if the operation fails + */ + boolean add(Resource resource, Map<String, Object> properties) throws PersistenceException; + + /** + * Creates a new entry in the collection at the last position and add a reference to resource + * in the entry. + * Changes are transient & have to be saved by calling resolver.commit() + * + * @param resource resource to be added + * @return true if addition of resource to collection was successful or + * false if collection already contained the resource or resource is null. + * + * @throws {@link PersistenceException} if the operation fails + */ + boolean add(Resource resource) throws PersistenceException; + + + /** + * Removes a entry of resource from collection & returns true if successful. + * Changes are transient & have to be saved by calling resolver.commit() + * + * @param resource resource reference to be removed + * @return true if resource reference was successfully removed from the collection. + * false if not removed/not present + * + * @throws {@link PersistenceException} if the operation fails + */ + boolean remove(Resource resource) throws PersistenceException; + + /** + * This method inserts the referenced resource <code>srcResource</code> + * into the collection entry at the position immediately before the referenced resource <code>destResource</code>. + * + * To insert the referenced resource into last position, <code>destResource</code> can be null. + * + * @param srcResource Referenced resource that needs to be moved in the order + * @param destResource Referenced resource before which the <code>srcResource</code> will be placed. + */ + void orderBefore(Resource srcResource, Resource destResource); +} diff --git a/src/main/java/org/apache/sling/resource/collection/ResourceCollectionManager.java b/src/main/java/org/apache/sling/resource/collection/ResourceCollectionManager.java new file mode 100755 index 0000000..290e6d7 --- /dev/null +++ b/src/main/java/org/apache/sling/resource/collection/ResourceCollectionManager.java @@ -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.resource.collection; + +import java.util.Map; + +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; + +/** + * The <code>ResourceCollectionManager<code> defines the API to get, create and delete + * resource collection {@link org.apache.sling.resource.collection.ResourceCollection}. + * + * A ResourceCollectionManager instance can be retrieved by adapting ResourceResolver. + */ +public interface ResourceCollectionManager { + + /** + * This method returns a resource collection for the given <code>resource</code> + * that represents a {@link ResourceCollection}. + * + * It returns null if given resource is not a collection + * + * @param resource resource that represents a collection + * @return The {@link org.apache.sling.resource.collection.ResourceCollection} representing the collection. + * + */ + ResourceCollection getCollection(Resource resource); + + + /** + * This method creates a resource collection with a given name under the <code>parentResource</code>. + * The changes are transient and have to be saved by resourceResolver.commit() + * + * @param parentResource parent resource where collection needs to be created. + * @param name The name for collection. + * + * @return The {@link org.apache.sling.resource.collection.ResourceCollection} representing the created collection. + * + * @throws {@link PersistenceException} if the operation fails + */ + ResourceCollection createCollection(Resource parentResource, String name) throws PersistenceException; + + /** + * This method creates a resource collection with a given name under the <code>parentResource</code>. + * The changes are transient and have to be saved by resourceResolver.commit() + * + * @param parentResource parent resource where collection needs to be created. + * @param name The name for collection. + * @param properties The additional data for resource collection + * + * @return The {@link org.apache.sling.resource.collection.ResourceCollection} representing the created collection. + * + * @throws {@link PersistenceException} if the operation fails + */ + ResourceCollection createCollection(Resource parentResource, String name, Map<String,Object> properties) throws PersistenceException; + + /** + * Removes the {@link org.apache.sling.resource.collection.ResourceCollection} corresponding to the collection represented by + * <code>resource</code>. + * The changes are transient and have to be saved by resourceResolver.commit() + * + * @param resource resource representing a collection to be deleted. + * @return <code>true</code> if the collection was successfully removed. + * + * @throws {@link PersistenceException} if the operation fails + */ + boolean deleteCollection(Resource resource) throws PersistenceException; + + /** + * Returns the {@link ResourceResolver} from which this has been retrieved/adapted. + */ + ResourceResolver getResourceResolver(); +} \ No newline at end of file diff --git a/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionAdapterFactory.java b/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionAdapterFactory.java new file mode 100755 index 0000000..c7a2790 --- /dev/null +++ b/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionAdapterFactory.java @@ -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.resource.collection.impl; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.api.adapter.AdapterFactory; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.resource.collection.ResourceCollection; +import org.apache.sling.resource.collection.ResourceCollectionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * AdapterFactory that adapts Resources to: {@link ResourceCollection} + * And ResourceResolver to: {@link ResourceCollectionManager) + */ +@Component(metatype = false) +@Service +@Property(name = "service.description", value = "Collection Adapter Factory") +public class ResourceCollectionAdapterFactory implements AdapterFactory { + + private static final Logger log = LoggerFactory.getLogger(ResourceCollectionAdapterFactory.class); + + private static final Class<ResourceCollection> COLLECTION_CLASS = ResourceCollection.class; + + private static final Class<ResourceCollectionManager> COLLECTION_MGR_CLASS = ResourceCollectionManager.class; + + @Property(name = "adapters") + public static final String[] ADAPTER_CLASSES = { + COLLECTION_CLASS.getName(), COLLECTION_MGR_CLASS.getName() + + }; + + @Property(name = "adaptables") + public static final String[] ADAPTABLE_CLASSES = { + Resource.class.getName(), ResourceResolver.class.getName() + + }; + + // ---------- AdapterFactory ----------------------------------------------- + + public <AdapterType> AdapterType getAdapter(Object adaptable, + Class<AdapterType> type) { + if (adaptable instanceof Resource) { + return getAdapter((Resource) adaptable, type); + } else if (adaptable instanceof ResourceResolver) { + return getAdapter((ResourceResolver) adaptable, type); + } else { + log.warn("Unable to handle adaptable {}", + adaptable.getClass().getName()); + return null; + } + } + + @SuppressWarnings("unchecked") + private <AdapterType> AdapterType getAdapter(Resource resource, + Class<AdapterType> type) { + if (resource != null) { + if (type == COLLECTION_CLASS) { + if (resource.isResourceType(ResourceCollection.RESOURCE_TYPE)) { + return (AdapterType) new ResourceCollectionImpl(resource); + } + } + log.debug("Unable to adapt resource of {} to type {}", + resource.getResourceType(), type.getName()); + + } + log.debug("Unable to adapt null resource to type {}", type.getName()); + return null; + } + + @SuppressWarnings("unchecked") + private <AdapterType> AdapterType getAdapter(ResourceResolver resolver, + Class<AdapterType> type) { + if (COLLECTION_MGR_CLASS == type) { + return (AdapterType) new ResourceCollectionManagerImpl(resolver); + } else { + log.warn("Unable to adapt resolver to requested type {}", + type.getName()); + return null; + } + } +} diff --git a/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionImpl.java b/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionImpl.java new file mode 100755 index 0000000..ccf88a0 --- /dev/null +++ b/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionImpl.java @@ -0,0 +1,309 @@ +/* + * 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.resource.collection.impl; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.sling.api.resource.ModifiableValueMap; +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceUtil; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.jcr.resource.JcrResourceConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.sling.resource.collection.ResourceCollection; +import org.apache.sling.resource.collection.impl.util.ResourceCollectionUtil; + +/** + * Implements <code>ResourceCollection</code> + * + */ +public class ResourceCollectionImpl implements + ResourceCollection { + + private static final Logger log = LoggerFactory.getLogger(ResourceCollectionImpl.class); + + /** + * Defines the resource type property + */ + private static final String RESOURCE_TYPE = JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY; + + /** + * underlying resource + */ + private final Resource resource; + + /** + * The resource resolver in use by the resource. + */ + private final ResourceResolver resolver; + + private final Resource membersResource; + + private static final String REF_PROPERTY = "sling:resource"; + + private static final String MEMBERS_NODE_NAME = "members"; + + private static final String REFERENCES_PROP = "sling:references"; + + /** + * Creates a new collection from the given resource + * + * @param resource the resource + */ + public ResourceCollectionImpl(Resource resource) { + this.resource = resource; + resolver = resource.getResourceResolver(); + membersResource = resource.getChild(MEMBERS_NODE_NAME); + } + + /** + * {@inheritDoc} + */ + public String getName() { + return resource.getName(); + } + + /** + * {@inheritDoc} + */ + public String getPath() { + return resource.getPath(); + } + + /** + * {@inheritDoc} + */ + public boolean add(Resource res, Map<String, Object> properties) throws PersistenceException { + if (res != null && !contains(res)) { + ModifiableValueMap vm = membersResource.adaptTo(ModifiableValueMap.class); + String[] order = vm.get(REFERENCES_PROP, new String[]{}); + + order = (String[]) ArrayUtils.add(order, res.getPath()); + vm.put(REFERENCES_PROP, order); + + if (properties == null) { + properties = new HashMap<String, Object>(); + } + properties.put(REF_PROPERTY, res.getPath()); + resolver.create( + membersResource, + ResourceCollectionUtil.createUniqueChildName(membersResource, + res.getName()), properties); + log.debug("added member to resource {} to collection {}", + new String[] { res.getPath(), resource.getPath() }); + return true; + } + + return false; + } + + /** + * {@inheritDoc} + */ + public boolean add(Resource res) throws PersistenceException { + if (res != null && !contains(res)) { + ModifiableValueMap vm = membersResource.adaptTo(ModifiableValueMap.class); + String[] order = vm.get(REFERENCES_PROP, new String[]{}); + + order = (String[]) ArrayUtils.add(order, res.getPath()); + vm.put(REFERENCES_PROP, order); + + Map<String, Object> properties = new HashMap<String, Object>(); + properties.put(REF_PROPERTY, res.getPath()); + resolver.create( + membersResource, + ResourceCollectionUtil.createUniqueChildName(membersResource, + res.getName()), properties); + log.debug("added member to resource {} to collection {}", + new String[] { res.getPath(), resource.getPath() }); + return true; + } + + return false; + } + + + + /** + * {@inheritDoc} + */ + public Iterator<Resource> getResources() { + + ValueMap vm = membersResource.adaptTo(ValueMap.class); + String[] references = vm.get(REFERENCES_PROP, new String[]{}); + List<Resource> resources = new ArrayList<Resource>(); + + for (String path:references) { + Resource resource = resolver.getResource(path); + if (resource != null){ + resources.add(resource); + } + } + + return resources.iterator(); + } + + /** + * Returns the sling resource type on content node of collection + * + * @param + * @return <code>sling:resourceType</code> for the collection resource + */ + public String getType() { + return resource.getResourceType(); + } + + /** + * {@inheritDoc} + */ + public boolean contains(Resource res) { + if (res != null) { + ValueMap vm = membersResource.adaptTo(ValueMap.class); + String[] order = vm.get(REFERENCES_PROP, new String[]{}); + + int index = ArrayUtils.indexOf(order, res.getPath(), 0); + + return index >= 0 ? true: false; + } + + return false; + } + + /** + * {@inheritDoc} + */ + public boolean remove(Resource res) throws PersistenceException { + //remove the resource + Resource tobeRemovedRes = findRes(res); + if (tobeRemovedRes == null) { + return false; + } + resolver.delete(tobeRemovedRes); + //remove from order array + ModifiableValueMap vm = membersResource.adaptTo(ModifiableValueMap.class); + String[] order = vm.get(REFERENCES_PROP, new String[]{}); + + int index = ArrayUtils.indexOf(order, res.getPath(), 0); + + order = (String[]) ArrayUtils.remove(order, index); + vm.put(REFERENCES_PROP, order); + + return true; + } + + /** + * Sets the sling resource type on content node of collection + * + * @param type <code>sling:resourceType</code> to be set on the content node + * @return + */ + public void setType(String type) throws PersistenceException { + ModifiableValueMap mvp = resource.adaptTo(ModifiableValueMap.class); + mvp.put(RESOURCE_TYPE, type); + } + + private Resource findRes(Resource res) { + if (res != null) { + String resName = res.getName(); + if (membersResource.getChild(resName) != null + && (res.getPath()).equals(ResourceUtil.getValueMap( + membersResource.getChild(resName)).get(REF_PROPERTY, ""))) + return membersResource.getChild(resName); + // handle multiple res with same name but different paths + Iterator<Resource> children = membersResource.listChildren(); + while (children.hasNext()) { + Resource r = children.next(); + if (ResourceUtil.getValueMap(r).get(REF_PROPERTY, "").equals( + res.getPath())) return r; + } + } + return null; + } + + public void orderBefore(Resource srcResource, Resource destResource) { + if (srcResource == null) { + throw new IllegalArgumentException("Source Resource can not be null"); + } + ModifiableValueMap vm = membersResource.adaptTo(ModifiableValueMap.class); + String[] order = vm.get(REFERENCES_PROP, new String[]{}); + String srcPath = srcResource.getPath(); + int srcIndex = ArrayUtils.indexOf(order, srcPath); + if (srcIndex < 0) { + log.warn("Collection ordering failed, as there is no resource {} in collection {} for destResource", + srcPath, getPath()); + return ; + } + if (destResource == null) { + //add it to the end. + order = (String[]) ArrayUtils.remove(order, srcIndex); + order = (String[]) ArrayUtils.add(order, srcPath); + } else { + String destPath = destResource.getPath(); + + if (destPath.equals(srcPath)) { + String message = MessageFormat.format("Collection ordering failed, as source {} and destination {} can not be same", + srcPath, destPath); + log.error(message); + throw new IllegalArgumentException(message); + } + + int destIndex = ArrayUtils.indexOf(order, destPath); + + if (destIndex < 0) { + log.warn("Collection ordering failed, as there is no resource {} in collection {} for destResource", + destPath, getPath()); + return; + } + + order = (String[]) ArrayUtils.remove(order, srcIndex); + if (srcIndex < destIndex) { //recalculate dest index + destIndex = ArrayUtils.indexOf(order, destPath); + } + order = (String[]) ArrayUtils.add(order, destIndex, srcPath); + } + + vm.put(REFERENCES_PROP, order); + } + + public ModifiableValueMap getProperties(Resource resource) { + Iterator<Resource> entries = membersResource.listChildren(); + while (entries.hasNext()) { + Resource entry = entries.next(); + String path = ResourceUtil.getValueMap(entry).get( + REF_PROPERTY, ""); + + if (resource.getPath().equals(path)) { + return entry.adaptTo(ModifiableValueMap.class); + } + } + + return null; + } +} diff --git a/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionManagerImpl.java b/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionManagerImpl.java new file mode 100755 index 0000000..450bc7c --- /dev/null +++ b/src/main/java/org/apache/sling/resource/collection/impl/ResourceCollectionManagerImpl.java @@ -0,0 +1,138 @@ +/* + * 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.resource.collection.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.jcr.resource.JcrResourceConstants; +import org.apache.sling.resource.collection.ResourceCollection; +import org.apache.sling.resource.collection.ResourceCollectionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * Implements <code>ResourceCollectionManger</code> interface. And provides + * create, delete, get apis for ResourceCollection. + * + * A ResourceCollectionManager instance can be retrieved by adapting ResourceResolver. + */ +public class ResourceCollectionManagerImpl implements ResourceCollectionManager { + + private static final Logger log = LoggerFactory.getLogger(ResourceCollectionManager.class); + + private final ResourceResolver resolver; + + public ResourceCollectionManagerImpl(ResourceResolver resolver) { + this.resolver = resolver; + } + + /** + * {@inheritDoc} + */ + public ResourceCollection getCollection(Resource resource) { + if (resource != null) { + if (resource.isResourceType(ResourceCollection.RESOURCE_TYPE)) { + return new ResourceCollectionImpl(resource); + } + } else { + throw new IllegalArgumentException("resource can not be null"); + } + + return null; + } + + /** + * {@inheritDoc} + */ + public ResourceCollection createCollection(Resource parentResource, String name) + throws PersistenceException { + return createCollection(parentResource, name, null); + } + + /** + * {@inheritDoc} + */ + public ResourceCollection createCollection(Resource parentResource, String name, + Map<String, Object> properties) throws PersistenceException { + + if (parentResource != null) { + String fullPath = parentResource.getPath() + name; + + if (resolver.getResource(fullPath) != null) { + throw new IllegalArgumentException("invalid path, " + fullPath + + "resource already exists"); + } + + if (properties == null) { + properties = new HashMap<String, Object>(); + } + + if (properties.get(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY) != null + && !ResourceCollection.RESOURCE_TYPE.equals(properties.get(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY))) { + properties.put( + JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY, + ResourceCollection.RESOURCE_TYPE); + } else { + properties.put( + JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY, + ResourceCollection.RESOURCE_TYPE); + } + Resource collectionRes = resolver.create(parentResource, name, properties); + resolver.create(collectionRes, "members", null); + log.debug("collection {} created", fullPath); + + return new ResourceCollectionImpl( + resolver.getResource(collectionRes.getPath())); + } else { + log.error("parent resource can not be null"); + throw new IllegalArgumentException("parent resource can not be null "); + } + + } + + /** + * {@inheritDoc} + * + * @throws PersistenceException + */ + public boolean deleteCollection(Resource resource) + throws PersistenceException { + if (resource != null) { + log.debug("collection {} deleted", resource.getPath()); + resolver.delete(resource); + return true; + } else { + throw new IllegalArgumentException("resource can not be null"); + } + } + + /** + * {@inheritDoc} + */ + public ResourceResolver getResourceResolver() { + return resolver; + } + +} \ No newline at end of file diff --git a/src/main/java/org/apache/sling/resource/collection/impl/util/ResourceCollectionUtil.java b/src/main/java/org/apache/sling/resource/collection/impl/util/ResourceCollectionUtil.java new file mode 100755 index 0000000..2f56494 --- /dev/null +++ b/src/main/java/org/apache/sling/resource/collection/impl/util/ResourceCollectionUtil.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sling.resource.collection.impl.util; + + +import org.apache.sling.api.resource.Resource; + +public class ResourceCollectionUtil { + + /** + * Create a unique name for a child of the <code>resource</code>. Generates a unique name and test if child + * already exists. If name is already existing, iterate until a unique one is found + * + * @param resource parent resource + * @param name the name to check + * @return a unique label string + */ + public static String createUniqueChildName(Resource resource, String name) { + if (resource.getChild(name)!=null) { + // leaf node already exists, create new unique name + String leafNodeName; + int i = 0; + do { + leafNodeName = name + String.valueOf(i); + i++; + } while (resource.getChild(leafNodeName)!=null); + return leafNodeName; + } + return name; + } + +} diff --git a/src/test/java/org/apache/sling/resource/collection/impl/ResourceCollectionImplTest.java b/src/test/java/org/apache/sling/resource/collection/impl/ResourceCollectionImplTest.java new file mode 100755 index 0000000..f37c207 --- /dev/null +++ b/src/test/java/org/apache/sling/resource/collection/impl/ResourceCollectionImplTest.java @@ -0,0 +1,221 @@ +package org.apache.sling.resource.collection.impl; + + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import junit.framework.Assert; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.jcr.resource.JcrResourceConstants; +import org.apache.sling.resource.collection.ResourceCollection; +import org.apache.sling.resource.collection.ResourceCollectionManager; +import org.apache.sling.resource.collection.test.MockResource; +import org.apache.sling.resource.collection.test.MockResourceResolver; +import org.junit.Before; +import org.junit.Test; + +public class ResourceCollectionImplTest { + private ResourceResolver resResolver; + + @Before + public void setUp() throws Exception { + resResolver = new MockResourceResolver(); + //create some root resource + Resource resource = new MockResource(resResolver, "/", "type"); + + ((MockResourceResolver) resResolver).addResource(resource); + } + + @Test + public void testAddResource() throws Exception { + ResourceCollectionManager rcm = new ResourceCollectionManagerImpl(resResolver); + + ResourceCollection collection = rcm.createCollection(resResolver.getResource("/"), "test1"); + + Resource resource = new MockResource(resResolver, "/res1", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource); + resource = new MockResource(resResolver, "/res2", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource); + + Assert.assertEquals(true, collection.contains(resource)); + + Assert.assertEquals(true, collection.contains(resource)); + Assert.assertNotNull(resResolver.getResource("/test1")); + Assert.assertEquals(ResourceCollection.RESOURCE_TYPE, resResolver.getResource("/test1").getResourceType()); + } + + @Test + public void testCreateCollection() throws Exception { + ResourceCollectionManager rcm = new ResourceCollectionManagerImpl(resResolver); + + ResourceCollection collection = rcm.createCollection(resResolver.getResource("/"), "test1"); + + Resource resource = new MockResource(resResolver, "/res1", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + resource = new MockResource(resResolver, "/res2", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + + Assert.assertEquals(true, collection.contains(resource)); + Assert.assertNotNull(resResolver.getResource("/test1")); + Assert.assertEquals(ResourceCollection.RESOURCE_TYPE, resResolver.getResource("/test1").getResourceType()); + } + + @Test + public void testGetCollection() throws Exception { + ResourceCollectionManager rcm = new ResourceCollectionManagerImpl(resResolver); + + ResourceCollection collection = rcm.createCollection(resResolver.getResource("/"), "test1"); + + Resource resource = new MockResource(resResolver, "/res1", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + resource = new MockResource(resResolver, "/res2", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + + collection = rcm.getCollection(resResolver.getResource(collection.getPath())); + + Assert.assertEquals(true, collection.contains(resource)); + Assert.assertNotNull(resResolver.getResource("/test1")); + Assert.assertEquals(ResourceCollection.RESOURCE_TYPE, resResolver.getResource("/test1").getResourceType()); + } + + @Test + public void testListCollection() throws Exception { + ResourceCollectionManager rcm = new ResourceCollectionManagerImpl(resResolver); + + ResourceCollection collection = rcm.createCollection(resResolver.getResource("/"), "collection1"); + + Resource resource = new MockResource(resResolver, "/res1", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + resource = new MockResource(resResolver, "/res2", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + + Assert.assertEquals(true, collection.contains(resource)); + + Iterator<Resource> resources = collection.getResources(); + + int numOfRes = 0; + while (resources.hasNext()) { + resources.next(); + numOfRes ++; + } + + Assert.assertEquals(2, numOfRes); + } + + @Test + public void testCreateCollectionWithProperties() throws Exception { + ResourceCollectionManager rcm = new ResourceCollectionManagerImpl(resResolver); + Map<String, Object> props = new HashMap<String, Object>(); + props.put(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY, "some/type"); + props.put("creator", "slingdev"); + + ResourceCollection collection = rcm.createCollection(resResolver.getResource("/"), "collection3", props); + + Resource resource = new MockResource(resResolver, "/res1", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + + + Resource collectionRes = resResolver.getResource("/collection3"); + Assert.assertNotNull(collectionRes); + + Assert.assertEquals(true, collection.contains(resource)); + Assert.assertEquals(ResourceCollection.RESOURCE_TYPE, collectionRes.getResourceSuperType()); + + ValueMap vm = collectionRes.adaptTo(ValueMap.class); + + Assert.assertEquals("slingdev", vm.get("creator", "")); + } + + @Test + public void testAddResourceWithProperties() throws Exception { + ResourceCollectionManager rcm = new ResourceCollectionManagerImpl(resResolver); + Map<String, Object> props = new HashMap<String, Object>(); + props.put("creator", "slingdev"); + + ResourceCollection collection = rcm.createCollection(resResolver.getResource("/"), "collection3"); + + Resource resource = new MockResource(resResolver, "/res1", "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, props); + + + Resource collectionRes = resResolver.getResource("/collection3"); + Assert.assertNotNull(collectionRes); + + Assert.assertEquals(true, collection.contains(resource)); + + ValueMap vm = collection.getProperties(resource); + + if (vm != null) { + Assert.assertEquals("slingdev", vm.get("creator", "")); + } else { + Assert.fail("no resource entry in collection"); + } + } + + @Test + public void testOrdering() throws Exception { + ResourceCollectionManager rcm = new ResourceCollectionManagerImpl(resResolver); + + ResourceCollection collection = rcm.createCollection(resResolver.getResource("/"), "test1"); + String[] resPaths = {"/res1", "/res2"}; + Resource resource = new MockResource(resResolver, resPaths[0], "type"); + ((MockResourceResolver) resResolver).addResource(resource); + + collection.add(resource, null); + Resource resource2 = new MockResource(resResolver, resPaths[1], "type"); + ((MockResourceResolver) resResolver).addResource(resource2); + + collection.add(resource2, null); + + Assert.assertEquals(true, collection.contains(resource2)); + Assert.assertNotNull(resResolver.getResource("/test1")); + Assert.assertEquals(ResourceCollection.RESOURCE_TYPE, resResolver.getResource("/test1").getResourceType()); + + Iterator<Resource> resources = collection.getResources(); + + int numOfRes = 0; + while (resources.hasNext()) { + Resource entry = resources.next(); + Assert.assertEquals(resPaths[numOfRes], entry.getPath()); + numOfRes ++; + } + + //change the order + collection.orderBefore(resource2, resource); + + resources = collection.getResources(); + + numOfRes = 2; + while (resources.hasNext()) { + numOfRes --; + Resource entry = resources.next(); + Assert.assertEquals(resPaths[numOfRes], entry.getPath()); + } + + Assert.assertEquals(0, numOfRes); + } +} diff --git a/src/test/java/org/apache/sling/resource/collection/test/MockResource.java b/src/test/java/org/apache/sling/resource/collection/test/MockResource.java new file mode 100755 index 0000000..a97369a --- /dev/null +++ b/src/test/java/org/apache/sling/resource/collection/test/MockResource.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.resource.collection.test; + +import org.apache.sling.api.resource.ModifiableValueMap; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.SyntheticResource; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.wrappers.ModifiableValueMapDecorator; +import org.apache.sling.api.wrappers.ValueMapDecorator; + +import java.util.HashMap; +import java.util.Map; + +public class MockResource extends SyntheticResource { + + private String resourceType; + private String resourceSuperType; + private Map<String,Object> properties = new HashMap<String,Object>(); + + public MockResource(ResourceResolver resourceResolver, String path, + String resourceType) { + this(resourceResolver, path, resourceType, null); + } + + public MockResource(ResourceResolver resourceResolver, String path, + String resourceType, String resourceSuperType) { + super(resourceResolver, path, resourceType); + + setResourceType(resourceType); + setResourceSuperType(resourceSuperType); + } + + public void addProperty(String key, Object value){ + this.properties.put(key,value); + } + + public Map<String,Object> getProperties(){ + return this.properties; + } + + @Override + public String getResourceType() { + return resourceType; + } + + public void setResourceType(String resourceType) { + this.resourceType = resourceType; + } + + @Override + public String getResourceSuperType() { + return resourceSuperType; + } + + public void setResourceSuperType(String resourceSuperType) { + this.resourceSuperType = resourceSuperType; + } + + @SuppressWarnings("unchecked") + public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) { + if (type == ValueMap.class) { + ValueMap map = new ValueMapDecorator(new HashMap<String, Object>()); + if (resourceType != null) { + map.put("resourceType", resourceType); + } + if (resourceSuperType != null) { + map.put("resourceSuperType", resourceSuperType); + } + for (String key : this.properties.keySet()) { + map.put(key,this.properties.get(key)); + } + return (AdapterType) map; + } + + if (type == ModifiableValueMap.class) { + ModifiableValueMap map = new ModifiableValueMapDecorator(this.properties); + if (resourceType != null) { + map.put("resourceType", resourceType); + } + if (resourceSuperType != null) { + map.put("resourceSuperType", resourceSuperType); + } + return (AdapterType) map; + } + throw new UnsupportedOperationException("AdaptTo " + type.getSimpleName() + " not implemented"); + } +} diff --git a/src/test/java/org/apache/sling/resource/collection/test/MockResourceResolver.java b/src/test/java/org/apache/sling/resource/collection/test/MockResourceResolver.java new file mode 100755 index 0000000..5b7d9b3 --- /dev/null +++ b/src/test/java/org/apache/sling/resource/collection/test/MockResourceResolver.java @@ -0,0 +1,249 @@ +/* + * 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.resource.collection.test; + +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.sling.api.resource.LoginException; +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.jcr.resource.JcrResourceConstants; + +public class MockResourceResolver implements ResourceResolver { + + private String[] searchPath; + + private Map<String, Resource> resources = new LinkedHashMap<String, Resource>(); + + private Map<String, Collection<Resource>> children = new LinkedHashMap<String, Collection<Resource>>(); + + public void addResource(Resource resource) { + this.resources.put(resource.getPath(), resource); + } + + public void addChildren(Resource parent, Collection<Resource> children) { + this.children.put(parent.getPath(), children); + } + + public Resource resolve(HttpServletRequest request) { + throw new UnsupportedOperationException("Not implemented"); + + } + + public Resource resolve(String absPath) { + throw new UnsupportedOperationException("Not implemented"); + + } + + public String map(String resourcePath) { + return resourcePath; // a rather simplistic 1:1 map... + + } + + public Resource getResource(String path) { + return resources.get(path); + } + + public Resource getResource(Resource base, String path) { + if (!path.startsWith("/")) { + path = base.getPath() + "/" + path; + } + return getResource(path); + } + + public String[] getSearchPath() { + return searchPath.clone(); + + } + + public Iterator<Resource> listChildren(final Resource parent) { + Collection<Resource> childCollection = children.get(parent.getPath()); + if (childCollection != null) { + return childCollection.iterator(); + } + + return new Iterator<Resource>() { + final String parentPath = parent.getPath() + "/"; + + final Iterator<Resource> elements = resources.values().iterator(); + + Resource nextResource = seek(); + + public boolean hasNext() { + return nextResource != null; + } + + public Resource next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + Resource result = nextResource; + nextResource = seek(); + return result; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + private Resource seek() { + while (elements.hasNext()) { + Resource next = elements.next(); + String path = next.getPath(); + if (path.startsWith(parentPath) + && path.indexOf('/', parentPath.length()) < 0) { + return next; + } + } + return null; + } + }; + } + + public Iterator<Resource> findResources(String query, String language) { + throw new UnsupportedOperationException("Not implemented"); + + } + + public Iterator<Map<String, Object>> queryResources(String query, + String language) { + throw new UnsupportedOperationException("Not implemented"); + + } + + public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) { + throw new UnsupportedOperationException("Not implemented"); + + } + + public void setSearchPath(String... searchPath) { + if (searchPath == null) { + this.searchPath = new String[0]; + } else { + this.searchPath = new String[searchPath.length]; + for (int i=0; i < searchPath.length; i++) { + String entry = searchPath[i]; + if (!entry.endsWith("/")) { + entry = entry.concat("/"); + } + this.searchPath[i] = entry; + } + } + } + + public String map(HttpServletRequest request, String resourcePath) { + return request.getContextPath() + resourcePath; + } + + public Resource resolve(HttpServletRequest request, String absPath) { + throw new UnsupportedOperationException("Not implemented"); + } + + public void close() { + // nothing to do + } + + public String getUserID() { + return null; + } + + public boolean isLive() { + return true; + } + + public ResourceResolver clone(Map<String, Object> authenticationInfo) + throws LoginException { + // TODO Auto-generated method stub + return null; + } + + public Object getAttribute(String name) { + // TODO Auto-generated method stub + return null; + } + + public Iterator<String> getAttributeNames() { + // TODO Auto-generated method stub + return null; + } + + public void commit() throws PersistenceException { + // TODO Auto-generated method stub + + } + + public Resource create(Resource arg0, String arg1, Map<String, Object> arg2) + throws PersistenceException { + String superType = "SuperType"; + String resType = "ResType"; + + if (arg2 != null) { + if (arg2.containsKey(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY)) { + superType = (String) arg2.remove(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY); + } + + if (arg2.containsKey(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY)) { + resType = (String) arg2.remove(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY); + } + } + + String resourcePath = arg0.getPath(); + if (arg0.getPath().equals("/")) { + resourcePath = resourcePath + arg1; + } else { + resourcePath = resourcePath + "/" + arg1; + } + MockResource resource = new MockResource(this, resourcePath, resType, superType); + if (arg2 != null) { + for (String key: arg2.keySet()) { + resource.addProperty(key, arg2.get(key)); + } + } + this.resources.put(resource.getPath(), resource); + return resource; + } + + public void delete(Resource arg0) throws PersistenceException { + // TODO Auto-generated method stub + } + + public Iterable<Resource> getChildren(Resource arg0) { + // TODO Auto-generated method stub + return null; + } + + public boolean hasChanges() { + // TODO Auto-generated method stub + return false; + } + + public void revert() { + // TODO Auto-generated method stub + + } +} + -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
