blob: 567f95f915eab4d29bba7269286e45dc71b1c210 [file] [log] [blame]
/*
* 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.testing.mock.sling.builder;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.JcrConstants;
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.testing.mock.osgi.MapUtil;
import org.jetbrains.annotations.NotNull;
/**
* Helper class for building test content in the resource hierarchy with as less
* boilerplate code as possible.
*/
public class ContentBuilder {
static final String DUMMY_TEMPLATE = "/apps/sample/templates/template1";
protected final ResourceResolver resourceResolver;
/**
* @param resourceResolver Resource resolver
*/
public ContentBuilder(@NotNull ResourceResolver resourceResolver) {
this.resourceResolver = resourceResolver;
}
/**
* Create resource. If parent resource(s) do not exist they are created
* automatically using <code>nt:unstructured</code> nodes.
* @param path Page path
* @return Resource object
*/
public final @NotNull Resource resource(@NotNull String path) {
return resource(path, ValueMap.EMPTY);
}
/**
* Create resource. If parent resource(s) do not exist they are created
* automatically using <code>nt:unstructured</code> nodes.
* @param path Page path
* @param properties Properties for resource.
* @return Resource object
*/
public final @NotNull Resource resource(@NotNull String path, @NotNull Map<String, Object> properties) {
String parentPath = ResourceUtil.getParent(path);
if (parentPath == null) {
throw new IllegalArgumentException("Path has no parent: " + path);
}
// check if properties map contains maps representing child resources
Map<String,Object> propertiesWihtoutChildren;
Map<String,Map<String,Object>> children = getChildMaps(properties);
if (!children.isEmpty()) {
propertiesWihtoutChildren = new HashMap<>();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
if (!children.containsKey(entry.getKey())) {
propertiesWihtoutChildren.put(entry.getKey(), entry.getValue());
}
}
}
else {
propertiesWihtoutChildren = properties;
}
// create resource
Resource parentResource = ensureResourceExists(parentPath);
String name = ResourceUtil.getName(path);
Resource newResource;
try {
newResource = resourceResolver.create(parentResource, name, propertiesWihtoutChildren);
} catch (PersistenceException ex) {
throw new RuntimeException("Unable to create resource at " + path, ex);
}
// create child resources
for (Map.Entry<String,Map<String,Object>> entry : children.entrySet()) {
resource(newResource, entry.getKey(), entry.getValue());
}
return newResource;
}
@SuppressWarnings("unchecked")
private Map<String,Map<String,Object>> getChildMaps(Map<String,Object> properties) {
Map<String,Map<String,Object>> result = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
if (entry.getValue() instanceof Map) {
result.put(entry.getKey(), (Map)entry.getValue());
}
}
return result;
}
/**
* Create resource. If parent resource(s) do not exist they are created
* automatically using <code>nt:unstructured</code> nodes.
* @param path Page path
* @param properties Properties for resource.
* @return Resource object
*/
public final @NotNull Resource resource(@NotNull String path, @NotNull Object @NotNull ... properties) {
return resource(path, MapUtil.toMap(properties));
}
/**
* Create child resource below the given parent resource.
* @param resource Parent resource
* @param name Child resource name
* @return Resource object
*/
public final @NotNull Resource resource(@NotNull Resource resource, @NotNull String name) {
return resource(resource, name, ValueMap.EMPTY);
}
/**
* Create child resource below the given parent resource.
* @param resource Parent resource
* @param name Child resource name
* @param properties Properties for resource.
* @return Resource object
*/
public final @NotNull Resource resource(@NotNull Resource resource, @NotNull String name, @NotNull Map<String, Object> properties) {
String path = resource.getPath() + "/" + StringUtils.stripStart(name, "/");
return resource(path, properties);
}
/**
* Create child resource below the given parent resource.
* @param resource Parent resource
* @param name Child resource name
* @param properties Properties for resource.
* @return Resource object
*/
public final @NotNull Resource resource(@NotNull Resource resource, @NotNull String name, @NotNull Object @NotNull ... properties) {
return resource(resource, name, MapUtil.toMap(properties));
}
/**
* Ensure that a resource exists at the given path. If not, it is created
* using <code>nt:unstructured</code> node type.
* @param path Resource path
* @return Resource at path (existing or newly created)
*/
@SuppressWarnings("null")
protected final @NotNull Resource ensureResourceExists(@NotNull String path) {
if (StringUtils.isEmpty(path) || StringUtils.equals(path, "/")) {
return resourceResolver.getResource("/");
}
Resource resource = resourceResolver.getResource(path);
if (resource != null) {
return resource;
}
String parentPath = ResourceUtil.getParent(path);
if (parentPath == null) {
throw new IllegalArgumentException("Path has no parent: " + path);
}
String name = ResourceUtil.getName(path);
Resource parentResource = ensureResourceExists(parentPath);
try {
resource = resourceResolver.create(parentResource, name,
ImmutableValueMap.of(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED));
resourceResolver.commit();
return resource;
} catch (PersistenceException ex) {
throw new RuntimeException("Unable to create resource at " + path, ex);
}
}
}