eu.ciechanowiec.sling.rocket.jcr.NodeProperties Maven / Gradle / Ivy
Show all versions of sling.rocket.commons Show documentation
package eu.ciechanowiec.sling.rocket.jcr;
import eu.ciechanowiec.conditional.Conditional;
import eu.ciechanowiec.sling.rocket.commons.ResourceAccess;
import eu.ciechanowiec.sling.rocket.jcr.path.JCRPath;
import eu.ciechanowiec.sling.rocket.jcr.path.WithJCRPath;
import eu.ciechanowiec.sling.rocket.unit.DataSize;
import eu.ciechanowiec.sling.rocket.unit.DataUnit;
import eu.ciechanowiec.sneakyfun.SneakyConsumer;
import lombok.SneakyThrows;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import javax.jcr.*;
import javax.jcr.nodetype.NodeType;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import static eu.ciechanowiec.sneakyfun.SneakyFunction.sneaky;
/**
*
* Represents {@link Property}-ies of a {@link Node}.
*
*
* The class provides API operations on {@link Property}-ies
* in a way detached from an ongoing {@link Session}. {@link Session}'s live cycle is supposed to be fully
* managed by {@link NodeProperties} itself in an encapsulated manner.
*
*/
@SuppressWarnings({
"WeakerAccess", "ClassWithTooManyMethods", "MethodCount", "MultipleStringLiterals",
"PMD.AvoidDuplicateLiterals", "PMD.CouplingBetweenObjects", "PMD.ExcessivePublicCount"
})
@Slf4j
@ToString
public class NodeProperties implements WithJCRPath {
private final JCRPath jcrPath;
@ToString.Exclude
private final ResourceAccess resourceAccess;
/**
* Constructs an instance of this class.
* @param jcrNodePath {@link JCRPath} to the underlying {@link Node}
* @param resourceAccess {@link ResourceAccess} that will be used by the constructed
* object to acquire access to resources
*/
public NodeProperties(JCRPath jcrNodePath, ResourceAccess resourceAccess) {
this.jcrPath = jcrNodePath;
this.resourceAccess = resourceAccess;
log.trace("Initialized {}", this);
}
/**
* Constructs an instance of this class.
* @param withJCRPath object that contains a {@link JCRPath} to the underlying {@link Node}
* @param resourceAccess {@link ResourceAccess} that will be used by the constructed
* object to acquire access to resources
*/
public NodeProperties(WithJCRPath withJCRPath, ResourceAccess resourceAccess) {
this(withJCRPath.jcrPath(), resourceAccess);
}
/**
* Retrieves the primary type of the underlying {@link Node}.
* @return primary type of the underlying {@link Node}
*/
public String primaryType() {
log.trace("Retrieving the primary type of {}", this);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(sneaky(node -> Optional.ofNullable(node.getPrimaryNodeType())))
.map(NodeType::getName)
.orElseThrow();
}
}
/**
* Checks if the underlying {@link Node} is of one of the specified primary types.
* @param acceptablePrimaryTypes names of the primary types against which the check is performed
* @return {@code true} if the underlying {@link Node} is of one of the specified primary types;
* {@code false} otherwise
*/
public boolean isPrimaryType(String... acceptablePrimaryTypes) {
return isPrimaryType(List.of(acceptablePrimaryTypes));
}
/**
* Checks if the underlying {@link Node} is of one of the specified primary types.
* @param acceptablePrimaryTypes names of the primary types against which the check is performed
* @return {@code true} if the underlying {@link Node} is of one of the specified primary types;
* {@code false} otherwise
*/
public boolean isPrimaryType(Collection acceptablePrimaryTypes) {
log.trace("Checking if {} is of this primary type: '{}'", this, acceptablePrimaryTypes);
String actualPrimaryType = primaryType();
return acceptablePrimaryTypes.stream().anyMatch(actualPrimaryType::equals);
}
/**
* Asserts that the underlying {@link Node} is of the specified primary type.
* @param expectedPrimaryType name of the primary type against which the assertion is performed
* @throws IllegalPrimaryTypeException if the underlying {@link Node} isn't of the specified primary type
*/
public void assertPrimaryType(String expectedPrimaryType) {
log.trace("Asserting that {} is of '{}' primary type", this, expectedPrimaryType);
Conditional.isTrueOrThrow(
isPrimaryType(expectedPrimaryType), new IllegalPrimaryTypeException(expectedPrimaryType)
);
}
/**
*
* Retrieves the {@link Value} of the specified {@link Property} and converts it into the given type.
*
*
* -
* It is guaranteed that the method supports types specified in the {@link Class} fields of
* {@link DefaultProperties}. Other types and translations between types are supported to the extent that they
* are supported by the underlying {@link ValueMap#get(String, Object)} method.
*
* -
* To ensure that the supported type is passed, it is recommended to use factory {@code of} methods from
* {@link DefaultProperties} when specifying the default value, e.g.:
*
{@code
* double price = nodeProperties.propertyValue("price", DefaultProperties.of(99.99));
* }
*
* -
*
* Both unary and multi-valued {@link Property}-ies are supported.
*
* Usage example with a unary {@link Property}:
* {@code
* long price = nodeProperties.propertyValue("price", DefaultProperties.LONG_ZERO);
* String name = nodeProperties.propertyValue("name", DefaultProperties.STRING_EMPTY);
* }
* Usage example with a multi-valued {@link Property}:
* {@code
* long[] prices = nodeProperties.propertyValue("prices", new long[]{DefaultProperties.LONG_ZERO});
* String[] names = nodeProperties.propertyValue("names", new String[]{DefaultProperties.STRING_EMPTY});
* }
*
*
* @param propertyName name of the {@link Property} from which the {@link Value} should be retrieved
* @param defaultValue default {@link Value} to use if the specified {@link Property} does not exist or
* its value cannot be converted to the requested type; the {@code defaultValue} is also used
* to define the type to convert the {@link Value} to
* @return {@link Value} of the specified {@link Property} converted to the requested type or the
* {@code defaultValue} if the specified {@link Property} does not exist or its {@link Value} cannot be
* converted to the requested type
* @param expected type
*/
public T propertyValue(String propertyName, T defaultValue) {
log.trace("Getting '{}' property value for {}", propertyName, this);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.map(Resource::getValueMap)
.map(WithPrimitiveArrayTranslation::new)
.map(valueMapWithTranslation -> valueMapWithTranslation.get(propertyName, defaultValue))
.orElse(defaultValue);
}
}
/**
*
* Retrieves the {@link Value} of the specified {@link Property} and converts it into the given type.
*
*
* -
* It is guaranteed that the method supports types specified in the {@link Class} fields of
* {@link DefaultProperties}. Other types and translations between types are supported to the extent that they
* are supported by the underlying {@link ValueMap#get(String, Class)} method.
*
* -
* To ensure that the supported type is passed, it is recommended to use {@link Class} fields of
* {@link DefaultProperties} when specifying the default value, e.g.:
*
{@code
* Optional price = nodeProperties.propertyValue("price", DefaultProperties.DOUBLE_CLASS);
* }
*
* -
*
* Both unary and multi-valued {@link Property}-ies are supported.
*
*
* Usage example with a unary {@link Property}:
*
{@code
* Optional price = nodeProperties.propertyValue("price", DefaultProperties.LONG_CLASS);
* Optional name = nodeProperties.propertyValue("name", DefaultProperties.STRING_CLASS);}
*
* Usage example with a multi-valued {@link Property}:
* {@code
* Optional prices = nodeProperties.propertyValue("prices", DefaultProperties.LONG_CLASS_ARRAY);
* Optional names = nodeProperties.propertyValue("names", DefaultProperties.STRING_CLASS_ARRAY);
* }
*
*
* @param propertyName name of the {@link Property} from which the {@link Value} should be retrieved
* @param type {@link Class} with the type that should represent the requested {@link Value} and which that
* {@link Value} will be cast to
* @return {@link Optional} containing the {@link Value} of the specified {@link Property} converted to the
* requested type; if the specified {@link Property} does not exist or its {@link Value} cannot be
* converted to the requested type, an empty {@link Optional} is returned
* @param expected type
*/
public Optional propertyValue(String propertyName, Class type) {
log.trace("Getting '{}' property value for {}", propertyName, this);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.map(Resource::getValueMap)
.map(WithPrimitiveArrayTranslation::new)
.flatMap(valueMapWithTranslation -> valueMapWithTranslation.get(propertyName, type));
}
}
/**
* Retrieves the {@link PropertyType} of the specified {@link Property}.
* @param propertyName name of the {@link Property} whose {@link PropertyType} should be retrieved
* @return {@link PropertyType} of the specified {@link Property}
*/
public int propertyType(String propertyName) {
log.trace("Getting '{}' property type for {}", propertyName, this);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> new ConditionalProperty(propertyName).retrieveFrom(node))
.map(sneaky(Property::getValue))
.map(Value::getType)
.orElse(PropertyType.UNDEFINED);
}
}
/**
* Checks if the underlying {@link Node} contains a {@link Property} that has the specified name.
* @param propertyName name of the hypothetically existent {@link Property}
* @return {@code true} if the underlying {@link Node} contains a {@link Property} that has the specified name;
* {@code false} otherwise
*/
public boolean containsProperty(String propertyName) {
log.trace("Checking if '{}' contains property of this name: '{}'", this, propertyName);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.map(Resource::getValueMap)
.map(valueMap -> valueMap.containsKey(propertyName))
.orElse(false);
}
}
/**
* Retrieves the {@link Value} of a {@link Property} of type {@link PropertyType#BINARY} as a {@link File}.
* @param propertyName name of the {@link Property} from which the {@link Value} of type {@link PropertyType#BINARY}
* should be retrieved
* @return {@link Value} of a {@link Property} of type {@link PropertyType#BINARY} as a {@link File};
* empty {@link Optional} is returned if the {@link Property} isn't of type {@link PropertyType#BINARY}
* or doesn't exist
*/
public Optional retrieveFile(String propertyName) {
log.trace("Getting the value of the '{}' property as a file. {}", propertyName, this);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> new ConditionalProperty(propertyName).retrieveFrom(node))
.map(sneaky(Property::getValue))
.flatMap(this::asBinary)
.map(this::asFile);
}
}
/**
* Retrieves the {@link DataSize} of a {@link Value} of a {@link Property} of type {@link PropertyType#BINARY}.
* @param propertyName name of the {@link Property} of type {@link PropertyType#BINARY}
* that contains a {@link Value} whose {@link DataSize} should be retrieved
* @return {@link DataSize} of a {@link Value} of a {@link Property} of type {@link PropertyType#BINARY};
* zero-sized {@link DataSize} is returned if the {@link Property} isn't of type {@link PropertyType#BINARY}
* or doesn't exist
*/
public DataSize binarySize(String propertyName) {
log.trace("Getting the value of the '{}' property as a file. {}", propertyName, this);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> new ConditionalProperty(propertyName).retrieveFrom(node))
.map(sneaky(Property::getValue))
.flatMap(this::asBinary)
.map(sneaky(Binary::getSize))
.map(bytes -> new DataSize(bytes, DataUnit.BYTES))
.orElse(new DataSize(0, DataUnit.BYTES));
}
}
/**
*
* Returns all {@link Property}-ies of the underlying {@link Node} as a {@link Map}
* of {@link Property} names to {@link Property} {@link Value}-s converted to {@link String}.
*
* The following {@link Property}-ies are omitted from the result:
*
* - {@link Property}-ies with {@link Value}-s that cannot be converted to {@link String}
* - {@link Property}-ies of type {@link PropertyType#BINARY}
*
* @return {@link Property}-ies of the underlying {@link Node} as a {@link Map}
* of {@link Property} names to {@link Property} {@link Value}-s converted to {@link String}
*/
public Map all() {
log.trace("Retrieving all properties of {}", this);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
return Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.map(Resource::getValueMap)
.map(ValueMap::keySet)
.orElse(Set.of())
.stream()
.filter(propertyName -> propertyType(propertyName) != PropertyType.BINARY)
.map(propertyName -> Map.entry(
propertyName, propertyValue(propertyName, DefaultProperties.STRING_CLASS))
)
.filter(entry -> entry.getValue().isPresent())
.map(entry -> Map.entry(entry.getKey(), entry.getValue().orElseThrow()))
.collect(Collectors.toUnmodifiableMap(
Map.Entry::getKey, Map.Entry::getValue, (first, second) -> first)
);
}
}
/**
*
* Sets the value of the specified {@link Property} according to the logic described in
* {@link Node#setProperty(String, String)}.
*
* This operation can overwrite the current {@link PropertyType} of the existing {@link Property} if it differs from
* the new {@link PropertyType}. However, such overwriting behavior is supported only to the extent to which
* it is supported by the underlying {@link Node#setProperty(String, String)}.
* @param name name of the {@link Property} to set
* @param value value of the {@link Property} to set
* @return {@link Optional} containing this {@link NodeProperties} if the {@link Property} was set successfully;
* an empty {@link Optional} is returned if the {@link Property} wasn't set due to any reason
*/
@SuppressWarnings("PMD.LinguisticNaming")
public Optional setProperty(String name, String value) {
log.trace("Setting property '{}' to '{}'", name, value);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
Optional result = Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> setProperty(node, name, value));
result.ifPresent(SneakyConsumer.sneaky(nodeProperties -> resourceResolver.commit()));
return result;
}
}
/**
*
* Sets the value of the specified {@link Property} according to the logic described in
* {@link Node#setProperty(String, boolean)}.
*
* This operation can overwrite the current {@link PropertyType} of the existing {@link Property} if it differs from
* the new {@link PropertyType}. However, such overwriting behavior is supported only to the extent to which
* it is supported by the underlying {@link Node#setProperty(String, boolean)}.
* @param name name of the {@link Property} to set
* @param value value of the {@link Property} to set
* @return {@link Optional} containing this {@link NodeProperties} if the {@link Property} was set successfully;
* an empty {@link Optional} is returned if the {@link Property} wasn't set due to any reason
*/
@SuppressWarnings("PMD.LinguisticNaming")
public Optional setProperty(String name, boolean value) {
log.trace("Setting property '{}' to '{}'", name, value);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
Optional result = Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> setProperty(node, name, value));
result.ifPresent(SneakyConsumer.sneaky(nodeProperties -> resourceResolver.commit()));
return result;
}
}
/**
*
* Sets the value of the specified {@link Property} according to the logic described in
* {@link Node#setProperty(String, long)}.
*
* This operation can overwrite the current {@link PropertyType} of the existing {@link Property} if it differs from
* the new {@link PropertyType}. However, such overwriting behavior is supported only to the extent to which
* it is supported by the underlying {@link Node#setProperty(String, long)}.
* @param name name of the {@link Property} to set
* @param value value of the {@link Property} to set
* @return {@link Optional} containing this {@link NodeProperties} if the {@link Property} was set successfully;
* an empty {@link Optional} is returned if the {@link Property} wasn't set due to any reason
*/
@SuppressWarnings("PMD.LinguisticNaming")
public Optional setProperty(String name, long value) {
log.trace("Setting property '{}' to '{}'", name, value);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
Optional result = Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> setProperty(node, name, value));
result.ifPresent(SneakyConsumer.sneaky(nodeProperties -> resourceResolver.commit()));
return result;
}
}
/**
*
* Sets the value of the specified {@link Property} according to the logic described in
* {@link Node#setProperty(String, double)}.
*
* This operation can overwrite the current {@link PropertyType} of the existing {@link Property} if it differs from
* the new {@link PropertyType}. However, such overwriting behavior is supported only to the extent to which
* it is supported by the underlying {@link Node#setProperty(String, double)}.
* @param name name of the {@link Property} to set
* @param value value of the {@link Property} to set
* @return {@link Optional} containing this {@link NodeProperties} if the {@link Property} was set successfully;
* an empty {@link Optional} is returned if the {@link Property} wasn't set due to any reason
*/
@SuppressWarnings("PMD.LinguisticNaming")
public Optional setProperty(String name, double value) {
log.trace("Setting property '{}' to '{}'", name, value);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
Optional result = Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> setProperty(node, name, value));
result.ifPresent(SneakyConsumer.sneaky(nodeProperties -> resourceResolver.commit()));
return result;
}
}
/**
*
* Sets the value of the specified {@link Property} according to the logic described in
* {@link Node#setProperty(String, BigDecimal)}.
*
* This operation can overwrite the current {@link PropertyType} of the existing {@link Property} if it differs from
* the new {@link PropertyType}. However, such overwriting behavior is supported only to the extent to which
* it is supported by the underlying {@link Node#setProperty(String, BigDecimal)}.
* @param name name of the {@link Property} to set
* @param value value of the {@link Property} to set
* @return {@link Optional} containing this {@link NodeProperties} if the {@link Property} was set successfully;
* an empty {@link Optional} is returned if the {@link Property} wasn't set due to any reason
*/
@SuppressWarnings("PMD.LinguisticNaming")
public Optional setProperty(String name, BigDecimal value) {
log.trace("Setting property '{}' to '{}'", name, value);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
Optional result = Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> setProperty(node, name, value));
result.ifPresent(SneakyConsumer.sneaky(nodeProperties -> resourceResolver.commit()));
return result;
}
}
/**
*
* Sets the value of the specified {@link Property} according to the logic described in
* {@link Node#setProperty(String, Calendar)}.
*
* This operation can overwrite the current {@link PropertyType} of the existing {@link Property} if it differs from
* the new {@link PropertyType}. However, such overwriting behavior is supported only to the extent to which
* it is supported by the underlying {@link Node#setProperty(String, Calendar)}.
* @param name name of the {@link Property} to set
* @param value value of the {@link Property} to set
* @return {@link Optional} containing this {@link NodeProperties} if the {@link Property} was set successfully;
* an empty {@link Optional} is returned if the {@link Property} wasn't set due to any reason
*/
@SuppressWarnings("PMD.LinguisticNaming")
public Optional setProperty(String name, Calendar value) {
log.trace("Setting property '{}' to '{}'", name, value);
try (ResourceResolver resourceResolver = resourceAccess.acquireAccess()) {
String jcrPathRaw = jcrPath.get();
Optional result = Optional.ofNullable(resourceResolver.getResource(jcrPathRaw))
.flatMap(resource -> Optional.ofNullable(resource.adaptTo(Node.class)))
.flatMap(node -> setProperty(node, name, value));
result.ifPresent(SneakyConsumer.sneaky(nodeProperties -> resourceResolver.commit()));
return result;
}
}
@SuppressWarnings("PMD.LinguisticNaming")
private Optional setProperty(Node node, String name, String value) {
try {
node.setProperty(name, value);
log.trace("Property '{}' set to '{}' for {}", name, value, this);
return Optional.of(this);
} catch (@SuppressWarnings("OverlyBroadCatchBlock") RepositoryException exception) {
String message = String.format(
"Unable to set property '%s' to '%s' for %s", name, value, this
);
log.error(message, exception);
return Optional.empty();
}
}
@SuppressWarnings("PMD.LinguisticNaming")
private Optional setProperty(Node node, String name, boolean value) {
try {
node.setProperty(name, value);
log.trace("Property '{}' set to '{}' for {}", name, value, this);
return Optional.of(this);
} catch (@SuppressWarnings("OverlyBroadCatchBlock") RepositoryException exception) {
String message = String.format(
"Unable to set property '%s' to '%s' for %s", name, value, this
);
log.error(message, exception);
return Optional.empty();
}
}
@SuppressWarnings("PMD.LinguisticNaming")
private Optional setProperty(Node node, String name, long value) {
try {
node.setProperty(name, value);
log.trace("Property '{}' set to '{}' for {}", name, value, this);
return Optional.of(this);
} catch (@SuppressWarnings("OverlyBroadCatchBlock") RepositoryException exception) {
String message = String.format(
"Unable to set property '%s' to '%s' for %s", name, value, this
);
log.error(message, exception);
return Optional.empty();
}
}
@SuppressWarnings("PMD.LinguisticNaming")
private Optional setProperty(Node node, String name, double value) {
try {
node.setProperty(name, value);
log.trace("Property '{}' set to '{}' for {}", name, value, this);
return Optional.of(this);
} catch (@SuppressWarnings("OverlyBroadCatchBlock") RepositoryException exception) {
String message = String.format(
"Unable to set property '%s' to '%s' for %s", name, value, this
);
log.error(message, exception);
return Optional.empty();
}
}
@SuppressWarnings("PMD.LinguisticNaming")
private Optional setProperty(Node node, String name, BigDecimal value) {
try {
node.setProperty(name, value);
log.trace("Property '{}' set to '{}' for {}", name, value, this);
return Optional.of(this);
} catch (@SuppressWarnings("OverlyBroadCatchBlock") RepositoryException exception) {
String message = String.format(
"Unable to set property '%s' to '%s' for %s", name, value, this
);
log.error(message, exception);
return Optional.empty();
}
}
@SuppressWarnings("PMD.LinguisticNaming")
private Optional setProperty(Node node, String name, Calendar value) {
try {
node.setProperty(name, value);
log.trace("Property '{}' set to '{}' for {}", name, value, this);
return Optional.of(this);
} catch (@SuppressWarnings("OverlyBroadCatchBlock") RepositoryException exception) {
String message = String.format(
"Unable to set property '%s' to '%s' for %s", name, value, this
);
log.error(message, exception);
return Optional.empty();
}
}
@SneakyThrows
private Optional asBinary(Value value) {
int valueType = value.getType();
if (valueType == PropertyType.BINARY) {
Binary binary = value.getBinary();
return Optional.of(binary);
} else {
log.trace("Not a binary type");
return Optional.empty();
}
}
@SneakyThrows
private File asFile(Binary binary) {
log.trace("Converting binary to a file");
File tempFile = File.createTempFile("jcr-binary_", ".tmp");
tempFile.deleteOnExit();
Path tempFilePath = tempFile.toPath();
try (InputStream inputStream = binary.getStream();
OutputStream outputStream = Files.newOutputStream(tempFilePath)) {
IOUtils.copy(inputStream, outputStream);
binary.dispose();
}
log.trace("Converted binary to a file: {}", tempFile);
return tempFile;
}
@Override
public JCRPath jcrPath() {
return jcrPath;
}
}