The Talon Manual

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

div

...

id

...

toc

...

classtoc
div
classtocTitle

In This Section

div
classtocContents

Table of Contents
maxLevel2
indent8px
stylenone

Introduction: The Listener API

...

Developers may tap into listener mechanism to perform additional model validations as given in example below. The example demonstrates how to use the listener mechanism to enforce globally unique field names ids (meaning both the model for which code is generated and all its imports recursively).

Code Block
languagejava
titlePseudocode Demonstrating External Validation
package mypackage;

import java.util.HashSet;
import java.util.Set;
import com.neeve.adm.AdmField;
import com.neeve.adm.AdmModel;
import com.neeve.adm.AdmModelImport;
import com.neeve.adm.AdmSourceCodeErrorAggregator;
import com.neeve.tools.AdmCodeGenerator;
import com.neeve.tools.AdmCodeGenerator.CodeGenerateEvent;
public class CodegenListener implements AdmCodeGenerator.CodegenListener {
    @Override
    public void codeGenerateEvent(CodeGenerateEvent e) {
        switch (e.getEventType()) {
            case START:
                System.err.println("CodegenListener START");
                break;
            case SKIP:
                System.err.println("CodegenListener SKIP");
                break;
            case MODEL_PARSED:
                System.err.println("CodegenListener MODEL_PARSED " + e.getModel().getFullName());
                validateFieldIdsUnique(e.getModel(), e.getErrorAggregator(), new HashSet<Short>(), new HashSet<String>());
                // e.getErrorAggregator().add("Test external error", AdmSourceCodeErrorAggregator.Severity.ERROR, e.getModel().getCodeSource());
                break;
            case END:
                System.err.println("CodegenListener END " + e.getModel().getFullName());
                // e.getErrorAggregator().add("Test external error", AdmSourceCodeErrorAggregator.Severity.ERROR, e.getModel().getCodeSource());
                break;
        }
    }
    private void validateFieldIdsUnique(AdmModel model, AdmSourceCodeErrorAggregator aggregator, Set<Short> fields, Set<String> modelsProcessed) {
        // iterate imports and run validation for them if not already run. We will run bottom -> top validation so we assume that imported models have correct
        // field ids and the importing model doesn't if it defines the same id as in one of the imports.
        for (AdmModelImport modelImport : model.getModelImports()) {
            if (!modelsProcessed.contains(modelImport.getModel().getFullName())) {
                validateFieldIdsUnique(modelImport.getModel(), aggregator, fields, modelsProcessed);
                modelsProcessed.add(modelImport.getModel().getFullName());
            }
        }
        // now we check fields of current model
        for (AdmField field : model.getFields()) {
            if (fields.contains(field.getId())) {
                // aggregator collects errors and they will be displayed at the end of code generation.
                aggregator.add("Duplicate field id",
                               AdmSourceCodeErrorAggregator.Severity.ERROR,
                               field.getCodeSource(), null);
                // note that classes derived from AdmModelElement
                // usually have source code (error line) information retrieved through getCodeSource()
                // pointing back to place in XML where their XML representation is.
            }
            else {
                fields.add(field.getId());
            }
        }
    }
}

 In pom.xml we may use this listener as follows:

Code Block
languagexml
titleSample usage in pom.xml
        <plugins>
            <!-- Generates X model from XML model file -->
            <plugin>
                <groupId>com.neeve</groupId>
                <artifactId>nvx-core-maven-plugin</artifactId>
                <version>${project.version}</version>
                <executions>
                    <execution>
                        <id>Model</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <!-- The usual configuration params go here ... -->
 
							<!-- The listener class that should be on the build classpath for this project -->
                            <codegenListenerClassName>mypackage.CodegenListener</codegenListenerClassName>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>