From 9a8dadcdbe3db02783f0dc4d5f723971b19c1712 Mon Sep 17 00:00:00 2001 From: Mattias Hellborg Arthursson Date: Sun, 29 Sep 2013 16:51:51 +0200 Subject: [PATCH] LDAP-268: Reference documentation of the new @DnAttribute annotation. Some javadoc polishing. --- .../ldap/core/LdapOperations.java | 21 ++++++-- .../ldap/core/LdapTemplate.java | 10 +++- .../ldap/odm/annotations/DnAttribute.java | 35 ++++++++++++ src/docbkx/odm.xml | 53 +++++++++++++++---- 4 files changed, 105 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/springframework/ldap/core/LdapOperations.java b/core/src/main/java/org/springframework/ldap/core/LdapOperations.java index 4277e1eb..a1f0a2ea 100644 --- a/core/src/main/java/org/springframework/ldap/core/LdapOperations.java +++ b/core/src/main/java/org/springframework/ldap/core/LdapOperations.java @@ -1692,31 +1692,46 @@ public interface LdapOperations { T findByDn(Name dn, Class clazz); /** - * Create the given entry in the LDAP directory. + * Create the given entry in the LDAP directory. If the field annotated with {@link org.springframework.ldap.odm.annotations.Id} + * is set in the object, this will be used as the distinguished name of the new entry. If no explicit DN is specified, + * an attempt will be made to calculate the name from fields annotated with {@link org.springframework.ldap.odm.annotations.DnAttribute}. * * @param entry The entry to be create, it must not already exist in the directory. * * @throws org.springframework.ldap.NamingException on error. + * @throws IllegalArgumentException if the entry is null or on failure to determine the distinguished name. * @since 2.0 */ void create(Object entry); /** - * Update the given entry in the LDAP directory. + * Update the given entry in the LDAP directory. If the distinguished name is not explicitly specified (i.e. if the + * field annotated with {@link org.springframework.ldap.odm.annotations.Id} is null), + * an attempt will be made to calculate the name from fields annotated with + * {@link org.springframework.ldap.odm.annotations.DnAttribute}. If the {@link org.springframework.ldap.odm.annotations.Id} + * field and the calculated DN is different, the entry will be moved (i.e., an {@link #unbind(javax.naming.Name)} + * followed by a {@link #bind(DirContextOperations)}. Otherwise + * the current data of the entry will be read from the directory and a {@link #modifyAttributes(DirContextOperations)} + * operation will be performed using the ModificationItems resulting from the changes of the + * entry compared to its current state in the directory. * * @param entry The entry to update, it must already exist in the directory. * * @throws org.springframework.ldap.NamingException on error. + * @throws IllegalArgumentException if the entry is null or on failure to determine the distinguished name. * @since 2.0 */ void update(Object entry); /** - * Delete an entry from the LDAP directory. + * Delete an entry from the LDAP directory. If the field annotated with {@link org.springframework.ldap.odm.annotations.Id} + * is set in the object, this will be used as the distinguished name of the new entry. If no explicit DN is specified, + * an attempt will be made to calculate the name from fields annotated with {@link org.springframework.ldap.odm.annotations.DnAttribute}. * * @param entry The entry to delete, it must already exist in the directory. * * @throws org.springframework.ldap.NamingException on error. + * @throws IllegalArgumentException if the entry is null or on failure to determine the distinguished name. * @since 2.0 */ void delete(Object entry); diff --git a/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java b/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java index 68e642a0..3a1bea93 100644 --- a/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java +++ b/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java @@ -1819,12 +1819,18 @@ public class LdapTemplate implements LdapOperations, InitializingBean { @Override public void delete(Object entry) { + Assert.notNull(entry, "Entry must not be null"); if (log.isDebugEnabled()) { log.debug(String.format("Deleting %s$1", entry)); } - // Just to check that this is a managed class - unbind(odm.getId(entry)); + Name id = odm.getId(entry); + if(id == null) { + id = odm.getCalculatedId(entry); + } + + Assert.notNull(id, String.format("Unable to determine id for entry %s", entry.toString())); + unbind(id); } @Override diff --git a/core/src/main/java/org/springframework/ldap/odm/annotations/DnAttribute.java b/core/src/main/java/org/springframework/ldap/odm/annotations/DnAttribute.java index 1167f49e..def495ab 100644 --- a/core/src/main/java/org/springframework/ldap/odm/annotations/DnAttribute.java +++ b/core/src/main/java/org/springframework/ldap/odm/annotations/DnAttribute.java @@ -1,3 +1,19 @@ +/* + * Copyright 2005-2013 the original author or authors. + * + * Licensed 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.springframework.ldap.odm.annotations; import java.lang.annotation.ElementType; @@ -6,11 +22,30 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** + * Indicates that a field is to be automatically populated to/from the distinguished name + * of an entry. Fields annotated with this annotation will be automatically populated with values from + * the distinguished names of found entries. + *

+ * For automatic calculation of the DN of an entry to work, the {@link #index()} value + * must be specified on all DnAttribute annotations in that class, and these attribute values, + * prepended with the {@link org.springframework.ldap.odm.annotations.Entry#base()} value will be used + * to figure out the distinguished name of entries to create and update. + *

* @author Mattias Hellborg Arthursson + * @since 2.0 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DnAttribute { + /** + * The name of the distinguished name attribute. + * @return the attribute name. + */ String value(); + + /** + * The index of this attribute in the calculated distinguished name of an entry. + * @return the 0-based index of this attribute. + */ int index() default -1; } diff --git a/src/docbkx/odm.xml b/src/docbkx/odm.xml index 14cea152..b12665b9 100644 --- a/src/docbkx/odm.xml +++ b/src/docbkx/odm.xml @@ -54,7 +54,12 @@ attribute to the object class field. - + + @DnAttribute - Indicates the mapping of a dn + attribute to the object class field. + + + @Transient - Indicates the field is not persistent and should be ignored by the OdmManager. @@ -88,9 +93,23 @@ which allows you to indicate whether the attribute is regarded as binary based or string based by the LDAP JNDI provider. + + The @DnAttribute annotation is used to map object class fields + to and from components in the distinguished name of an entry. Fields annotated with + @DnAttribute + will automatically be populated with the appropriate value from the distinguished name + when an entry is read from the directory tree. If the index attribute + of all @DnAttribute annotations in a class is specified, the DN + will also be calculated when creating and updating entries. For update scenarios, + this will also automatically take care of moving entries in the tree if attributes + that are part of the distinguished name have changed. + + The @Transient annotation is used to indicate the field should be ignored by the object directory mapping and not mapped to - an underlying LDAP property. + an underlying LDAP property. Note that if a @DnAttribute is not to be bound + to an Attribute, i.e. it is only part of the Distinguished Name and not represented by an object attibute, + it must also be annotated with @Transient. @@ -227,31 +246,47 @@ Execution +@Entry(objectClasses = { "person", "top" }, base="ou=someOu") +public class Person { + @Id + private Name dn; + + @Attribute(name="cn") + @DnAttribute(value="cn", index=1) + private String fullName; + + // No @Attribute annotation means this will be bound to the LDAP attribute + // with the same value + private String description; + + @DnAttribute(value="ou", index=0) + @Transient + private String company; + + @Transient + private String someUnmappedField; + // ...more attributes below +} + + public class OdmPersonDao { @Autowired private LdapTemplate ldapTemplate; public Person create(Person person) { - person.setDn(buildDn(person)); ldapTemplate.create(person); return person; } - private Name buildDn(Person person) { - // build a distinguished name based on a person. - } - public Person findByUid(String uid) { return ldapTemplate.findOne(query().where("uid").is(uid), Person.class); } public void update(Person person) { - // Requires that the Person was originally retrieved from this Dao, i.e. that the Dn is populated. ldapTemplate.update(person); } public void delete(Person person) { - // Requires that the Person was originally retrieved from this Dao, i.e. that the Dn is populated. ldapTemplate.delete(person); }