/* * Chrysalix * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * See the AUTHORS.txt file in the distribution for a full listing of * individual contributors. * * Chrysalix is free software. Unless otherwise indicated, all code in Chrysalix * is licensed to you under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Chrysalix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.modelspace.internal; import java.math.BigDecimal; import java.util.Calendar; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.Session; import javax.jcr.Value; import org.modelspace.Model; import org.modelspace.ModelObject; import org.modelspace.ModelProperty; import org.modelspace.ModelspaceException; import org.modelspace.ModelspaceI18n; import org.modelspace.ModelspaceLexicon; import org.modelspace.PropertyDescriptor; import org.modelspace.internal.task.TaskWithResult; import org.modelspace.internal.task.WriteTask; import org.modeshape.common.util.CheckArg; /** * The base class for a {@link ModelProperty model property}. */ public class ModelPropertyImpl implements ModelProperty { private static final String UNABLE_TO_CONSTRUCT_PROPERTY = "Unable to construct model property for parent '%s'"; final ModelObjectImpl parent; final String path; /** * @param parent * the property's parent (cannot be <code>null</code>) * @param jcrProperty * the JCR property (cannot be <code>null</code>) * @throws ModelspaceException * if there is an error constructing the property */ ModelPropertyImpl( final ModelObjectImpl parent, final Property jcrProperty ) throws ModelspaceException { CheckArg.isNotNull( parent, "parent" ); CheckArg.isNotNull( jcrProperty, "jcrProperty" ); this.parent = parent; try { this.path = jcrProperty.getPath(); } catch ( final Exception e ) { throw new ModelspaceException( e, ModelspaceI18n.localize( UNABLE_TO_CONSTRUCT_PROPERTY, this.parent.name() ) ); } } /** * {@inheritDoc} * * @see org.modelspace.ModelElement#absolutePath() */ @Override public String absolutePath() { return this.path; } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#booleanValue() */ @Override public boolean booleanValue() throws ModelspaceException { return modelspace().run( new TaskWithResult< Boolean >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public Boolean run( final Session session ) throws Exception { return session.getProperty( path ).getBoolean(); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#booleanValues() */ @Override public boolean[] booleanValues() throws ModelspaceException { return modelspace().run( new TaskWithResult< boolean[] >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public boolean[] run( final Session session ) throws Exception { final Property property = session.getProperty( path ); if ( property.isMultiple() ) { final Value[] values = property.getValues(); final boolean[] booleanValues = new boolean[ values.length ]; int i = 0; for ( final Value value : values ) { booleanValues[ i++ ] = value.getBoolean(); } return booleanValues; } return new boolean[] { property.getBoolean() }; } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#dateValue() */ @Override public Calendar dateValue() throws ModelspaceException { return modelspace().run( new TaskWithResult< Calendar >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public Calendar run( final Session session ) throws Exception { return session.getProperty( path ).getDate(); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#dateValues() */ @Override public Calendar[] dateValues() throws ModelspaceException { return modelspace().run( new TaskWithResult< Calendar[] >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public Calendar[] run( final Session session ) throws Exception { final Property property = session.getProperty( path ); if ( property.isMultiple() ) { final Value[] values = property.getValues(); final Calendar[] dateValues = new Calendar[ values.length ]; int i = 0; for ( final Value value : values ) { dateValues[ i++ ] = value.getDate(); } return dateValues; } return new Calendar[] { property.getDate() }; } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#decimalValue() */ @Override public BigDecimal decimalValue() throws ModelspaceException { return modelspace().run( new TaskWithResult< BigDecimal >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public BigDecimal run( final Session session ) throws Exception { return session.getProperty( path ).getDecimal(); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#decimalValues() */ @Override public BigDecimal[] decimalValues() throws ModelspaceException { return modelspace().run( new TaskWithResult< BigDecimal[] >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public BigDecimal[] run( final Session session ) throws Exception { final Property property = session.getProperty( path ); if ( property.isMultiple() ) { final Value[] values = property.getValues(); final BigDecimal[] decimalValues = new BigDecimal[ values.length ]; int i = 0; for ( final Value value : values ) { decimalValues[ i++ ] = value.getDecimal(); } return decimalValues; } return new BigDecimal[] { property.getDecimal() }; } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#descriptor() */ @Override public PropertyDescriptor descriptor() throws ModelspaceException { return modelspace().run( new TaskWithResult< PropertyDescriptor >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public PropertyDescriptor run( final Session session ) throws Exception { final Property property = session.getProperty( path ); return new PropertyDescriptorImpl( property.getDefinition() ); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#doubleValue() */ @Override public double doubleValue() throws ModelspaceException { return modelspace().run( new TaskWithResult< Double >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public Double run( final Session session ) throws Exception { return session.getProperty( path ).getDouble(); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#doubleValues() */ @Override public double[] doubleValues() throws ModelspaceException { return modelspace().run( new TaskWithResult< double[] >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public double[] run( final Session session ) throws Exception { final Property property = session.getProperty( path ); if ( property.isMultiple() ) { final Value[] values = property.getValues(); final double[] doubleValues = new double[ values.length ]; int i = 0; for ( final Value value : values ) { doubleValues[ i++ ] = value.getDouble(); } return doubleValues; } return new double[] { property.getDouble() }; } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#longValue() */ @Override public long longValue() throws ModelspaceException { return modelspace().run( new TaskWithResult< Long >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public Long run( final Session session ) throws Exception { return session.getProperty( path ).getLong(); } } ); } /** * @see org.modelspace.ModelProperty#longValues() */ @Override public long[] longValues() throws ModelspaceException { return modelspace().run( new TaskWithResult< long[] >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public long[] run( final Session session ) throws Exception { final Property property = session.getProperty( path ); if ( property.isMultiple() ) { final Value[] values = property.getValues(); final long[] longValues = new long[ values.length ]; int i = 0; for ( final Value value : values ) { longValues[ i++ ] = value.getLong(); } return longValues; } return new long[] { property.getLong() }; } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelElement#model() */ @Override public Model model() throws ModelspaceException { return modelspace().model( this.path ); } Node modelNode( final Session session ) throws Exception { Node node = session.getNode( path ); while ( !node.isNodeType( ModelspaceLexicon.Model.MODEL_MIXIN ) ) { node = node.getParent(); } return node; } /** * {@inheritDoc} * * @see org.modelspace.ModelElement#modelRelativePath() */ @Override public String modelRelativePath() throws ModelspaceException { return modelspace().run( new TaskWithResult< String >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public String run( final Session session ) throws Exception { return path.substring( modelNode( session ).getPath().length() + 1 ); } } ); } ModelspaceImpl modelspace() { return this.parent.modelspace; } /** * {@inheritDoc} * * @see org.modelspace.ModelElement#name() */ @Override public String name() throws ModelspaceException { return modelspace().run( new TaskWithResult< String >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public String run( final Session session ) throws Exception { return session.getNode( path ).getName(); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#parent() */ @Override public ModelObject parent() throws ModelspaceException { return modelspace().run( new TaskWithResult< ModelObject >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public ModelObject run( final Session session ) throws Exception { final Node node = session.getProperty( path ).getParent(); return new ModelObjectImpl( modelspace(), node.getPath(), node.getIndex() ); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#set(java.lang.Object[]) */ @Override public void set( final Object... values ) throws ModelspaceException { modelspace().run( new WriteTask() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.WriteTask#run(javax.jcr.Session) */ @Override public void run( final Session session ) throws Exception { final Property property = session.getProperty( path ); if ( values == null ) { property.remove(); } else { final int count = values.length; final boolean multiple = property.isMultiple(); final int type = property.getType(); if ( count == 0 ) { // remove if property is multi-valued if ( multiple ) { property.remove(); } else { // single-valued property throw new ModelspaceException( ModelspaceI18n.localize( ModelObjectImpl.UNABLE_TO_REMOVE_SINGLE_VALUE_PROPERTY_WITH_EMPTY_ARRAY, path, parent.name() ) ); } } else if ( count > 1 ) { if ( multiple ) { property.setValue( Util.createValues( session.getValueFactory(), values, type ) ); } else { throw new ModelspaceException( ModelspaceI18n.localize( ModelObjectImpl.UNABLE_TO_SET_SINGLE_VALUE_PROPERTY_WITH_MULTIPLE_VALUES, property.getName(), parent.name() ) ); } } else { // only one value so set property if ( multiple ) { property.setValue( Util.createValues( session.getValueFactory(), values, type ) ); } else { property.setValue( Util.createValue( session.getValueFactory(), values[ 0 ] ) ); } } } } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#stringValue() */ @Override public String stringValue() throws ModelspaceException { return modelspace().run( new TaskWithResult< String >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public String run( final Session session ) throws Exception { return session.getProperty( path ).getString(); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#stringValues() */ @Override public String[] stringValues() throws ModelspaceException { return modelspace().run( new TaskWithResult< String[] >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public String[] run( final Session session ) throws Exception { final Property property = session.getProperty( path ); if ( property.isMultiple() ) { final Value[] values = property.getValues(); final String[] stringValues = new String[ values.length ]; int i = 0; for ( final Value value : values ) { stringValues[ i++ ] = value.getString(); } return stringValues; } return new String[] { property.getString() }; } } ); } /** * {@inheritDoc} * * @see java.lang.Object#toString() */ @Override public String toString() { return this.path; } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#value() */ @Override public Object value() throws ModelspaceException { return modelspace().run( new TaskWithResult< Object >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public Object run( final Session session ) throws Exception { final Property property = session.getProperty( path ); final Value value = property.getValue(); final int propType = property.getType(); return Util.convert( value, propType ); } } ); } /** * {@inheritDoc} * * @see org.modelspace.ModelProperty#values() */ @Override public Object[] values() throws ModelspaceException { return modelspace().run( new TaskWithResult< Object[] >() { /** * {@inheritDoc} * * @see org.modelspace.internal.task.TaskWithResult#run(javax.jcr.Session) */ @Override public Object[] run( final Session session ) throws Exception { final Property property = session.getProperty( path ); final int propType = property.getType(); if ( property.isMultiple() ) { final Value[] values = property.getValues(); final Object[] objectValues = new Object[ values.length ]; int i = 0; for ( final Value value : values ) { objectValues[ i++ ] = Util.convert( value, propType ); } return objectValues; } return new Object[] { Util.convert( property.getValue(), propType ) }; } } ); } }