Page tree
Skip to end of metadata
Go to start of metadata

Introduction

Currently one has to type fully qualified classname in order to define a field in any configuration such as 

class: info.magnolia.ui.form.field.definition.TextFieldDefinition

However, fully qualified classnames are hard to remember and verbose. If we were to simplify/reduce the verbosity from the configuration, our configuration files would look much nicer and compact as well as It wouldn't be a hassle to remember which definition is coming from which class and hence its fully qualified class name. The ticket of  DEV-338 - Getting issue details... STATUS  is created to tackle this problem and MGNLUI-3882 - Getting issue details... STATUS  to implement it. Perhaps for the time being It may seems like we are only targeting fields ,however, the solution which comes up from the discussion regarding the fields should/could be applied relatively easy to the other parts of Magnolia configuration such as actions.



Potential Solutions

Those solution can be applied at info.magnolia.ui.form.field.factory.FieldFactoryFactory#createFieldFactory(FieldDefinition, Object...).

This method is responsible to create a field factory instance out of the FieldDefinition, its the place when the query the registry for FieldTypeDefinition against given definition class.

1) Annotations

We may annotate fields like below and get those fields easily in the runtime. Those annotation would contain values where we use it as reduced definitions (shortcuts).

Ideally we would create a component out of it e.g AnnotationResolver which would be generic for all annotations we have say fields, actions, etc.

Resolver also has to update the key-value pairs over time in order words, it has to scan the classpath like ClasspathScanner.


Example implementation:

Reflections reflections = new Reflections("info.magnolia.ui.form.field");
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(Field.class);


@Retention(RetentionPolicy.RUNTIME)
public @interface Field {
    String name();
}
 
@Field(name="text")
public class TextFieldDefinition extends ConfiguredFieldDefinition {}

Advantages

  • Self documented
  • Elegant look
  • Not error prone
  • Potential to apply it for all definitions

Drawbacks

  • Need to edit Java code
  • All definitions should be modified with the Annotation
  • Performance ?
 

2) Pre-defined key-value pair

A predefined key-value pair could be used to generate the reduced version of field definitions.

Advantages

  • Straightforward for user

Drawbacks

  • Ugly looking structure to maintain
  • Old school

3) Runtime Classpath search with specific Pattern

Basically we can get all the subclasses of FieldDefinition and if the given reduced class form matches the pattern we can easily identify which class it points to. For instance:

  • text → TextFieldDefinition
  • basicupload → BasicUploadFieldDefinition
  • checkbox → CheckBoxFieldDefinition

As you might grasp there is a pattern which makes is easier to detect those reduced form definitions. It's very doable to create an instance of a definition class based on the given keyword for instance 'text'.

The biggest drawback for this approach is that there would be conflicts since we would have to search the whole Classpath for fields due to users' custom field implementations. Upon a conflict it would be hard if not impossible to detect which definition is the correct one. Theoretically it's possible to have this approach without conflicts with users naming the classes properly(ideally with suffix/prefix of the module or similar) but this wouldn't be a nice thing to do.


Example implementation:

Reflections reflections = new Reflections("info.magnolia.ui.form.field");
Set<Class<? extends FieldDefinition>> subTypesOf = reflections.getSubTypesOf(FieldDefinition.class);

 

Advantages

  • Predefined pattern
  • No code changes in the definitions

Drawbacks

  • Error prone at wrong hands
  • Might be conflicts over different packages
  • Performance ?

4) Registry reference Id

There are already defined reference keys for those fields such as 'textField' for TextFieldDefinition. We can make use of those and simply make a call to the registry in order to get the definition. Users need to simply adjust those names as they wish to.


Example implementation:

fieldTypeDefinitionRegistry.getProvider("textField").get();


Advantages

  • Already defined values for default definitions
  • Easily configurable

Drawbacks

  • Can't think of any



Migration and Fallback Mechanism

Although this chapter still sort of depends on the accepted solution, migration wouldn't be necessary for due to the fact that the actual plan here is to use both of the way to define a field class meaning that one may use the reduced version or directly fully qualified version. Fallback mechanism on the other hand, also depends on the accepted solution but ideally it shouldn't be even necessary since both ways would be accepted.


Further Ideas


  • Some mechanism/app to display user which shortcut would point to which definition class.
  • If we go with solution#4, we should be reducing the reference ids e.g 'textField' to 'text' would look nicer and we know that its already a field.
 
  • No labels

2 Comments

  1. Could you point me to a description how the M2B(N2B) should be handled? Can't find it when skimming the text. Thx (smile)

  2. To be honest - I would remove the first three variants, because obviously why would we want to re-invent the wheel, when field type defs can be referenced via registry? One thing we need to do is to make the FieldTypeDefiniton extend the NamedDefinition interface (so that the custom names could be specified and some other minor requirements fulfilled).

    Roman Kovařík's question is a valid though - how do we expand the alias to a class name at the transformation process: N2B has some crutches that might provide that (@TransformedBy or similar), whereas Map2Bean has no capabilities for that at all.