Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 23992 invoked from network); 25 Jul 2007 02:45:46 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 25 Jul 2007 02:45:46 -0000 Received: (qmail 67072 invoked by uid 500); 25 Jul 2007 02:45:47 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 67038 invoked by uid 500); 25 Jul 2007 02:45:47 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 67027 invoked by uid 99); 25 Jul 2007 02:45:47 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Jul 2007 19:45:47 -0700 X-ASF-Spam-Status: No, hits=-98.6 required=10.0 tests=ALL_TRUSTED,INFO_TLD,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Jul 2007 19:45:44 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 6F3101A981C; Tue, 24 Jul 2007 19:45:24 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r559292 - in /directory/sandbox/akarasulu/j2l/trunk/runtime/src: main/java/org/apache/directory/j2l/configuration/ main/java/org/apache/directory/j2l/descriptions/ main/resources/ test/java/org/apache/directory/j2l/annotations/ test/java/or... Date: Wed, 25 Jul 2007 02:45:24 -0000 To: commits@directory.apache.org From: akarasulu@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070725024524.6F3101A981C@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: akarasulu Date: Tue Jul 24 19:45:22 2007 New Revision: 559292 URL: http://svn.apache.org/viewvc?view=rev&rev=559292 Log: added more code and finally got the extractor working properly but this stuff is pretty much junk and needs better organization Added: directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/resources/log4j.properties directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBeanNoAnnotations.java - copied, changed from r558576, directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBean.java directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/descriptions/ directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractorTest.java (with props) directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/resources/ directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/resources/log4j.properties Removed: directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBean.java Modified: directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/J2LConfiguration.java directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/PrimitiveMappingRegistry.java directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeToPropertyMapping.java directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractor.java directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/AnnotationTest.java Modified: directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/J2LConfiguration.java URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/J2LConfiguration.java?view=diff&rev=559292&r1=559291&r2=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/J2LConfiguration.java (original) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/J2LConfiguration.java Tue Jul 24 19:45:22 2007 @@ -19,6 +19,9 @@ */ package org.apache.directory.j2l.configuration; +import java.util.Set; +import java.util.HashSet; + /** * Document me! * @@ -43,12 +46,17 @@ /** * Configuration information about the schema to generate. */ - private SchemaConfiguration schemaConfiguration; + private SchemaConfiguration schemaConfiguration = new SchemaConfiguration(); /** * Used to lookup default syntax and matchingRule mappings for Java primitive types. */ - private PrimitiveMappingRegistry primitiveMappingRegistry; + private PrimitiveMappingRegistry primitiveMappingRegistry = new PrimitiveMappingRegistry(); + + /** + * A set of bean property names to ignore. + */ + private Set ignoredProperties = new HashSet(); /** * If true will generate an OpenLDAP compatible schema file using the @@ -93,6 +101,18 @@ */ private boolean generateModifierObjects = false; + + public J2LConfiguration() + { + ignoredProperties.add( "class" ); + } + + + public boolean isPropertyIgnored( String propertyName ) + { + return ignoredProperties.contains( propertyName ); + } + public String getTargetPackage() { @@ -221,5 +241,15 @@ public void setPrimitiveMappingRegistry( PrimitiveMappingRegistry primitiveMappingRegistry ) { this.primitiveMappingRegistry = primitiveMappingRegistry; + } + + public Set getIgnoredProperties() + { + return ignoredProperties; + } + + public void setIgnoredProperties( Set ignoredProperties ) + { + this.ignoredProperties = ignoredProperties; } } Modified: directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/PrimitiveMappingRegistry.java URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/PrimitiveMappingRegistry.java?view=diff&rev=559292&r1=559291&r2=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/PrimitiveMappingRegistry.java (original) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/configuration/PrimitiveMappingRegistry.java Tue Jul 24 19:45:22 2007 @@ -21,6 +21,8 @@ import org.apache.directory.shared.ldap.constants.SchemaConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Map; import java.util.HashMap; @@ -106,6 +108,7 @@ private Map class2syntax = new HashMap(); + private Logger log = LoggerFactory.getLogger( PrimitiveMappingRegistry.class ); public PrimitiveMappingRegistry( PrimitiveMapping[] overrides ) @@ -123,12 +126,17 @@ { class2syntax.put( STRING_MAPPING.getJavaType(), STRING_MAPPING ); class2syntax.put( INT_MAPPING.getJavaType(), INT_MAPPING ); + class2syntax.put( int.class, INT_MAPPING ); class2syntax.put( BYTE_MAPPING.getJavaType(), BYTE_MAPPING ); + class2syntax.put( byte.class, BYTE_MAPPING ); class2syntax.put( LONG_MAPPING.getJavaType(), LONG_MAPPING ); + class2syntax.put( long.class, LONG_MAPPING ); class2syntax.put( SHORT_MAPPING.getJavaType(), SHORT_MAPPING ); + class2syntax.put( short.class, SHORT_MAPPING ); class2syntax.put( BIG_INT_MAPPING.getJavaType(), BIG_INT_MAPPING ); class2syntax.put( BIT_SET_MAPPING.getJavaType(), BIT_SET_MAPPING ); class2syntax.put( BOOLEAN_MAPPING.getJavaType(), BOOLEAN_MAPPING ); + class2syntax.put( boolean.class, BOOLEAN_MAPPING ); class2syntax.put( CHAR_ARRAY_MAPPING.getJavaType(), CHAR_ARRAY_MAPPING ); class2syntax.put( BYTE_ARRAY_MAPPING.getJavaType(), BYTE_ARRAY_MAPPING ); class2syntax.put( DATE_MAPPING.getJavaType(), DATE_MAPPING ); @@ -151,6 +159,7 @@ public PrimitiveMapping lookup( Class javaType ) { + log.debug( "looking up mapping for {}", javaType.getName() ); return class2syntax.get( javaType ); } } Modified: directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeToPropertyMapping.java URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeToPropertyMapping.java?view=diff&rev=559292&r1=559291&r2=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeToPropertyMapping.java (original) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeToPropertyMapping.java Tue Jul 24 19:45:22 2007 @@ -24,12 +24,11 @@ import org.apache.directory.j2l.configuration.J2LConfiguration; import org.apache.commons.beanutils.DynaProperty; import org.apache.commons.beanutils.DynaClass; -import org.apache.commons.collections.CollectionUtils; import java.lang.reflect.Method; import java.lang.annotation.Annotation; -import java.util.List; -import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; /** * Useful data structure to track an attributeType to Java Bean Property along with @@ -42,13 +41,15 @@ { private final J2LConfiguration configuration; private AttributeTypeDescription attributeTypeDescription = new AttributeTypeDescription(); - private boolean isRequired = false; + private boolean required = false; + private boolean ignored = false; + private boolean existsInAnotherSchema = false; private Method setter; private Method getter; - private DynaClass dynaClass; + private Class beanClass; private DynaProperty dynaProperty; private PrimitiveMapping primitiveMapping; - private List annotations; + private Map annotations; public AttributeToPropertyMapping( J2LConfiguration configuration ) @@ -69,18 +70,25 @@ } - public List getAllPropertyAnnotations() + public Map getAllPropertyAnnotations() { + // @TODO we can detect and respond to duplicate annotations on getters and setters if ( annotations == null ) { - annotations = new ArrayList(); + annotations = new HashMap(); if ( getter != null && getter.getAnnotations() != null && getter.getAnnotations().length > 0 ) { - CollectionUtils.addAll( annotations, getter.getAnnotations() ); + for ( Annotation annotation : getter.getAnnotations() ) + { + annotations.put( annotation.getClass(), annotation ); + } } if ( setter != null && setter.getAnnotations() != null && setter.getAnnotations().length > 0 ) { - CollectionUtils.addAll( annotations, setter.getAnnotations() ); + for ( Annotation annotation : setter.getAnnotations() ) + { + annotations.put( annotation.getClass(), annotation ); + } } } @@ -102,13 +110,13 @@ public boolean isRequired() { - return isRequired; + return required; } public void setRequired( boolean required ) { - isRequired = required; + this.required = required; } @@ -152,16 +160,40 @@ public PrimitiveMapping getPrimitiveMapping() { + if ( primitiveMapping == null ) + { + this.primitiveMapping = configuration.getPrimitiveMappingRegistry().lookup( dynaProperty.getType() ); + } return primitiveMapping; } - public DynaClass getDynaClass() + public boolean isIgnored() + { + return ignored; + } + + public void setIgnored( boolean ignored ) + { + this.ignored = ignored; + } + + public boolean isExistsInAnotherSchema() + { + return existsInAnotherSchema; + } + + public void setExistsInAnotherSchema( boolean existsInAnotherSchema ) + { + this.existsInAnotherSchema = existsInAnotherSchema; + } + + public Class getBeanClass() { - return dynaClass; + return beanClass; } - public void setDynaClass( DynaClass dynaClass ) + public void setBeanClass( Class beanClass ) { - this.dynaClass = dynaClass; + this.beanClass = beanClass; } } Modified: directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractor.java URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractor.java?view=diff&rev=559292&r1=559291&r2=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractor.java (original) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractor.java Tue Jul 24 19:45:22 2007 @@ -21,12 +21,16 @@ import org.apache.directory.shared.ldap.schema.UsageEnum; import org.apache.directory.j2l.configuration.J2LConfiguration; -import org.apache.directory.j2l.configuration.OidGenerator; +import org.apache.directory.j2l.annotations.attribute.*; import org.apache.commons.beanutils.DynaClass; -import org.apache.commons.beanutils.BasicDynaClass; import org.apache.commons.beanutils.DynaProperty; +import org.apache.commons.beanutils.WrapDynaClass; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.NotImplementedException; +import org.apache.commons.collections.CollectionUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; import java.lang.reflect.Method; @@ -42,46 +46,157 @@ */ public class AttributeTypeExtractor { + private final static Logger log = LoggerFactory.getLogger( AttributeTypeExtractor.class ); private final J2LConfiguration configuration; - private final OidGenerator generator; - public AttributeTypeExtractor( J2LConfiguration configuration, OidGenerator generator ) + public AttributeTypeExtractor( J2LConfiguration configuration ) { this.configuration = configuration; - this.generator = generator; } - public Set extractAttributeToPropertyMappings( Class beanClass ) + public List extractAttributeToPropertyMappings( Class beanClass ) { - Set atds = new HashSet(); - DynaClass dynaClass = new BasicDynaClass( beanClass.getName(), beanClass ); + /* + * We want to add to the front of this list all the attributeTypes + * that can be processed without dependencies first: meaning without + * having a superType. Some schema processors may not be able to take + * into account seeing an attributeType which depends on another before + * seeing it's dependent attributeType first. + */ + List withOutSuperTypes = new ArrayList(); + List withSuperTypes = new ArrayList(); + + DynaClass dynaClass = WrapDynaClass.createDynaClass( beanClass ); DynaProperty[] properties = dynaClass.getDynaProperties(); for ( DynaProperty dynaProperty : properties ) { + if ( configuration.isPropertyIgnored( dynaProperty.getName() ) ) + { + continue; + } + // @TODO if the dynaProperty is mapped or indexed we need to take alternative approaches // This is to manage the cardinality aspect - what about dealing with sets? - atds.add( extractAttributeToPropertyMapping( dynaClass, dynaProperty ) ); + AttributeToPropertyMapping mapping = extractAttributeToPropertyMapping( beanClass, dynaProperty ); + + if ( ! mapping.isIgnored() ) + { + if ( mapping.getAttributeTypeDescription().getSuperType() == null ) + { + withOutSuperTypes.add( mapping ); + } + else + { + withSuperTypes.add( mapping ); + } + } + } + + // short out here if we cannot have dependency issues with no superTyped attributeTypes + if ( withSuperTypes.size() == 0 ) + { + return withOutSuperTypes; + } + + // @TODO this code below needs to be applied at a higher level to the + // entire pool of mappings for the schema rather than for each bean + + /* + * Populate a map with the oid of the attributeTypes we have seen mapped + * to their AttributeToPropertyMappings. We use this structure to see + * if one AttributeToPropertyMapping depends on another. + */ + Map oid2Mapping + = new HashMap(); + for ( AttributeToPropertyMapping mapping : withSuperTypes ) + { + oid2Mapping.put( mapping.getAttributeTypeDescription().getNumericOid(), mapping ); + } + for ( AttributeToPropertyMapping mapping : withOutSuperTypes ) + { + oid2Mapping.put( mapping.getAttributeTypeDescription().getNumericOid(), mapping ); + } + + List combined = new ArrayList(); + combined.addAll( withOutSuperTypes ); + AttributeToPropertyMapping starter = withSuperTypes.get( 0 ); + addWithDependenciesFirst( oid2Mapping, combined, withSuperTypes, starter ); + + return combined; + } + + + /** + * Adds the mappings that a mapping with a superType depends on to the combined + * list before adding the mapping with the superType. This is done recursively + * until the mappings from the withSuperTypes list are consumed. + * + * @param oid2mappings a map of attributeType numericOids to their mappings + * @param combined the final combined list of mappings with least dependencies + * @param withSuperTypes the list of mappings with superTypes + * @param mapping the mapping to consider for dependencies + */ + public void addWithDependenciesFirst( Map oid2mappings, + List combined, + List withSuperTypes, + AttributeToPropertyMapping mapping ) + { + // basis case - exist when we have no more superTyped mappings + if ( withSuperTypes.isEmpty() ) + { + combined.add( mapping ); + return; + } + + AttributeToPropertyMapping superTypeMapping = + oid2mappings.get( mapping.getAttributeTypeDescription().getSuperType() ); + + // if the superType is not defined in our map it must be external (in another schema) + if ( superTypeMapping == null ) + { + combined.add( mapping ); + return; + } + + // if the superType mapping is already in the combined list then we're good + // and can just add this mapping now since the attributeType it depends on + // has it's mapping before this current dependent mapping + if ( combined.contains( superTypeMapping ) ) + { + combined.add( mapping ); + return; + } + + // ----- Recursive Call ---------------------------------------------- + + // The superType mapping is not in combined so we must add it with its + // deps first then we can add our mapping which depends on this superType. + if ( withSuperTypes.contains( superTypeMapping ) ) + { + withSuperTypes.remove( superTypeMapping ); + addWithDependenciesFirst( oid2mappings, combined, withSuperTypes, superTypeMapping ); } - return atds; + combined.add( mapping ); } - public AttributeToPropertyMapping extractAttributeToPropertyMapping( DynaClass dynaClass, DynaProperty dynaProperty ) + public AttributeToPropertyMapping extractAttributeToPropertyMapping( Class clazz, DynaProperty dynaProperty ) { AttributeToPropertyMapping mapping = new AttributeToPropertyMapping( configuration ); - mapping.setSetter( getPropertySetter( dynaClass, dynaProperty ) ); - mapping.setGetter( getPropertyGetter( dynaClass, dynaProperty ) ); - mapping.setDynaClass( dynaClass ); + mapping.setSetter( getPropertySetter( clazz, dynaProperty ) ); + mapping.setGetter( getPropertyGetter( clazz, dynaProperty ) ); + mapping.setBeanClass( clazz ); + mapping.setDynaProperty( dynaProperty ); if ( mapping.getGetter() == null && mapping.getSetter() == null ) { - throw new IllegalStateException( "dynaProperty " + dynaProperty.getName() + " in class " - + dynaClass.getClass() + " should at least have a getter or setter." ); + throw new IllegalStateException( "Property " + dynaProperty.getName() + " in class " + + clazz + " should at least have a getter or setter." ); } checkForDuplicateAnnotations( mapping ); @@ -98,10 +213,167 @@ private void applyAnnotationsToAttributeTypeDescription( AttributeToPropertyMapping mapping ) { - List annotations = mapping.getAllPropertyAnnotations(); - for ( Annotation annotation : annotations ) + Map annotations = mapping.getAllPropertyAnnotations(); + + // ----- IgnoreBeanProperty -------------------------------------------------- + + if ( annotations.containsKey( IgnoreBeanProperty.class ) ) { - if ( annotation instanceof ) + log.info( "Ignoring {} property.", mapping.getDynaProperty().getName() ); + mapping.setIgnored( true ); + return; + } + + // ----- LdapAttributeAliases -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeAliases.class ) ) + { + String[] aliases = ( ( LdapAttributeAliases ) annotations.get( LdapAttributeAliases.class ) ).value(); + List names = new ArrayList(aliases.length); + CollectionUtils.addAll( names, aliases ); + log.info( "Overriding aliases {} for {} property.", names, mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setNames( names ); + } + + // ----- LdapAttributeCollective -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeCollective.class ) ) + { + log.info( "Setting {} property as collective attributeType.", mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setCollective( true ); + } + + // ----- LdapAttributeDescription -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeDescription.class ) ) + { + String desc = ( ( LdapAttributeDescription ) annotations.get( LdapAttributeDescription.class ) ).value(); + log.info( "Setting {} property's attributeType description.", mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setDescription( desc ); + } + + // ----- LdapAttributeEqualityMatch -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeEqualityMatch.class ) ) + { + String mr = ( ( LdapAttributeEqualityMatch ) annotations.get( LdapAttributeEqualityMatch.class ) ).value(); + log.info( "Using {} matchingRule for {} property.", mr, mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setEqualityMatchingRule( mr ); + } + + // ----- LdapAttributeExists -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeExists.class ) ) + { + log.info( "Not generating attributeType description for {} property. " + + "It's marked as existing in another schema.", mapping.getDynaProperty().getName() ); + mapping.setExistsInAnotherSchema( true ); + } + + // ----- LdapAttributeNotUserModifiable -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeNotUserModifiable.class ) ) + { + log.info( "AttributeType of {} property will not be user modifiable.", mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setUserModifiable( false ); + } + + // ----- LdapAttributeObsolete -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeObsolete.class ) ) + { + log.info( "Marking {} property's attributeType will be obsolete.", mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setObsolete( true ); + } + + // ----- LdapAttributeOid -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeOid.class ) ) + { + String oid = ( ( LdapAttributeOid ) annotations.get( LdapAttributeOid.class ) ).value(); + log.info( "Overriding sequentially assigned OID for {} property: using {} instead.", + mapping.getDynaProperty().getName(), oid ); + mapping.getAttributeTypeDescription().setNumericOid( oid ); + } + + // ----- LdapAttributeOrderingMatch -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeOrderingMatch.class ) ) + { + String mr = ( ( LdapAttributeOrderingMatch ) annotations.get( LdapAttributeOrderingMatch.class ) ).value(); + log.info( "Using {} matchingRule for {} property's attributeType ordering.", + mr, mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setOrderingMatchingRule( mr ); + } + + // ----- LdapAttributeRequired -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeRequired.class ) ) + { + log.info( "Marking {} property as required (in MUST list) within objectClass.", + mapping.getDynaProperty().getName() ); + mapping.setRequired( true ); + } + + // ----- LdapAttributeSchemaExtension[s] -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeSchemaExtensions.class ) ) + { + LdapAttributeSchemaExtension[] extentionsArray = ( ( LdapAttributeSchemaExtensions ) + annotations.get( LdapAttributeSchemaExtensions.class ) ).value(); + Map> extensions = new HashMap>( extentionsArray.length ); + for ( LdapAttributeSchemaExtension extension : extentionsArray ) + { + String[] valuesArray = extension.values(); + List values = new ArrayList( valuesArray.length ); + CollectionUtils.addAll( values, valuesArray ); + extensions.put( extension.name(), values ); + } + + log.info( "Adding schema extensions for attributeType description of {0} property: {1}", + mapping.getDynaProperty().getName(), extensions ); + mapping.getAttributeTypeDescription().setExtensions( extensions ); + } + + // ----- LdapAttributeSubstringMatch -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeSubstringMatch.class ) ) + { + String mr = ( ( LdapAttributeSubstringMatch ) + annotations.get( LdapAttributeSubstringMatch.class ) ).value(); + log.info( "Using matchingRule {} for substring matching {} property's attributeType.", + mr, mapping.getDynaProperty().getName() ); + mapping.getAttributeTypeDescription().setSubstringsMatchingRule( mr ); + } + + // ----- LdapAttributeSuperType -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeSuperType.class ) ) + { + String superType = ( ( LdapAttributeSuperType ) annotations.get( LdapAttributeSuperType.class ) ).value(); + log.info( "Setting superType of attributeType for {} property to {}.", + mapping.getDynaProperty().getName(), superType ); + mapping.getAttributeTypeDescription().setSuperType( superType ); + } + + // ----- LdapAttributeSyntax -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeSyntax.class ) ) + { + String syntax = ( ( LdapAttributeSyntax ) annotations.get( LdapAttributeSyntax.class ) ).value(); + log.info( "Overriding syntax of {} property's attributeType: using {}.", + mapping.getDynaProperty().getName(), syntax ); + mapping.getAttributeTypeDescription().setSyntax( syntax ); + } + + // ----- LdapAttributeUsage -------------------------------------------------- + + if ( annotations.containsKey( LdapAttributeUsage.class ) ) + { + UsageEnum usage = ( ( LdapAttributeUsage ) annotations.get( LdapAttributeUsage.class ) ).value(); + log.info( "Overriding default USAGE for attributeType of {} property: using {}", + mapping.getDynaProperty().getName(), usage.toString() ); + mapping.getAttributeTypeDescription().setUsage( usage ); } } @@ -110,11 +382,14 @@ { if ( mapping.getDynaProperty().isIndexed() && mapping.getDynaProperty().isMapped() ) { + log.error( "Cannot handle complex properties such as maps and lists right now for property {}", + mapping.getDynaProperty().getName() ); throw new NotImplementedException( "Only simple properties are handled." ); } mapping.getAttributeTypeDescription().setUsage( UsageEnum.USER_APPLICATIONS ); - mapping.getAttributeTypeDescription().setNumericOid( generator.nextAttributeTypeOid() ); + mapping.getAttributeTypeDescription().setNumericOid( + configuration.getSchemaConfiguration().getOidGenerator().nextAttributeTypeOid() ); mapping.getAttributeTypeDescription().setCollective( false ); mapping.getAttributeTypeDescription().setDescription( "undocumented" ); mapping.getAttributeTypeDescription().setObsolete( false ); @@ -139,7 +414,7 @@ mapping.getAttributeTypeDescription().setExtensions( extensions ); // ----- setup the name ------------------------------ - String name = null; + String name; if ( configuration.getEntityPrefix() != null ) { // use the prefix + property name if prefix is specified @@ -148,7 +423,7 @@ else { // default to fully qualified class name of bean + [P]roperty - name = mapping.getDynaClass().getName() + "." + + name = mapping.getBeanClass().getName() + "." + StringUtils.capitalize( mapping.getDynaProperty().getName() ); } mapping.getAttributeTypeDescription().setNames( Collections.singletonList( name ) ); @@ -163,6 +438,9 @@ { if ( mapping.getGetter().getAnnotations().length != 0 && mapping.getSetter().getAnnotations().length != 0 ) { + log.error( "Found duplicate (potentially ambiguous) annotations on property {} methods.\n" + + "Please only use mutator or accessor but not both for the same annotation!", + mapping.getDynaProperty().getName() ); throw new IllegalArgumentException( "Both setter and getter contain annotations in class " + mapping.getGetter().getClass().getName() + ": " + mapping.getGetter().getName() + " and " + mapping.getSetter().getName() ); @@ -170,40 +448,65 @@ } } - public static Method getPropertySetter( DynaClass dynaClass, DynaProperty property ) + + public static Method getPropertySetter( Class clazz, DynaProperty property ) { - Method setter = null; + Method setter; try { - setter = dynaClass.getClass().getMethod( "set" + StringUtils.capitalize( property.getName() ), - new Class[] { property.getClass() } ); + String methodName = "set" + StringUtils.capitalize( property.getName() ); + + for ( Method method : clazz.getMethods() ) + { + log.debug( method.getName() ); + } + + setter = clazz.getMethod( methodName, new Class[] { property.getType() } ); + } + catch ( NoSuchMethodException e ) + { + log.info( "No setter found on bean property: {}", property.getName() ); + return null; } - catch ( NoSuchMethodException e ) {} return setter; } - public static Method getPropertyGetter( DynaClass dynaClass, DynaProperty property ) + public static Method getPropertyGetter( Class clazz, DynaProperty property ) { Method getter = null; try { - getter = dynaClass.getClass().getMethod( "get" + StringUtils.capitalize( property.getName() ), - new Class[] { property.getClass() } ); + String methodName = "get" + StringUtils.capitalize( property.getName() ); + getter = clazz.getMethod( methodName ); + } + catch ( NoSuchMethodException e ) + { + if ( property.getType() == Boolean.class ) + { + log.info( "No getter expected for boolean bean property: {}", property.getName() ); + } + else + { + log.warn( "Expecting getter but none found for non-boolean bean property: {}", property.getName() ); + } } - catch ( NoSuchMethodException e ) {} if ( getter == null ) { try { - getter = dynaClass.getClass().getMethod( "is" + StringUtils.capitalize( property.getName() ), - new Class[] { property.getClass() } ); + getter = clazz.getMethod( "is" + StringUtils.capitalize( property.getName() ) ); + } + catch ( NoSuchMethodException e ) + { + log.warn( "Expecting getter (with 'is' prefix) but non found for boolean bean property: {}", + property.getName() ); + return null; } - catch ( NoSuchMethodException e ) {} } return getter; } Added: directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/resources/log4j.properties URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/resources/log4j.properties?view=auto&rev=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/resources/log4j.properties (added) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/main/resources/log4j.properties Tue Jul 24 19:45:22 2007 @@ -0,0 +1,6 @@ +log4j.rootCategory=ERROR, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n + Modified: directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/AnnotationTest.java URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/AnnotationTest.java?view=diff&rev=559292&r1=559291&r2=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/AnnotationTest.java (original) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/AnnotationTest.java Tue Jul 24 19:45:22 2007 @@ -22,7 +22,7 @@ /** * Test cases for the various annotations used in J2L. Two classes are used * for testing these annotations. They are included in this package as - * TestBean and MutableTestBean. + * TestBeanNoAnnotations and MutableTestBean. * * @author Apache Directory Project * @version $Rev$, $Date$ Copied: directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBeanNoAnnotations.java (from r558576, directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBean.java) URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBeanNoAnnotations.java?view=diff&rev=559292&p1=directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBean.java&r1=558576&p2=directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBeanNoAnnotations.java&r2=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBean.java (original) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/annotations/TestBeanNoAnnotations.java Tue Jul 24 19:45:22 2007 @@ -19,24 +19,27 @@ */ package org.apache.directory.j2l.annotations; + /** - * A bean with J2L annotations used for testing these annotations. + * A bean without any annotations to test the defaults. * * @author Apache Directory Project * @version $Rev$, $Date$ */ -public class TestBean +public class TestBeanNoAnnotations { private String stringProperty; private short shortProperty; private long longProperty; private byte byteProperty; private boolean booleanProperty; - private char charProperty; + // not supported + // private char charProperty; private int intProperty; - private float floatProperty; - private double doubleProperty; - private FooEnum enumProperty; + // not supported + // private float floatProperty; + // private double doubleProperty; + // private FooEnum enumProperty; public String getStringProperty() { @@ -63,16 +66,19 @@ return booleanProperty; } + /* not supported yet public char getCharProperty() { return charProperty; } + */ public int getIntProperty() { return intProperty; } + /* not supported yet public float getFloatProperty() { return floatProperty; @@ -87,6 +93,7 @@ { return enumProperty; } + */ protected void setStringProperty( String stringProperty ) { @@ -98,16 +105,19 @@ this.booleanProperty = booleanProperty; } + /* not supported yet protected void setCharProperty( char charProperty ) { this.charProperty = charProperty; } + */ protected void setIntProperty( int intProperty ) { this.intProperty = intProperty; } + /* not supported yet protected void setFloatProperty( float floatProperty ) { this.floatProperty = floatProperty; @@ -122,6 +132,7 @@ { this.enumProperty = enumProperty; } + */ protected void setShortProperty( short shortProperty ) { Added: directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractorTest.java URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractorTest.java?view=auto&rev=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractorTest.java (added) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractorTest.java Tue Jul 24 19:45:22 2007 @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.directory.j2l.descriptions; + +import junit.framework.TestCase; +import org.apache.directory.j2l.configuration.J2LConfiguration; +import org.apache.directory.j2l.annotations.TestBeanNoAnnotations; +import org.apache.directory.shared.ldap.schema.SchemaUtils; + +import java.util.List; + + +/** + * Test cases for the AttributeTypeExtractor. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class AttributeTypeExtractorTest extends TestCase +{ + J2LConfiguration configuration; + AttributeTypeExtractor extractor; + + + public void setUp() + { + configuration = new J2LConfiguration(); + configuration.setEntityPrefix( "bogus" ); + configuration.getSchemaConfiguration().setName( "bogus" ); + configuration.setGenerateSchemaFile( true ); + extractor = new AttributeTypeExtractor( configuration ); + } + + + public void tearDown() + { + extractor = null; + configuration = null; + } + + + public void testExtraction() throws Exception + { + List mappings = + extractor.extractAttributeToPropertyMappings( TestBeanNoAnnotations.class ); + for ( AttributeToPropertyMapping mapping : mappings ) + { + System.out.println( SchemaUtils.render( mapping.getAttributeTypeDescription() ) ); + } + } +} Propchange: directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/java/org/apache/directory/j2l/descriptions/AttributeTypeExtractorTest.java ------------------------------------------------------------------------------ svn:executable = * Added: directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/resources/log4j.properties URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/resources/log4j.properties?view=auto&rev=559292 ============================================================================== --- directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/resources/log4j.properties (added) +++ directory/sandbox/akarasulu/j2l/trunk/runtime/src/test/resources/log4j.properties Tue Jul 24 19:45:22 2007 @@ -0,0 +1,6 @@ +log4j.rootCategory=DEBUG, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n +