Skip to content

Introduction Cartridge Developers

Dr. Jawa edited this page Feb 24, 2015 · 44 revisions

You are a Cartridge Developer if...

  • You have seen a lot of boiler plate codes in your application which can be optimized by generating them.
  • You want to have a strict control of your application architecture (== you are the software architect of the application).
  • You want to offer other application developers the power of Model Driven Software Development so that they can model using UML2 and generate, e.g Java codes, XML files, etc.

What are your steps to create a cartrige for KissMDA?

  • You create a Maven project based on KissMDA Cartridge Maven archetype: kissmda-maven-cartridge-archetype
  • You need to learn how to use UML2 and JDT frameworks for Eclipse and other Java frameworks for generating stuffs you want to generate:
    • UML2 API for working with the UML2 file.
    • JDT for creating Java source codes.
    • JAXB or Java DOM API or Java StAX API for creating XML files.
  • Of course you can use template engines such as Apache Velocity or FreeMarker to create files you may need but you need to integrate those frameworks by yourself in your own cartridge.
  • You need to know what functionalities we already offer from our kissmda-core component so you can reuse them.
  • You need to design your UML profile. This is the "language" of your own. Based on this profile you will design your transformator (== the code that reads your UML model and generates some stuffs (Java class, XML files, etc.) based on your UML profile).
  • Don't forget to unit test and integration test your cartridge's codes. For this purpose you need to build a UML model which uses the UML profile as if you were an application developer.
  • That's it.
  • Important to remember:
    • Use Java as much as you can, do not use DSL or what so ever those hype scripting languages.
    • Keep the cartridge as simple as you can, structure and refactor them wisely, use Dependency Injection framework like Guice or SpringFramework.
    • Always unit and integration test!

Do we have an example of a cartridge which powered by KissMDA?

Simple Cartridge "kissmda-cartridges-simple-java"

Thia simple cartridge just create a Java Interface out of Entities. Here is a short description of this cartridge: Readme file of the cartridge. Let's take a fast look at our Seven Steps Down to Earth!

(1) We need a Maven project

Yes, this is the first step we need to make and here is an example Maven catrjdge project: kissmda-cartridges-simple-java. To create a new Maven cartridge project we can use the Maven archetype: kissmda-maven-cartridge-archetype.

(2) Implement the Transformer Interface

Here is an example of a Java class which implements the Transformer Interface: SimpleJavaTransformer.java

public class SimpleJavaTransformer implements Transformer {
	private static final String STEREOTYPE_ENTITY = "Entity";
	private static final String STEREOTYPE_SOURCEDIRECTORY = "SourceDirectory";
	private String sourceDirectoryPackageName;
	@Inject
	private PackageHelper packageHelper;
	@Inject
	private FileWriter fileWriter;
	@Inject
	private InterfaceGenerator interfaceGenerator;
	private Context context;

	@Override
	public void transform(Context context) throws TransformerException {
		this.context = context;
		try {
                        // Do something to transform from UML2 to Java, XML, or what so ever
			...
		} catch (URISyntaxException e) {
			throw new TransformerException(e);
		} catch (IOException e) {
			throw new TransformerException(e);
		}
	}
...

(3) Get the "Root" UML package and iterate through all the elements which have Stereotypes we defined before

...
			// Get the root package
			org.eclipse.uml2.uml.Package outPackage = getRootPackage(context);
			sourceDirectoryPackageName = "";

			// Check the stereotype of the root package
			checkStereotypeRootPackage(outPackage);

			// Get all elements with defined stereotypes
			EList<Element> list = outPackage.allOwnedElements();
			for (Element element : list) {
				EList<Stereotype> stereotypes = element.getAppliedStereotypes();
				for (Stereotype stereotype : stereotypes) {
					if (stereotype.getName().equals(STEREOTYPE_SOURCEDIRECTORY)) {
						// From this SourceDirectory we can work...
						org.eclipse.uml2.uml.Package packagez =
                                                     (org.eclipse.uml2.uml.Package) element;
						sourceDirectoryPackageName = packagez.getName();
						logger.info("SourceDirectory package name: "
								+ sourceDirectoryPackageName);
					}
					if (stereotype.getName().equals(STEREOTYPE_ENTITY)) {
						// Stereotype Interface
						Class clazz = (Class) element;
						logger.info("Class: " + clazz.getName() + " - "
								+ "Stereotype: " + stereotype.getName());
						// Generate the interface for this class
						String compilationUnit = interfaceGenerator
								.generateInterface(clazz,
										sourceDirectoryPackageName);
						generateClassFile(clazz, compilationUnit);
					}
				}
			}
...

(4) Create Java, XML with JDT, DOM, all in Java

Here is an example creating a Java method with JDT: InterfaceGenerator.java

...
	@SuppressWarnings("unchecked")
	public TypeDeclaration generateClass(Class clazz, AST ast,
			CompilationUnit cu) {
		String className = getClassName(clazz);
		TypeDeclaration td = ast.newTypeDeclaration();
		td.setInterface(true);
		td.modifiers().add(
				ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
		td.setName(ast.newSimpleName(className));
		cu.types().add(td);
		return td;
	}
...

(5) Unit test every single classes we write

Here is an example of a JUnit test class: InterfaceGeneratorTest.java

...
	@SuppressWarnings("unchecked")
	public void testGenerateClass() {
		Class clazz = mock(Class.class);
		when(clazz.getQualifiedName()).thenReturn(
				"Data::de::crowdcode::kissmda::testapp::components::Company");
		when(clazz.getName()).thenReturn("Company");

		EList<Association> associations = new UniqueEList<Association>();
		when(clazz.getAssociations()).thenReturn(associations);

		EList<Interface> interfaces = new UniqueEList<Interface>();
		when(clazz.getImplementedInterfaces()).thenReturn(interfaces);

		AST ast = AST.newAST(AST.JLS3);
		CompilationUnit cu = ast.newCompilationUnit();
		TypeDeclaration td = ast.newTypeDeclaration();
		td.setInterface(true);
		td.modifiers().add(
				ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
		td.setName(ast.newSimpleName("Company"));

		interfaceGenerator.generateClass(clazz, ast, cu);

		assertTrue(td != null);
	}
...

(6) Generate the output file as we need them

...
        private void generateClassFile(Class clazz, String compilationUnit)
			throws IOException {
		String fullPackageName = packageHelper.getFullPackageName(clazz,
				sourceDirectoryPackageName);
		fileWriter.createFile(context, fullPackageName, clazz.getName(),
				compilationUnit);
	}
...

(7) Enjoy your coffee and the nice generated Java classes, XML files or all other artefacts!

Yes, this is the reality: you only work with the best code editor ever: Java code editor with Eclipse or IntelliJ!