Example of custom file processor using parameters

Let's take the ToUppercaseProcessor example and enhance it to bring more user interaction.

We want, as new functionality, that the user can:

  • Choose to transform the text to uppercase, lowercase or not transform the case.
  • Choose to remove diacritic marks (like accents, cedillas, dots, tildes ...)

So, the file:

John
François
André
João

will become (if the user choose "to lower case" and "remove diacritic marks")

john
francois
andre
joao

To implement this behaviour, you will functionally need two parameters:

  • A "type of change" that specify what case change will be applied. This parameter can take 3 values "None", "Uppercase" and "Lowercase". We will define a TypeOfChange enumeration type to specify the 3 possible values.
  • A "remove diacritic marks" that can be true or false, it will simply be a boolean value.

Parameters in processors

When a file processor defines parameters, you usually want to do 2 things:

  • Remind the parameters values so that, in next execution, the user will find back the previous values. The Piper Tool will also allow saving several configured pipelines (a pipeline is a suite of file processors) to be able to retrieve them later.
    The processor interacts with a Settings object to load and save parameters.
  • Display the parameters in the tool GUI so that the user can update them.
    In the File Piper tool, the GUI is automatically generated. All you have to do is the define setters/getters for the parameters in your processor class and to decorate the getters with appropriate annotations.

Using Settings

The Settings interface used in the Piper Tool works like a typed java Properties class. You have method to get and put typed values using a string key to identify them. The getter methods always take a default value as last parameter. This default value is returned if the setting is not (yet) defined.

So, for our example parameterized processor, it parameter handling will look like:

    private static final String TYPE_OF_CHANGE_KEY = "changeCase.type";
    private static final String REMOVE_DIACRITIC_MARKS_KEY = "changeCase.removeDiacriticMarks";

    enum TypeOfChange {
        None, Uppercase, Lowercase
    };

    public TypeOfChange getTypeOfChange() {
        return (TypeOfChange) getSettings().getEnumProperty(TYPE_OF_CHANGE_KEY, TypeOfChange.None);
    }

    public void setTypeOfChange(TypeOfChange typeOfChange) {
        getSettings().setEnumProperty(TYPE_OF_CHANGE_KEY, typeOfChange);
    }

    public boolean getRemoveDiacriticMarks() {
        return getSettings().getBooleanProperty(REMOVE_DIACRITIC_MARKS_KEY, false);
    }

    public void setRemoveDiacriticMarks(boolean removeDiacriticMarks) {
        getSettings().setBooleanProperty(REMOVE_DIACRITIC_MARKS_KEY, removeDiacriticMarks);
    }

There's nothing more to do to have the parameters correctly stored and retrieved by the Piper Tool. Remind, that we inherit from the OneToOneTextFileProcessor base class. It's this class that provides the getSettings() method.

If you prefer to put the parameter values in instance variables, you can alternatively do something like:

    private static final String TYPE_OF_CHANGE_KEY = "changeCase.type";
    private static final String REMOVE_DIACRITIC_MARKS_KEY = "changeCase.removeDiacriticMarks";

    private TypeOfChange typeOfChange;
    private boolean removeDiacriticMarks;    
    
    enum TypeOfChange {
        None, Uppercase, Lowercase
    };

        public void init(Settings sett) {
            super.init(sett);
        typeOfChange = (TypeOfChange) sett.getEnumProperty(TYPE_OF_CHANGE_KEY, TypeOfChange.None);
        removeDiacriticMarks = sett.getBooleanProperty(REMOVE_DIACRITIC_MARKS_KEY, false);
        }
        
    public TypeOfChange getTypeOfChange() {
        return typeOfChange;
    }

    public void setTypeOfChange(TypeOfChange newTypeOfChange) {
        typeOfChange=newTypeOfChange;
        getSettings().setEnumProperty(TYPE_OF_CHANGE_KEY, typeOfChange);
    }

    public boolean getRemoveDiacriticMarks() {
        return removeDiacriticMarks;
    }

    public void setRemoveDiacriticMarks(boolean newRemoveDiacriticMarks) {
        removeDiacriticMarks=newRemoveDiacriticMarks;
        getSettings().setBooleanProperty(REMOVE_DIACRITIC_MARKS_KEY, removeDiacriticMarks);
    }

Notice that, in this case, you have to initialize you instance variables when the settings are set on the processor by overriding the init method.

Automatic GUI

Using the automatic GUI to edit parameters is extremely simple: just put a @EditorConfig annotation on the getters of your parameters.

In our example it becomes:

    @EditorConfig(name = "Case change")
    public TypeOfChange getTypeOfChange() {
        return (TypeOfChange) getSettings().getEnumProperty(TYPE_OF_CHANGE_KEY, TypeOfChange.None);
    }

    ...
    
    @EditorConfig(name = "Remove diacritic marks")
    public boolean getRemoveDiacriticMarks() {
        return getSettings().getBooleanProperty(REMOVE_DIACRITIC_MARKS_KEY, false);
    }
    

The EditorConfig annotation can take several parameters, for simple usage like here you can use:

  • name: gives a name to the parameter, this name will be used as label in the GUI.
  • description: give a description of your parameter, it will be shown as a tooltip in the GUI.
  • index: an integer value that can be used to order the fields in the GUI.

It's as simple as that!

Implement the processor logic

Of course, you have to implement the new logic using the input parameter values in the process(...) method. As this is plain java programming and not the purpose of this document, I will not comment this implementation here. If you want to see it, the full source code is in the FilePiper-ExtensionExample project.

Result

The processing done by this parameterized processor is not far more complex than for the toUppercase processor. I will not describe it here. The full code is available in the ChangeCaseProcessor class of the FilePiper-ExtensionExample project.

To have the processor displayed in the available processor drop down, you have to put its name in the xxx configuration file META_INF/services/org.filePiper.model.FileProcessor as explained in previous example.

When you choose this new "Change case" processor you will see the generated GUI (using the 'Thin metal' look & feel here):

<i>Generated interface for "Change Case" processor</i>

See running the examples for explanations on how to build and deploy the examples.