Author: cziegeler Date: Thu Apr 13 14:30:40 2017 New Revision: 1791259 URL: http://svn.apache.org/viewvc?rev=1791259&view=rev Log: SLING-6723 : Make dependency to javax.jcr, jcr.contentloader and jcr.api optional
Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupport.java sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupportImpl.java sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupport.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupport.java?rev=1791259&r1=1791258&r2=1791259&view=diff ============================================================================== --- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupport.java (original) +++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupport.java Thu Apr 13 14:30:40 2017 @@ -20,11 +20,6 @@ package org.apache.sling.servlets.post.i import java.util.List; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFactory; - import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.PersistenceException; import org.apache.sling.api.resource.Resource; @@ -107,24 +102,89 @@ public class JCRSupport { return false; } - public Value parse(Session session, String value, ValueFactory factory, boolean weak) throws RepositoryException { - return ReferenceParser.parse(session, value, factory, weak); + public boolean isPropertyProtectedOrNewAutoCreated(final Object node, final String name) + throws PersistenceException { + if ( node != null && supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).isPropertyProtectedOrNewAutoCreated(node, name); + } + return false; + } + + public boolean isPropertyMandatory(final Object node, final String name) + throws PersistenceException { + if ( node != null && supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).isPropertyMandatory(node, name); + } + return false; + } + + public boolean isPropertyMultiple(final Object node, final String name) + throws PersistenceException { + if ( node != null && supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).isPropertyMultiple(node, name); + } + return false; + } + + public boolean isNewNode(final Object node) { + if ( node != null && supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).isNewNode(node); + } + return true; + } + + public Integer getPropertyType(final Object node, final String name) + throws PersistenceException { + if ( node != null && supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).getPropertyType(node, name); + } + return null; + } + + public boolean hasSession(final ResourceResolver resolver) { + if ( supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).hasSession(resolver); + } + return false; } /** - * Parses the given source strings and returns the respective reference value - * instances. If no node matches for any of the sources - * returns <code>null</code>. - * <p/> + * Stores property value(s) as reference(s). Will parse the reference(s) from the string + * value(s) in the {@link RequestProperty}. * - * @param values path or UUID strings - * @param factory the value factory - * @param weak true to create a WeakReference value - * @return the values or <code>null</code> - * @throws RepositoryException + * @return true only if parsing was successful and the property was actually changed */ - public Value[] parse(Session session, String[] values, ValueFactory factory, boolean weak) throws RepositoryException { - return ReferenceParser.parse(session, values, factory, weak); + public Modification storeAsReference( + final Resource resource, + final Object node, + final String name, + final String[] values, + final int type, + final boolean multiValued) + throws PersistenceException { + if ( node != null && supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).storeAsReference(node, name, values, type, multiValued); + } + throw new PersistenceException("Resource " + resource.getPath() + " does not support reference properties.", null, resource.getPath(), name); } + public void setTypedProperty(final Object n, + final String name, + final String[] values, + final int type, + final boolean multiValued) + throws PersistenceException { + if ( n != null && supportImpl != null ) { + ((JCRSupportImpl)supportImpl).setTypedProperty(n, name, values, type, multiValued); + } else { + throw new PersistenceException("Property should be stored through JCR but JCR support is not available"); + } + } + + public Object getNode(final Resource rsrc) { + if ( supportImpl != null ) { + return ((JCRSupportImpl)supportImpl).getNode(rsrc); + } + return null; + } } Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupportImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupportImpl.java?rev=1791259&r1=1791258&r2=1791259&view=diff ============================================================================== --- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupportImpl.java (original) +++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JCRSupportImpl.java Thu Apr 13 14:30:40 2017 @@ -23,10 +23,14 @@ import java.util.List; import javax.jcr.ItemNotFoundException; import javax.jcr.Node; import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Session; +import javax.jcr.Value; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.nodetype.PropertyDefinition; import org.apache.jackrabbit.JcrConstants; import org.apache.sling.api.SlingHttpServletRequest; @@ -242,4 +246,152 @@ public class JCRSupportImpl { } return false; } + + private PropertyDefinition searchPropertyDefinition(final NodeType nodeType, final String name) { + if ( nodeType.getPropertyDefinitions() != null ) { + for(final PropertyDefinition pd : nodeType.getPropertyDefinitions()) { + if ( pd.getName().equals(name) ) { + return pd; + } + } + } + // SLING-2877: + // no need to search property definitions of super types, as nodeType.getPropertyDefinitions() + // already includes those. see javadoc of {@link NodeType#getPropertyDefinitions()} + return null; + } + + private PropertyDefinition searchPropertyDefinition(final Node node, final String name) + throws RepositoryException { + PropertyDefinition result = searchPropertyDefinition(node.getPrimaryNodeType(), name); + if ( result == null ) { + if ( node.getMixinNodeTypes() != null ) { + for(final NodeType mt : node.getMixinNodeTypes()) { + result = this.searchPropertyDefinition(mt, name); + if ( result != null ) { + return result; + } + } + } + } + return result; + } + + public boolean isPropertyProtectedOrNewAutoCreated(final Object n, final String name) + throws PersistenceException { + final Node node = (Node)n; + try { + final PropertyDefinition pd = this.searchPropertyDefinition(node, name); + if ( pd != null ) { + // SLING-2877 (autocreated check is only required for new nodes) + if ( (node.isNew() && pd.isAutoCreated()) || pd.isProtected() ) { + return true; + } + } + } catch ( final RepositoryException re) { + throw new PersistenceException(re.getMessage(), re); + } + return false; + } + + public boolean isNewNode(final Object node) { + return ((Node)node).isNew(); + } + + public boolean isPropertyMandatory(final Object node, final String name) + throws PersistenceException { + try { + final Property prop = ((Node)node).getProperty(name); + return prop.getDefinition().isMandatory(); + } catch ( final RepositoryException re) { + throw new PersistenceException(re.getMessage(), re); + } + } + + public boolean isPropertyMultiple(final Object node, final String name) + throws PersistenceException { + try { + final Property prop = ((Node)node).getProperty(name); + return prop.getDefinition().isMultiple(); + } catch ( final RepositoryException re) { + throw new PersistenceException(re.getMessage(), re); + } + } + + public Integer getPropertyType(final Object node, final String name) + throws PersistenceException { + try { + if ( ((Node)node).hasProperty(name) ) { + return ((Node)node).getProperty(name).getType(); + } + } catch ( final RepositoryException re) { + throw new PersistenceException(re.getMessage(), re); + } + return null; + } + + private boolean isWeakReference(int propertyType) { + return propertyType == PropertyType.WEAKREFERENCE; + } + + /** + * Stores property value(s) as reference(s). Will parse the reference(s) from the string + * value(s) in the {@link RequestProperty}. + * + * @return A modification only if parsing was successful and the property was actually changed + */ + public Modification storeAsReference( + final Object n, + final String name, + final String[] values, + final int type, + final boolean multiValued) + throws PersistenceException { + try { + final Node node = (Node)n; + if (multiValued) { + Value[] array = ReferenceParser.parse(node.getSession(), values, isWeakReference(type)); + if (array != null) { + return Modification.onModified( + node.setProperty(name, array).getPath()); + } + } else { + if (values.length >= 1) { + Value v = ReferenceParser.parse(node.getSession(), values[0], isWeakReference(type)); + if (v != null) { + return Modification.onModified( + node.setProperty(name, v).getPath()); + } + } + } + return null; + } catch ( final RepositoryException re) { + throw new PersistenceException(re.getMessage(), re); + } + } + + public boolean hasSession(final ResourceResolver resolver) { + return resolver.adaptTo(Session.class) != null; + } + + public void setTypedProperty(final Object n, + final String name, + final String[] values, + final int type, + final boolean multiValued) + throws PersistenceException { + try { + if (multiValued) { + ((Node)n).setProperty(name, values, type); + } else if (values.length >= 1) { + ((Node)n).setProperty(name, values[0], type); + } + } catch ( final RepositoryException re) { + throw new PersistenceException(re.getMessage(), re); + } + } + + public Object getNode(final Resource rsrc) { + return rsrc.adaptTo(Node.class); + } } Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java?rev=1791259&r1=1791258&r2=1791259&view=diff ============================================================================== --- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java (original) +++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/ReferenceParser.java Thu Apr 13 14:30:40 2017 @@ -24,6 +24,7 @@ import javax.jcr.ValueFactory; /** * Takes a string representation of a node (either a path or a uuid) and tries to parse it. + * ReferenceParser is only used if JCR is available. */ public class ReferenceParser { @@ -33,17 +34,16 @@ public class ReferenceParser { * <p/> * * @param value a path or UUID - * @param factory the value factory * @param weak true to create a WeakReference value * @return the value or <code>null</code> * @throws RepositoryException */ - public static Value parse(Session session, String value, ValueFactory factory, boolean weak) throws RepositoryException { + public static Value parse(Session session, String value, boolean weak) throws RepositoryException { Node n = parse(session, value); if (n == null) { return null; } - return createReferenceValue(n, factory, weak); + return createReferenceValue(n, session.getValueFactory(), weak); } /** @@ -58,14 +58,14 @@ public class ReferenceParser { * @return the values or <code>null</code> * @throws RepositoryException */ - public static Value[] parse(Session session, String[] values, ValueFactory factory, boolean weak) throws RepositoryException { + public static Value[] parse(Session session, String[] values, boolean weak) throws RepositoryException { Value ret[] = new Value[values.length]; for (int i=0; i< values.length; i++) { Node n = parse(session, values[i]); if (n == null) { return null; } - ret[i] = createReferenceValue(n, factory, weak); + ret[i] = createReferenceValue(n, session.getValueFactory(), weak); } return ret; } Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java?rev=1791259&r1=1791258&r2=1791259&view=diff ============================================================================== --- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java (original) +++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java Thu Apr 13 14:30:40 2017 @@ -24,15 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.jcr.Node; -import javax.jcr.Property; import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFactory; -import javax.jcr.nodetype.NodeType; -import javax.jcr.nodetype.PropertyDefinition; import org.apache.jackrabbit.JcrConstants; import org.apache.sling.api.resource.ModifiableValueMap; @@ -42,9 +34,10 @@ import org.apache.sling.servlets.post.Mo import org.apache.sling.servlets.post.SlingPostConstants; /** - * Sets a Property on the given Node, in some cases with a specific type and + * Sets a property on the given resource, in some cases with a specific type and * value. For example, "lastModified" with an empty value is stored as the * current Date. + * Special handling might apply if the resource is backed by a JCR node. */ public class SlingPropertyValueHandler { @@ -95,36 +88,6 @@ public class SlingPropertyValueHandler { return AUTO_PROPS.get(propertyName); } - private PropertyDefinition searchPropertyDefinition(final NodeType nodeType, final String name) { - if ( nodeType.getPropertyDefinitions() != null ) { - for(final PropertyDefinition pd : nodeType.getPropertyDefinitions()) { - if ( pd.getName().equals(name) ) { - return pd; - } - } - } - // SLING-2877: - // no need to search property definitions of super types, as nodeType.getPropertyDefinitions() - // already includes those. see javadoc of {@link NodeType#getPropertyDefinitions()} - return null; - } - - private PropertyDefinition searchPropertyDefinition(final Node node, final String name) - throws RepositoryException { - PropertyDefinition result = searchPropertyDefinition(node.getPrimaryNodeType(), name); - if ( result == null ) { - if ( node.getMixinNodeTypes() != null ) { - for(final NodeType mt : node.getMixinNodeTypes()) { - result = this.searchPropertyDefinition(mt, name); - if ( result != null ) { - return result; - } - } - } - } - return result; - } - /** * Set property on given node, with some automatic values when user provides * the field name but no value. @@ -139,13 +102,13 @@ public class SlingPropertyValueHandler { * * @param parent the parent node * @param prop the request property - * @throws RepositoryException if a repository error occurs + * @throws PersistenceException if a resource error occurs */ public void setProperty(final Resource parent, final RequestProperty prop) - throws RepositoryException, PersistenceException { + throws PersistenceException { final Modifiable mod = new Modifiable(); mod.resource = parent; - mod.node = parent.adaptTo(Node.class); + mod.node = jcrSupport.getNode(parent); mod.valueMap = parent.adaptTo(ModifiableValueMap.class); if ( mod.valueMap == null ) { throw new PersistenceException("Resource at '" + parent.getPath() + "' is not modifiable."); @@ -158,18 +121,12 @@ public class SlingPropertyValueHandler { } else if (AUTO_PROPS.containsKey(name)) { // check if this is a JCR resource and check node type - if ( mod.node != null ) { - final PropertyDefinition pd = this.searchPropertyDefinition(mod.node, name); - if ( pd != null ) { - // SLING-2877 (autocreated check is only required for new nodes) - if ( (mod.node.isNew() && pd.isAutoCreated()) || pd.isProtected() ) { - return; - } - } + if ( this.jcrSupport.isPropertyProtectedOrNewAutoCreated(mod.node, name) ) { + return; } // avoid collision with protected properties - final boolean isNew = (mod.node != null ? mod.node.isNew() : true); + final boolean isNew = jcrSupport.isNewNode(mod.node); switch (getAutoType(name)) { case CREATED: if (isNew) { @@ -196,12 +153,12 @@ public class SlingPropertyValueHandler { /** * Sets the property to the given date - * @param parent parent node + * @param parent parent resource * @param name name of the property - * @throws RepositoryException if a repository error occurs + * @throws PersistenceException if a resource error occurs */ - private void setCurrentDate(Modifiable parent, String name) - throws RepositoryException, PersistenceException { + private void setCurrentDate(final Modifiable parent, final String name) + throws PersistenceException { removePropertyIfExists(parent, name); parent.valueMap.put(name, now); changes.add(Modification.onModified(parent.resource.getPath() + '/' + name)); @@ -209,12 +166,12 @@ public class SlingPropertyValueHandler { /** * set property to the current User id - * @param parent parent node + * @param parent parent resource * @param name name of the property - * @throws RepositoryException if a repository error occurs + * @throws PersistenceException if a resource error occurs */ - private void setCurrentUser(Modifiable parent, String name) - throws RepositoryException, PersistenceException { + private void setCurrentUser(final Modifiable parent, final String name) + throws PersistenceException { removePropertyIfExists(parent, name); final String user = parent.resource.getResourceResolver().getUserID(); parent.valueMap.put(name, user); @@ -222,29 +179,20 @@ public class SlingPropertyValueHandler { } /** - * Removes the property with the given name from the parent node if it + * Removes the property with the given name from the parent resource if it * exists and if it's not a mandatory property. * - * @param parent the parent node + * @param parent the parent resource * @param name the name of the property to remove * @return path of the property that was removed or <code>null</code> if * it was not removed - * @throws RepositoryException if a repository error occurs. + * @throws PersistenceException if a repository error occurs. */ private String removePropertyIfExists(final Modifiable parent, final String name) - throws RepositoryException, PersistenceException { - if (parent.valueMap.containsKey(name) ) { - if ( parent.node != null ) { - final Property prop = parent.node.getProperty(name); - if (!prop.getDefinition().isMandatory()) { - final String path = prop.getPath(); - prop.remove(); - return path; - } - } else { - parent.valueMap.remove(name); - return parent.resource.getPath() + '/' + name; - } + throws PersistenceException { + if (parent.valueMap.containsKey(name) && !jcrSupport.isPropertyMandatory(parent.node, name)) { + parent.valueMap.remove(name); + return parent.resource.getPath() + '/' + name; } return null; } @@ -252,12 +200,12 @@ public class SlingPropertyValueHandler { /** * set property without processing, except for type hints * - * @param parent the parent node + * @param parent the parent resource * @param prop the request property - * @throws RepositoryException if a repository error occurs. + * @throws PersistenceException if a resource error occurs. */ private void setPropertyAsIs(final Modifiable parent, final RequestProperty prop) - throws RepositoryException, PersistenceException { + throws PersistenceException { String[] values = prop.getStringValues(); @@ -287,15 +235,13 @@ public class SlingPropertyValueHandler { removeIfSingleValueProperty(parent, prop); } - Session s = parent.resource.getResourceResolver().adaptTo(Session.class); - if (s != null) { - final ValueFactory valFac = s.getValueFactory(); + if (jcrSupport.hasSession(parent.resource.getResourceResolver())) { if (type == PropertyType.DATE) { - if (storeAsDate(parent, prop.getName(), values, multiValue, valFac)) { + if (storeAsDate(parent, prop.getName(), values, multiValue)) { return; } } else if (isReferencePropertyType(type)) { - if (storeAsReference(parent, prop.getName(), values, type, multiValue, valFac)) { + if (storeAsReference(parent, prop.getName(), values, type, multiValue)) { return; } } @@ -309,7 +255,7 @@ public class SlingPropertyValueHandler { * Patches a multi-value property using add and remove operations per value. */ private String[] patch(final Modifiable parent, String name, String[] values) - throws RepositoryException, PersistenceException { + throws PersistenceException { // we do not use a Set here, as we want to be very restrictive in our // actions and avoid touching elements that are not modified through the // add/remove patch operations; e.g. if the value "foo" occurs twice @@ -318,23 +264,16 @@ public class SlingPropertyValueHandler { List<String> oldValues = new ArrayList<>(); if (parent.valueMap.containsKey(name)) { - if ( parent.node != null ) { - final Property p = parent.node.getProperty(name); + if ( parent.node != null && !jcrSupport.isPropertyMultiple(parent.node, name)) { // can only patch multi-value props - if (!p.getDefinition().isMultiple()) { - return null; - } + return null; + } - for (Value v : p.getValues()) { - oldValues.add(v.getString()); - } - } else { - final String[] setValues = parent.valueMap.get(name, String[].class); - if ( setValues != null ) { - for(final String v : setValues) { - oldValues.add(v); - } + final String[] setValues = parent.valueMap.get(name, String[].class); + if ( setValues != null ) { + for(final String v : setValues) { + oldValues.add(v); } } } @@ -372,16 +311,13 @@ public class SlingPropertyValueHandler { return propertyType == PropertyType.REFERENCE || propertyType == PropertyType.WEAKREFERENCE; } - private boolean isWeakReference(int propertyType) { - return propertyType == PropertyType.WEAKREFERENCE; - } - /** * Returns the property type to use for the given property. This is defined * either by an explicit type hint in the request or simply the type of the * existing property. */ - private int getType(final Modifiable parent, RequestProperty prop) throws RepositoryException { + private int getType(final Modifiable parent, RequestProperty prop) + throws PersistenceException { // no explicit typehint int type = PropertyType.UNDEFINED; if (prop.getTypeHint() != null) { @@ -393,10 +329,9 @@ public class SlingPropertyValueHandler { } String[] values = prop.getStringValues(); if ( type == PropertyType.UNDEFINED && values != null && values.length > 0 ) { - if ( parent.node != null ) { - if ( parent.node.hasProperty(prop.getName()) ) { - type = parent.node.getProperty(prop.getName()).getType(); - } + final Integer jcrType = jcrSupport.getPropertyType(parent.node, prop.getName()); + if ( jcrType != null ) { + type = jcrType; } } return type; @@ -405,7 +340,8 @@ public class SlingPropertyValueHandler { /** * Returns whether the property should be handled as multi-valued. */ - private boolean isMultiValue(final Modifiable parent, RequestProperty prop, String[] values) throws RepositoryException { + private boolean isMultiValue(final Modifiable parent, RequestProperty prop, String[] values) + throws PersistenceException { // multiple values are provided if (values != null && values.length > 1) { return true; @@ -419,12 +355,12 @@ public class SlingPropertyValueHandler { return true; } // nothing in the request, so check the current JCR property definition + final Object value = parent.valueMap.get(prop.getName()); if ( parent.node != null ) { - if (parent.node.hasProperty(prop.getName()) ) { - return parent.node.getProperty(prop.getName()).getDefinition().isMultiple(); + if ( value != null ) { + return jcrSupport.isPropertyMultiple(parent.node, prop.getName()); } } else { - final Object value = parent.valueMap.get(prop.getName()); if ( value != null && value.getClass().isArray() ) { return true; } @@ -437,22 +373,15 @@ public class SlingPropertyValueHandler { * removes multi-value properties. */ private void clearProperty(final Modifiable parent, RequestProperty prop) - throws RepositoryException, PersistenceException { + throws PersistenceException { if (parent.valueMap.containsKey(prop.getName())) { - if ( parent.node != null ) { - if (parent.node.getProperty(prop.getName()).getDefinition().isMultiple()) { - //the existing property is multi-valued, so just delete it? - final String removePath = removePropertyIfExists(parent, prop.getName()); - if ( removePath != null ) { - changes.add(Modification.onDeleted(removePath)); - } - } else { - changes.add(Modification.onModified( - parent.node.setProperty(prop.getName(), "").getPath() - )); + if ( jcrSupport.isPropertyMultiple(parent.node, prop.getName()) ) { + // the existing property is multi-valued, so just delete it? + final String removePath = removePropertyIfExists(parent, prop.getName()); + if ( removePath != null ) { + changes.add(Modification.onDeleted(removePath)); } } else { - parent.valueMap.put(prop.getName(), ""); changes.add(Modification.onModified(parent.resource.getPath() + '/' + prop.getName())); } } @@ -461,8 +390,8 @@ public class SlingPropertyValueHandler { /** * Removes the property if it exists. */ - private void removeProperty(final Modifiable parent, RequestProperty prop) - throws RepositoryException, PersistenceException { + private void removeProperty(final Modifiable parent, final RequestProperty prop) + throws PersistenceException { final String removePath = removePropertyIfExists(parent, prop.getName()); if ( removePath != null ) { changes.add(Modification.onDeleted(removePath)); @@ -474,44 +403,36 @@ public class SlingPropertyValueHandler { */ private void removeIfSingleValueProperty(final Modifiable parent, final RequestProperty prop) - throws RepositoryException, PersistenceException { + throws PersistenceException { if (parent.valueMap.containsKey(prop.getName())) { - if ( parent.node != null ) { - if (!parent.node.getProperty(prop.getName()).getDefinition().isMultiple()) { - // the existing property is single-valued, so we have to delete it before setting the - // multi-value variation - final String removePath = removePropertyIfExists(parent, prop.getName()); - if ( removePath != null ) { - changes.add(Modification.onDeleted(removePath)); - } - } - } else { - final String removePath = removePropertyIfExists(parent, prop.getName()); - if ( removePath != null ) { - changes.add(Modification.onDeleted(removePath)); - } + if ( jcrSupport.isPropertyMultiple(parent.node, prop.getName()) ) { + // do nothing, multi value + return; + } + final String removePath = removePropertyIfExists(parent, prop.getName()); + if ( removePath != null ) { + changes.add(Modification.onDeleted(removePath)); } } } /** - * Parses the given source strings and returns the respective jcr date value + * Parses the given source strings and returns the respective Calendar value * instances. If no format matches for any of the sources * returns <code>null</code>. * <p/> * * @param sources date time source strings - * @param factory the value factory - * @return jcr date value representations of the source or <code>null</code> + * @return Calendar value representations of the source or <code>null</code> */ - private Value[] parse(String sources[], ValueFactory factory) { - Value ret[] = new Value[sources.length]; + private Calendar[] parse(final String sources[]) { + final Calendar ret[] = new Calendar[sources.length]; for (int i=0; i< sources.length; i++) { - Calendar c = dateParser.parse(sources[i]); + final Calendar c = dateParser.parse(sources[i]); if (c == null) { return null; } - ret[i] = factory.createValue(c); + ret[i] = c; } return ret; } @@ -523,22 +444,12 @@ public class SlingPropertyValueHandler { * * @return true only if parsing was successful and the property was actually changed */ - private boolean storeAsDate(final Modifiable parent, String name, String[] values, boolean multiValued, ValueFactory valFac) - throws RepositoryException, PersistenceException { + private boolean storeAsDate(final Modifiable parent, String name, String[] values, boolean multiValued) + throws PersistenceException { if (multiValued) { - final Value[] array = parse(values, valFac); + final Calendar[] array = parse(values); if (array != null) { - if ( parent.node != null ) { - parent.node.setProperty(name, array); - } else { - final Calendar[] dates = new Calendar[array.length]; - int index = 0; - for(final Value v : array) { - dates[index] = v.getDate(); - index++; - } - parent.valueMap.put(name, dates); - } + parent.valueMap.put(name, array); changes.add(Modification.onModified(parent.resource.getPath() + '/' + name)); return true; } @@ -566,32 +477,10 @@ public class SlingPropertyValueHandler { final String name, final String[] values, final int type, - final boolean multiValued, - final ValueFactory valFac) - throws RepositoryException, PersistenceException { - if ( parent.node == null ) { - throw new PersistenceException("Resource " + parent.resource.getPath() + " does not support reference properties."); - } - if (multiValued) { - Value[] array = this.jcrSupport.parse(parent.node.getSession(), values, valFac, isWeakReference(type)); - if (array != null) { - changes.add(Modification.onModified( - parent.node.setProperty(name, array).getPath() - )); - return true; - } - } else { - if (values.length >= 1) { - Value v = this.jcrSupport.parse(parent.node.getSession(), values[0], valFac, isWeakReference(type)); - if (v != null) { - changes.add(Modification.onModified( - parent.node.setProperty(name, v).getPath() - )); - return true; - } - } - } - return false; + final boolean multiValued) + throws PersistenceException { + final Modification mod = this.jcrSupport.storeAsReference(parent.resource, parent.node, name, values, type, multiValued); + return mod != null; } /** @@ -603,36 +492,18 @@ public class SlingPropertyValueHandler { final String[] values, final int type, final boolean multiValued) - throws RepositoryException, PersistenceException { - if ( parent.node != null ) { - Property p = null; + throws PersistenceException { + if ( parent.node != null && type != PropertyType.UNDEFINED ) { + jcrSupport.setTypedProperty(parent.node, name, values, type, multiValued); - if (multiValued) { - if (type == PropertyType.UNDEFINED) { - p = parent.node.setProperty(name, values); - } else { - p = parent.node.setProperty(name, values, type); - } - } else if (values.length >= 1) { - if (type == PropertyType.UNDEFINED) { - p = parent.node.setProperty(name, values[0]); - } else { - p = parent.node.setProperty(name, values[0], type); - } - } - - if (p != null) { - changes.add(Modification.onModified(p.getPath())); - } } else { if (multiValued) { parent.valueMap.put(name, toJavaObject(values, type)); - changes.add(Modification.onModified(parent.resource.getPath() + '/' + name)); } else if (values.length >= 1) { parent.valueMap.put(name, toJavaObject(values[0], type)); - changes.add(Modification.onModified(parent.resource.getPath() + '/' + name)); } } + changes.add(Modification.onModified(parent.resource.getPath() + '/' + name)); } /** Converts a value */ @@ -677,6 +548,6 @@ public class SlingPropertyValueHandler { public final static class Modifiable { public Resource resource; public ModifiableValueMap valueMap; - public Node node; + public Object node; } }