Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.merkle.oss.magnolia.powernode.NodeService Maven / Gradle / Ivy
package com.merkle.oss.magnolia.powernode;
import info.magnolia.jcr.util.NodeNameHelper;
import info.magnolia.jcr.util.NodeTypes;
import info.magnolia.jcr.util.NodeUtil;
import info.magnolia.jcr.wrapper.I18nNodeWrapper;
import java.util.Iterator;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import com.merkle.oss.magnolia.powernode.predicate.magnolia.IsMetaData;
import com.merkle.oss.magnolia.powernode.predicate.magnolia.IsMetaDataProperty;
public class NodeService extends RepositoryExceptionDelegator {
private final LocalizedNameProvider localizedNameProvider;
private final NodeNameHelper nodeNameHelper;
private final JcrSessionProvider jcrSessionProvider;
private final PropertyService propertyService;
@Inject
public NodeService(
final LocalizedNameProvider localizedNameProvider,
final NodeNameHelper nodeNameHelper,
final JcrSessionProvider jcrSessionProvider,
final PropertyService propertyService
) {
this.localizedNameProvider = localizedNameProvider;
this.nodeNameHelper = nodeNameHelper;
this.jcrSessionProvider = jcrSessionProvider;
this.propertyService = propertyService;
}
public Optional getSession(final String workspace) {
return get(() -> jcrSessionProvider.getSession(workspace));
}
public Optional getSystemSession(final String workspace) {
return get(() -> jcrSessionProvider.getSystemSession(workspace));
}
public Optional getByIdentifier(final String workspace, final String identifier) {
return getSession(workspace).flatMap(session -> getByIdentifier(session, identifier));
}
public Optional getByIdentifier(final Session session, final String identifier) {
return get(() -> session.getNodeByIdentifier(identifier));
}
public Optional getByPath(final String workspace, final String path) {
return getSession(workspace).flatMap(session -> getByPath(session, path));
}
public Optional getByPath(final Session session, final String path) {
return get(() -> session.getNode(path));
}
public Optional getRootNode(final String workspace) {
return getSession(workspace).map(this::getRootNode);
}
public Node getRootNode(final Session session) {
return getOrThrow(session::getRootNode);
}
public void rename(final Node node, final String newName) {
run(() -> {
if (!Objects.equals(node.getName(), newName)) {
final String validatedName = nodeNameHelper.getValidatedName(newName);
final String destinationPath = node.getParent().getPath() + "/" + validatedName;
@Nullable
final Node nextSibling = getNextSibling(node).orElse(null);
node.getSession().move(node.getPath(), destinationPath);
if(nextSibling != null) {
// Restore order of nodes (https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/change-node-name-without-move-method/m-p/299414)
node.getParent().orderBefore(validatedName, nextSibling.getName());
}
NodeTypes.LastModified.update(node);
}
});
}
private Optional getNextSibling(final Node node) {
final String nodeName = getOrThrow(node::getName);
return getParent(node).stream().flatMap(this::streamChildren).dropWhile(sibling -> Objects.equals(getOrThrow(sibling::getName), nodeName)).findFirst();
}
public void move(final Node node, final Node newParent) {
if (!getOrThrow(() -> node.getParent().isSame(newParent))) {
run(() -> {
final String destinationPath = newParent.getPath() + "/" + node.getName();
node.getSession().move(node.getPath(), destinationPath);
NodeTypes.LastModified.update(node);
NodeTypes.LastModified.update(newParent);
});
}
}
public void copy(final Node src, final Node dest, final Predicate recursiveChildNodePredicate, final Predicate propertyPredicate, final BiConsumer copyConsumer) {
run(() -> {
final Node copy = dest.addNode(src.getName(), src.getPrimaryNodeType().getName());
copyProperties(src, copy, propertyPredicate);
copyConsumer.accept(src, copy);
streamChildren(src, recursiveChildNodePredicate).forEach(page ->
copy(page, copy, recursiveChildNodePredicate, propertyPredicate, copyConsumer)
);
});
}
private void copyProperties(final Node src, final Node dest, final Predicate propertyPredicate) throws RepositoryException {
final PropertyIterator properties = src.getProperties();
while (properties.hasNext()) {
final Property property = properties.nextProperty();
if(new IsMetaDataProperty().negate().and(propertyPredicate).test(property)) {
if(property.isMultiple()) {
dest.setProperty(property.getName(), property.getValues());
}else {
dest.setProperty(property.getName(), property.getValue());
}
}
}
}
public Node getOrAddChild(final Node node, @Nullable final String primaryNodeTypeName, final String relativePath) {
final String[] relativePaths = relativePath.split("/", 2);
final Node childNode = getOrAddChildInternally(node, primaryNodeTypeName, relativePaths[0]);
if(relativePaths.length > 1) {
return getOrAddChild(childNode, primaryNodeTypeName, relativePaths[1]);
}
return childNode;
}
public Node getOrAddChild(final Node node, @Nullable final String primaryNodeTypeName, final String relativePath, final Locale locale) {
final String[] relativePaths = relativePath.split("/", 2);
final Node childNode = localizeNode(node, relativePaths[0], locale, localizedChildNodeName -> getOrAddChildInternally(node, primaryNodeTypeName, localizedChildNodeName));
if(relativePaths.length > 1) {
return getOrAddChild(childNode, primaryNodeTypeName, relativePaths[1], locale);
}
return childNode;
}
private Node getOrAddChildInternally(final Node node, @Nullable final String primaryNodeTypeName, final String childName) {
return getChild(node, childName).orElseGet(() -> getOrThrow(() -> node.addNode(childName, primaryNodeTypeName)));
}
/**
* Gets child by localizing all relative path names.
* e.g. /node1/child_de/grandchild_de
*/
public Optional getChild(final Node node, final String relativePath, final Locale locale) {
final String[] relativePaths = relativePath.split("/", 2);
return localizeNode(node, relativePaths[0], locale, localizedChildNodeName -> getChild(node, localizedChildNodeName)).flatMap(child ->
relativePaths.length > 1 ? getChild(child, relativePaths[1], locale) : Optional.of(child)
);
}
public Optional getChild(final Node node, final String relativePath) {
return get(() -> node.getNode(relativePath));
}
public Stream streamChildren(final Node node) {
return get(node::getNodes).stream()
.map(nodeIterator -> (Iterator)nodeIterator)
.flatMap(nodeIterator ->
StreamSupport.stream(Spliterators.spliteratorUnknownSize(nodeIterator, Spliterator.ORDERED), false)
)
.filter(new IsMetaData<>().negate());
}
public Stream streamChildren(final Node node, final Predicate predicate) {
return streamChildren(node).filter(predicate);
}
public Stream streamChildrenRecursive(final Node node) {
return streamChildren(node).flatMap(child ->
Stream.concat(
Stream.of(child),
streamChildrenRecursive(child)
)
);
}
public Stream streamChildrenRecursive(final Node node, final Predicate predicate) {
return streamChildrenRecursive(node).filter(predicate);
}
public Optional getParent(final Node node) {
return get(node::getParent);
}
public Optional getAncestor(final Node node, final Predicate predicate) {
return getParent(node).flatMap(parent ->
Optional.of(parent).filter(predicate).or(() -> getAncestor(parent, predicate))
);
}
public Optional getAncestorOrSelf(final Node node, final Predicate predicate) {
if(predicate.test(node)) {
return Optional.of(node);
}
return getAncestor(node, predicate);
}
public boolean hasProperty(final Node node, final String propertyName) {
return getOrThrow(() -> node.hasProperty(propertyName));
}
public boolean hasProperty(final Node node, final String propertyName, final Locale locale) {
return localizeProperty(node, propertyName, locale, localizedPropertyName -> hasProperty(node, localizedPropertyName));
}
public Optional getProperty(final Node node, final String propertyName, final PropertyService.PropertyProvider provider) {
return get(() -> propertyService.getProperty(node, propertyName, provider)).flatMap(Function.identity());
}
public Optional getProperty(final Node node, final String propertyName, final Locale locale, final PropertyService.PropertyProvider provider) {
return localizeProperty(node, propertyName, locale, localizedPropertyName -> getProperty(node, localizedPropertyName, provider));
}
public Stream streamMultiProperty(final Node node, final String propertyName, final PropertyService.PropertyProvider provider) {
return get(() -> propertyService.streamMultiProperty(node, propertyName, provider)).stream().flatMap(Function.identity());
}
public Stream streamMultiProperty(final Node node, final String propertyName, final Locale locale, final PropertyService.PropertyProvider provider) {
return localizeProperty(node, propertyName, locale, localizedPropertyName -> streamMultiProperty(node, localizedPropertyName, provider));
}
public Property setProperty(final Node node, final String propertyName, @Nullable final T value, final PropertyService.ValueFactory factory) {
return getOrThrow(() -> propertyService.setProperty(node, propertyName, value, factory));
}
public Property setProperty(final Node node, final String propertyName, final Locale locale, @Nullable final T value, final PropertyService.ValueFactory factory) {
return localizeProperty(node, propertyName, locale, localizedPropertyName -> setProperty(node, localizedPropertyName, value, factory));
}
public Property setMultiProperty(final Node node, final String propertyName, final Iterable values, final PropertyService.ValueFactory factory) {
return getOrThrow(() -> propertyService.setMultiProperty(node, propertyName, values, factory));
}
public Property setMultiProperty(final Node node, final String propertyName, final Locale locale, final Iterable values, final PropertyService.ValueFactory factory) {
return localizeProperty(node, propertyName, locale, localizedPropertyName -> setMultiProperty(node, localizedPropertyName, values, factory));
}
public Optional removeProperty(final Node node, final String propertyName) {
return get(() -> propertyService.removeProperty(node, propertyName)).flatMap(Function.identity());
}
public Optional removeProperty(final Node node, final String propertyName, final Locale locale) {
return localizeProperty(node, propertyName, locale, localizedPropertyName -> removeProperty(node, localizedPropertyName));
}
private T localizeProperty(final Node node, final String propertyName, final Locale locale, final Function provider) {
if (!NodeUtil.isWrappedWith(node, I18nNodeWrapper.class)) {
return provider.apply(localizedNameProvider.getLocalizedPropertyName(node, propertyName, locale));
}
return provider.apply(propertyName);
}
private T localizeNode(final Node node, final String nodeName, final Locale locale, final Function provider) {
return provider.apply(localizedNameProvider.getLocalizedNodeName(node, nodeName, locale));
}
}