Making Your Own Filter Conditions
In last section you saw how BeforeElement and InsideElement works. With these conditions and the basic options from StartElement and EndElement you can do a lot of filters. But your imagination always think in some type of filtering that will be difficult or impossible to accomplish just using BeforeElement or InsideElement. To solve this question, JColtrane allows user to create your own annotion with the all kind of conditions you want. So, in this section we will see the steps to build the annotation and conditions, making an example that intend to allow build a condition concerning to the current branch of the parsing process.
Step 1: Creating An Annotation
The first thing you must to do is create the annotation that will indicating the conditions you want. It's recomended using a significative name. For example, we will create the UserAnnotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface UserAnnotation {
String currentBranch() ;
}
In the annotation you must to insert the metadata that you will need to build you condition. In the above example, we need the current branch.
Step 2: Creating Condition
To create your condition, you mus implement the intefarce Condition from JColtrane's package net.sf.jColtrane.conditions. This interface has the method verify that returns a boolean. You must make it return true when your condition is satisfied and false if it's not satisfied. In our example, we want make possible for user choose a desired current branch based on a regular expression:
public class UserCondition implements Condition {
private Pattern pattern;
public UserCondition(String regularExpression,int elementDeep) {
pattern=Pattern.compile(regularExpression);
}
@Override
public boolean verify(ContextVariables contextVariables) {
return pattern.matcher(contextVariables.getCurrentBranch()).matches();
}
}
The ContextVariables is a special class that gives you all information about the parsing. We will see it in details in Receiving Parameters from JColtrane.
Step 3: Creating a ConditionFactory
You need to extend the abstract class ConditionFactory. This class has the abstract method getConditions that return a list of Condition. It receives a Annotation as parameter, that could be the UserAnnotation that we have created. So, in this class you receive de metadata you need to build your condition. Note that for the annotation could exist several linked conditions. So, this is the reason you need to return a list of conditions. You can just remember from StartElement that you can put a tag condition and a uri condition, so, in this case, there are 2 linked condition to the StartElement annotation. In our example we make just one condition for simplicity. Let's see:
public class UserConditionsFactory implements ConditionsFactory{
@Override
public List<Condition> getConditions(Annotation annotation) {
if(annotation instanceof UserAnnotation){
List<Condition> conditions=new LinkedList<Condition>();
UserAnnotation userAnnotation=(UserAnnotation) annotation;
conditions.add(new UserCondition(userAnnotation.currentBranch()));
return conditions;
}
return null;
}
}
Note that the method returns null if the annotation is not from the desired type. If you return null in this method, JColtrane will not consider any condition to execute the method.
Step 4: Indicating JColtrane the ConditionsFactory
In this Last Step, you need to tell JColtrane where to find the factory you created. We do this including the line in UserAnnotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@ConditionFactoryAnnotation(UserConditionsFactory.class)
public @interface UserAnnotation {
String currentBranch();
}
After this last step, you can use your condition wherever you want:
public class UserAnnotatedClass {
@UserAnnotation(currentBranch="/.*/line.*")
@StartElement
public void executeUserTest(@CurrentBranch String currentBranch){
System.out.println(currentBranch);
System.out.println("executing test!!!!!");
}
}
Runnign the test, based on XML document viewed in last section, system prints:
/beanDescriptor/line/
executing test!!!!!
/beanDescriptor/line/property/
executing test!!!!!
/beanDescriptor/line/paragraphy/
executing test!!!!!
/beanDescriptor/line/paragraphy/phrase/
executing test!!!!!
/beanDescriptor/line/property2/
executing test!!!!!
NOTE: Just like when using BeforeElement, you need to use your annotations with an StartElement or a EndElement annotations. If you use just your annotation, JColtrane will not do anything.
After this section, you have a powerfull tool to filter element in a XML parsing process. Now, to making you able to do anything you want when parsing XML, it's just missing how to get information from parsing process. Let's see it in Receiving Parameters from JColtrane.