blob: 8cecb1320849697586a6d18537862450290db979 [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.jcr.resource.internal.helper.jcr;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Iterator;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import org.apache.sling.adapter.annotations.Adaptable;
import org.apache.sling.adapter.annotations.Adapter;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Adaptable(adaptableClass = Resource.class, adapters = {
@Adapter(value = { Item.class, Property.class, Value.class, String.class, Boolean.class, Long.class,
Double.class, BigDecimal.class, Calendar.class, InputStream.class, Value[].class, String[].class,
Boolean[].class, Long[].class, Double[].class, BigDecimal[].class }),
@Adapter(value = Node.class, condition = "If the resource is a JcrPropertyResource and the property is a reference or weak reference property.") })
class JcrPropertyResource extends JcrItemResource<Property> { // this should be package private, see SLING-1414
/** default log */
private static final Logger LOGGER = LoggerFactory.getLogger(JcrPropertyResource.class);
private final String resourceType;
public JcrPropertyResource(@NotNull final ResourceResolver resourceResolver,
@NotNull final String path,
@Nullable final String version,
@NotNull final Property property) throws RepositoryException {
super(resourceResolver, path, version, property, new ResourceMetadata());
this.resourceType = getResourceTypeForNode(property.getParent())
+ "/" + property.getName();
if (PropertyType.BINARY != getProperty().getType()) {
this.getResourceMetadata().setContentType("text/plain");
this.getResourceMetadata().setCharacterEncoding("UTF-8");
}
this.getResourceMetadata().setContentLength(getContentLength(property));
}
public @NotNull String getResourceType() {
return resourceType;
}
public @Nullable String getResourceSuperType() {
return null;
}
@Override
@SuppressWarnings("unchecked")
public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
// the property itself
if (type == Property.class || type == Item.class) {
return (AdapterType) getProperty();
}
// the property value
try {
if (type == String.class) {
return (AdapterType) getProperty().getString();
} else if (type == Boolean.class) {
return (AdapterType) Boolean.valueOf(getProperty().getBoolean());
} else if (type == Long.class) {
return (AdapterType) Long.valueOf(getProperty().getLong());
} else if (type == Double.class) {
return (AdapterType) new Double(getProperty().getDouble());
} else if (type == BigDecimal.class) {
return (AdapterType) getProperty().getDecimal();
} else if (type == Calendar.class) {
return (AdapterType) getProperty().getDate();
} else if (type == Value.class) {
return (AdapterType) getProperty().getValue();
} else if (type == Node.class
&& (getProperty().getType() == PropertyType.REFERENCE ||
getProperty().getType() == PropertyType.WEAKREFERENCE)) {
return (AdapterType) getProperty().getNode();
} else if (type == InputStream.class) {
return (AdapterType) getInputStream();
} else if ( type == String[].class ) {
if ( getProperty().getDefinition().isMultiple() ) {
final Value[] values = getProperty().getValues();
final String[] result = new String[values.length];
for(int i=0; i<values.length; i++) {
result[i] = values[i].getString();
}
return (AdapterType)result;
}
return (AdapterType)new String[] {getProperty().getString()};
} else if (type == Boolean[].class) {
if ( getProperty().getDefinition().isMultiple() ) {
final Value[] values = getProperty().getValues();
final Boolean[] result = new Boolean[values.length];
for(int i=0; i<values.length; i++) {
result[i] = values[i].getBoolean();
}
return (AdapterType)result;
}
return (AdapterType)new Boolean[] {getProperty().getBoolean()};
} else if (type == Long[].class) {
if ( getProperty().getDefinition().isMultiple() ) {
final Value[] values = getProperty().getValues();
final Long[] result = new Long[values.length];
for(int i=0; i<values.length; i++) {
result[i] = values[i].getLong();
}
return (AdapterType)result;
}
return (AdapterType)new Long[] {getProperty().getLong()};
} else if (type == Double[].class) {
if ( getProperty().getDefinition().isMultiple() ) {
final Value[] values = getProperty().getValues();
final Double[] result = new Double[values.length];
for(int i=0; i<values.length; i++) {
result[i] = values[i].getDouble();
}
return (AdapterType)result;
}
return (AdapterType)new Double[] {getProperty().getDouble()};
} else if (type == BigDecimal[].class) {
if ( getProperty().getDefinition().isMultiple() ) {
final Value[] values = getProperty().getValues();
final BigDecimal[] result = new BigDecimal[values.length];
for(int i=0; i<values.length; i++) {
result[i] = values[i].getDecimal();
}
return (AdapterType)result;
}
return (AdapterType)new BigDecimal[] {getProperty().getDecimal()};
} else if (type == Calendar[].class) {
if ( getProperty().getDefinition().isMultiple() ) {
final Value[] values = getProperty().getValues();
final Calendar[] result = new Calendar[values.length];
for(int i=0; i<values.length; i++) {
result[i] = values[i].getDate();
}
return (AdapterType)result;
}
return (AdapterType)new Calendar[] {getProperty().getDate()};
} else if (type == Value[].class) {
if ( getProperty().getDefinition().isMultiple() ) {
return (AdapterType)getProperty().getValues();
}
return (AdapterType)new Value[] {getProperty().getValue()};
}
} catch (ValueFormatException vfe) {
LOGGER.debug("adaptTo: Problem accessing the property value of {}: {}",
getPath(), vfe.getMessage());
LOGGER.debug("adaptTo: Cause", vfe);
} catch (RepositoryException re) {
LOGGER.debug("adaptTo: Problem accessing the property " + getPath(), re);
}
// try to use adapter factories
return super.adaptTo(type);
}
@Override
public String toString() {
return getClass().getSimpleName() + ", type=" + getResourceType()
+ ", path=" + getPath();
}
private @NotNull Property getProperty() {
return getItem();
}
private InputStream getInputStream() {
Property prop = getProperty();
try {
return prop.getBinary().getStream();
} catch (RepositoryException re) {
LOGGER.error("getInputStream: Problem accessing the property "
+ getPath() + " stream", re);
}
// fall back to none in case of an error
return null;
}
@Override
@Nullable Iterator<Resource> listJcrChildren() {
return null;
}
@Override
public boolean hasChildren() {
return false;
}
}