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
>>
>