JBehave
  1. JBehave
  2. JBEHAVE-258

Annotation for ParameterConverter

    Details

    • Type: Improvement Improvement
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Number of attachments :
      0

      Description

      Simplifying adding ParameterConverter to Steps. Here's an example :

      public class DateTimeConverter  implements ParameterConverter {
      	@Override
      	public boolean accept(Type type) {
      		return type.equals( DateTime.class );
      	}
      
      	@Override
      	public Object convertValue(String value, Type type) {			
      		return new DateTime( value );
      	}
      }
      
      @ParameterConverters(DateTimeConverter.class)
      public class PersonSteps {
      	private Person person;
      	private DateTime currentDate;
      	// ... steps
      }
      

      The ParameterConverters annotation takes an array of TypeConverter :

      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.TYPE)
      public @interface ParameterConverters {
      	Class<? extends ParameterConverter>[] value();
      }
      

      Here is a steps factory :

      public class ParameterConverterStepsFactory {
      
          public CandidateSteps[] createCandidateSteps(Object... stepsInstances) throws InstantiationException, IllegalAccessException {
              CandidateSteps[] candidateSteps = new CandidateSteps[stepsInstances.length];
              for (int i = 0; i < stepsInstances.length; i++) {
              	Object stepsInstance = stepsInstances[i];
              	StepsConfiguration configuration;
              	
              	ParameterConverters parameterConverters = 
              		stepsInstance.getClass().getAnnotation( ParameterConverters.class );
              	
              	if( parameterConverters != null ) {
              		configuration = createConfiguration( parameterConverters );
              	} else {    		
              		configuration = new StepsConfiguration();
              	}
              	
                  candidateSteps[i] = new Steps(configuration, stepsInstance);
              }
              return candidateSteps;
          }
      
      	private StepsConfiguration createConfiguration(
      			ParameterConverters annotation) throws InstantiationException, IllegalAccessException {
      		ParameterConverter[] converters = new ParameterConverter[ annotation.value().length ];
      		for( int i = 0; i < converters.length; i ++ ) {
      			converters[ i ] = annotation.value()[ i ].newInstance();
      		}
      		org.jbehave.scenario.steps.ParameterConverters converterAggregate = 
      			new org.jbehave.scenario.steps.ParameterConverters( converters );
      		return new StepsConfiguration( converterAggregate );
      	}
      }
      

        Activity

        Hide
        Mauro Talevi added a comment -

        Interesting stuff, Bruno. My only comment is that the annotation route might work nicely with converters that have default constructors, but how do we handle those that take parameters upon instantiation. It might get pretty messy.

        Show
        Mauro Talevi added a comment - Interesting stuff, Bruno. My only comment is that the annotation route might work nicely with converters that have default constructors, but how do we handle those that take parameters upon instantiation. It might get pretty messy.
        Hide
        Bruno Bieth added a comment - - edited

        I believe in most cases converters don't need parameters.
        If I recall the example in the documentation speak about dates. Honestly I don't think you should handle date conversion differently across your scenarios.
        Of course I'm not saying you should remove the possibility to instanciate converters. Just that most of the time you'd have :

        @ParameterConverters({DateTimeConverter.class,PercentageConverter.class})
        public class PersonSteps {
        //...
        }
        

        As opposed to

        public class PersonSteps extends Steps {
        private static final StepsConfiguration configuration = new StepsConfiguration();
         
        public PersonSteps(ClassLoader classLoader) {
            super(configuration);
            configuration.useParameterConverters(new ParameterConverters(
                   new DateTimeConverter(),new PercentageConverter()));  // define converter for custom type Date
        }
        }
        

        and as a side note you have to extend Steps (at least that's what the documentation says).

        Show
        Bruno Bieth added a comment - - edited I believe in most cases converters don't need parameters. If I recall the example in the documentation speak about dates. Honestly I don't think you should handle date conversion differently across your scenarios. Of course I'm not saying you should remove the possibility to instanciate converters. Just that most of the time you'd have : @ParameterConverters({DateTimeConverter.class,PercentageConverter.class}) public class PersonSteps { //... } As opposed to public class PersonSteps extends Steps { private static final StepsConfiguration configuration = new StepsConfiguration(); public PersonSteps( ClassLoader classLoader) { super (configuration); configuration.useParameterConverters( new ParameterConverters( new DateTimeConverter(), new PercentageConverter())); // define converter for custom type Date } } and as a side note you have to extend Steps (at least that's what the documentation says).
        Hide
        Mauro Talevi added a comment -

        In some cases you do need to provide parameters to the converters, if you want to make the converters reasonably re-usable.

        But I take your point that for those converters that don't need parameters the annotation strategy is terser and more compact.

        BTW, the Steps classes don't need to extend Steps anymore and the converters configuration can be done
        outside of the Steps instance.

        Show
        Mauro Talevi added a comment - In some cases you do need to provide parameters to the converters, if you want to make the converters reasonably re-usable. But I take your point that for those converters that don't need parameters the annotation strategy is terser and more compact. BTW, the Steps classes don't need to extend Steps anymore and the converters configuration can be done outside of the Steps instance.

          People

          • Assignee:
            Unassigned
            Reporter:
            Bruno Bieth
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated: