Hi Christophe,

As you said is was possible to create a collection converter to do
this. See code below.

I suppose that it could be taken a step further using the collection
annotation properties autoRetrieve, autoUpdate, autoInsert properties
and the ObjectConverter to insert and update collection elements when
the parent is saved.

public class BeanReferenceByPathCollectionConverterImpl extends
AbstractCollectionConverterImpl {

        public BeanReferenceByPathCollectionConverterImpl(Map
atomicTypeConverters, ObjectConverter objectConverter, Mapper mapper)
{
                super(atomicTypeConverters, objectConverter, mapper);
        }

        protected ManageableObjects doGetCollection(Session session, Node
parentNode, CollectionDescriptor collectionDescriptor, Class
collectionFieldClass) throws RepositoryException {
                try {
            String jcrName = getCollectionJcrName(collectionDescriptor);
            if (!parentNode.hasProperty(jcrName)) {
                return null;
            }
            Property property = parentNode.getProperty(jcrName);
            Value[] values = property.getValues();

            ManageableObjects objects =
ManageableObjectsUtil.getManageableObjects(collectionFieldClass);

            // For collection of bean references, only Collections are supported
            if (! (objects instanceof ManageableCollection))
            {

                throw new JcrMappingException("Impossible to retrieve the
attribute "
                                + collectionDescriptor.getFieldName() + " in 
the class "
                                + 
collectionDescriptor.getClassDescriptor().getClassName()
                                +  " because it is not a collection");
            }

            for (int i = 0; i < values.length; i++) {
                String path = values[i].getString();
                Object object = objectConverter.getObject(session, path);
                ((ManageableCollection) objects).addObject(object);
            }

            return objects;
        }
        catch(Exception e) {
          throw new ObjectContentManagerException("Cannot get the
collection field : "
                  + collectionDescriptor.getFieldName()
                  + "for class " +
collectionDescriptor.getClassDescriptor().getClassName(), e);
        }
        }

        protected void doInsertCollection(Session session, Node parentNode,
CollectionDescriptor descriptor, ManageableObjects objects) throws
RepositoryException {
                addPathProperties(session, parentNode, descriptor, objects);
        }

        protected boolean doIsNull(Session session, Node parentNode,
CollectionDescriptor collectionDescriptor, Class collectionFieldClass)
throws RepositoryException {
                String jcrName = getCollectionJcrName(collectionDescriptor);
        return ! parentNode.hasProperty(jcrName);
        }

        protected void doUpdateCollection(Session session, Node parentNode,
CollectionDescriptor descriptor, ManageableObjects objects) throws
RepositoryException {
                String jcrName = getCollectionJcrName(descriptor);

        // Delete existing values
        if (parentNode.hasProperty(jcrName)) {
            parentNode.setProperty(jcrName, (Value[]) null);
        }

        if (objects == null) {
            return;
        }


        addPathProperties(session, parentNode, descriptor, objects);
        }

        private void addPathProperties(Session session, Node parentNode,
CollectionDescriptor collectionDescriptor, ManageableObjects objects)
throws RepositoryException {
                try {
            if (objects == null) {
                return;
            }

            String jcrName = getCollectionJcrName(collectionDescriptor);
            Value[] values = new Value[objects.getSize()];
            ValueFactory valueFactory = session.getValueFactory();
            Iterator collectionIterator = objects.getIterator();
            for (int i = 0; i < objects.getSize(); i++) {
                Object object = collectionIterator.next();
                                if (object != null)
                                {
                                        ClassDescriptor classDescriptor =
mapper.getClassDescriptorByClass(object.getClass());

                                        FieldDescriptor fieldDescriptor = 
classDescriptor.getPathFieldDescriptor();
                                        if (fieldDescriptor == null)
                                        {
                                                throw new 
JcrMappingException("The bean doesn't have an path -
classdescriptor : "
                                                                                
              + classDescriptor.getClassName());
                                        }

                                        String path = (String) 
ReflectionUtils.getNestedProperty(object,
fieldDescriptor.getFieldName());
                                        values[i] = 
valueFactory.createValue(path, PropertyType.STRING);
                                }
            }

            parentNode.setProperty(jcrName, values);
        }
        catch(Exception e) {
            throw new ObjectContentManagerException("Cannot insert
collection field : "
                    + collectionDescriptor.getFieldName()
                    + " of class "
                    +
collectionDescriptor.getClassDescriptor().getClassName(), e);
        }
        }
}

2009/10/26 Christophe Lombart <[email protected]>:
> It is supported but only by UUID.
> By path is also a good idea. It should be possible to add a new  OCM
> Collection converter for supporting reference by path .
>
> Christophe
>
>
> 2009/10/23 Ben Short <[email protected]>:
>> Hi,
>>
>> JCROM supports weak references as show in the following classes
>>
>> public class Person {
>>
>>       �...@jcrpath
>>        private String path;
>>       �...@jcrname
>>        private String name;
>>
>>       �...@jcrreference(byPath = true)
>>        private List<Pet> pets= new ArrayList<Pet>();
>>
>> }
>>
>> public class Pet {
>>
>>       �...@jcrpath
>>        private String path;
>>       �...@jcrname
>>        private String name;
>>
>> }
>>
>> This will result in a property on person node which contains a list of
>> paths to the pet nodes.
>>
>> Does jackrabbit-ocm support this?
>>
>> Regards
>>
>> Ben Short
>>
>
  • OCM Ben Short
    • Re: OCM Christophe Lombart
      • Re: OCM Ben Short
    • OCM Ben Short

Reply via email to