Skip to content

Commit

Permalink
Added ODM Metadata Inheritance fixes spring-projects#340
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob4001 committed Nov 25, 2021
1 parent 9516edd commit b009d28
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import javax.naming.Name;
Expand Down Expand Up @@ -85,29 +87,33 @@ public AttributeMetaData getAttribute(Field field) {
return fieldToAttribute.get(field);
}

public ObjectMetaData(Class<?> clazz) {
public ObjectMetaData(final Class<?> clazz) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Extracting metadata from %1$s", clazz));
}

// Get object class metadata - the @Entity annotation
Entry entity = clazz.getAnnotation(Entry.class);
if (entity != null) {
// findAllMergedAnnotations will return set of inherited annotations and apply them from superclass down to subclass
Set<Entry> entities = AnnotatedElementUtils.findAllMergedAnnotations(clazz,Entry.class);
if (entities != null && !entities.isEmpty()) {
// Default objectclass name to the class name unless it's specified
// in @Entity(name={objectclass1, objectclass2});
String[] localObjectClasses = entity.objectClasses();
if (localObjectClasses != null && localObjectClasses.length > 0 && localObjectClasses[0].length() > 0) {
for (String localObjectClass:localObjectClasses) {
objectClasses.add(new CaseIgnoreString(localObjectClass));
for (Entry entity: entities) {
String[] localObjectClasses = entity.objectClasses();
if (localObjectClasses.length > 0 && localObjectClasses[0].length() > 0) {
for (String localObjectClass : localObjectClasses) {
objectClasses.add(new CaseIgnoreString(localObjectClass));
}
}
} else {
String base = entity.base();
if (StringUtils.hasText(base)) {
this.base = LdapUtils.newLdapName(base);
}
}
if(objectClasses.isEmpty()) {
objectClasses.add(new CaseIgnoreString(clazz.getSimpleName()));
}

String base = entity.base();
if(StringUtils.hasText(base)) {
this.base = LdapUtils.newLdapName(base);
}
} else {
throw new MetaDataException(String.format("Class %1$s must have a class level %2$s annotation", clazz,
Entry.class));
Expand All @@ -119,31 +125,34 @@ public ObjectMetaData(Class<?> clazz) {
}

// Get field meta-data - the @Attribute annotation
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// So we can write to private fields
field.setAccessible(true);

// Skip synthetic or static fields
if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
continue;
}

AttributeMetaData currentAttributeMetaData=new AttributeMetaData(field);
if (currentAttributeMetaData.isId()) {
if (idAttribute!=null) {
// There can be only one id field
throw new MetaDataException(
String.format("You man have only one field with the %1$s annotation in class %2$s", Id.class, clazz));
ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException {
// So we can write to private fields
field.setAccessible(true);

// Skip synthetic or static fields
if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
return;
}

AttributeMetaData currentAttributeMetaData=new AttributeMetaData(field);
if (currentAttributeMetaData.isId()) {
if (idAttribute!=null) {
// There can be only one id field
throw new MetaDataException(
String.format("You man have only one field with the %1$s annotation in class %2$s", Id.class, clazz));
}
idAttribute=currentAttributeMetaData;
}
fieldToAttribute.put(field, currentAttributeMetaData);

if(currentAttributeMetaData.isDnAttribute()) {
dnAttributes.add(currentAttributeMetaData);
}
}
idAttribute=currentAttributeMetaData;
}
fieldToAttribute.put(field, currentAttributeMetaData);

if(currentAttributeMetaData.isDnAttribute()) {
dnAttributes.add(currentAttributeMetaData);
}
}
);

if (idAttribute == null) {
throw new MetaDataException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,42 @@ public void testMapping() {
assertField(entityData, "entryUUID", "entryUUID", null, false, false, false, true);
}

@Test
public void testMappingInherited() {
assertThat(tested.manageClass(UnitTestWorker.class))
.containsOnlyElementsOf(Arrays.asList("dn", "cn", "sn", "description", "telephoneNumber", "entryUUID", "objectclass", "workerId"));

DefaultObjectDirectoryMapper.EntityData entityData = tested.getMetaDataMap().get(UnitTestWorker.class);

assertThat(entityData).isNotNull();
assertThat(entityData.ocFilter).isEqualTo(query().
where("objectclass").is("inetOrgPerson")
.and("objectclass").is("organizationalPerson")
.and("objectclass").is("person")
.and("objectclass").is("top")
.and("objectclass").is("worker")
.filter());

assertThat(entityData.metaData).hasSize(9);

AttributeMetaData idAttribute = entityData.metaData.getIdAttribute();
assertThat(idAttribute.getField().getName()).isEqualTo("dn");
assertThat(idAttribute.isId()).isTrue();
assertThat(idAttribute.isBinary()).isFalse();
assertThat(idAttribute.isDnAttribute()).isFalse();
assertThat(idAttribute.isTransient()).isFalse();
assertThat(idAttribute.isCollection()).isFalse();

assertField(entityData, "fullName", "cn", "cn", false, false, false, false);
assertField(entityData, "lastName", "sn", null, false, false, false, false);
assertField(entityData, "description", "description", null, false, false, true, false);
assertField(entityData, "country", null, "c", false, true, false, false);
assertField(entityData, "company", null, "ou", false, true, false, false);
assertField(entityData, "telephoneNumber", "telephoneNumber", null, false, false, false, false);
assertField(entityData, "entryUUID", "entryUUID", null, false, false, false, true);
assertField(entityData, "workerId", "workerId", null, false, false, false, false);
}

@Test
public void testInvalidType() {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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
*
* https://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.core.impl;

import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;

/**
* @author Robert Wilson
*/
@Entry(objectClasses = {"worker"})
public class UnitTestWorker extends UnitTestPerson{
@Attribute(name = "workerId")
private String workerId;
}

0 comments on commit b009d28

Please sign in to comment.