This document is just the beginning of what should become a complete reference to the DML language. Currently, it contains only a few elements (the new ones that I'm adding to the language). * Entity type names ** package declarations Using the keyword "package" it is possible to define a common prefix for all the entity-type names that appear after that declaration. After a package declaration such as package some.qualified.id; all the _relative_ entity type names will be prefixed with "some.qualified.id.". For instance, the following class declarations are interpreted as shown (assuming no previous package declaration): class name; => class some.qualified.id.name; class another.name; => class some.qualified.id.another.name; A package declaration remains in effect until another package declaration is found. An empty package declaration is written as: package; and its effect is to make all the following entity type names as absolute. ** absolute entity type names When a package declaration is in effect, it is still possible to use an _absolute_ entity-type name, by starting the name with a ".". The name of the entity-type, however, will not have the dot, as shown below: package foo; class bar; => class foo.bar; class baz.quux; => class foo.baz.quux; class .abs.name; => class abs.name; * value types The slots of an entity type must always be of a certain value-type. But, even though there are a few value-types built into the DML, typically, each domain model will use a different set of value-types. So, in the DML it is possible to declare new value-types (only the declaration that the type exists, rather than its definition, which is, at least for now, out of the scope of the DML). There are two possible value-type declarations: one for enums and another one for other kinds of value-types. In the first case, the externalization of the values of the value-type are handled automatically by the DML compiler. In the latter case, it must be specified in the value-type declaration how should the values of that type be externalized. The syntax for enums is the following: enum value-type-fully-qualified-name [ as alias-identifier ] ; The syntax for non-enum value-types, however, is this: valueType value-type-fully-qualified-name [ as alias-identifier ] { [ ] } where must be present and has the following form: externalizeWith { valueType1 methodName1(); valueType2 methodName2(); ... } For ease of reference in the text that follows, we will call each of the "valueType methodName();" declarations that appears within the externalization-clause block delimited by braces an "externalization element". The value-type of an externalization element must have been previously declared as a valid value-type (and, therefore, it cannot be the same value-type of the current value-type declaration). Note, also, that this restriction prevents cycles in the externalization relations. The semantics of an externalization-clause for a value-type VT is that a value of VT should be externalized as a series of one or more values of other (more primitive) value-types, in the order specified by the externalization elements within the externalization-clause. Each externalization element describes the type of one of those values and what method should be called to get the externalization value. The current code generator assumes that if the method name of an externalization element contains a dot, then it is a static method with a single argument type assignable to a value of the value-type VT. Otherwise, it is a no-argument method of the class implementing the value-type. Unlike the , the is optional. If no is specified, a value is reconstructed by calling the constructor of the value-type with the values corresponding to the external representation of the value, in the same order as they were specified in the . If, however, an is specified, it must have the following form: internalizeWith methodName(); In this case, the method called "methodName" should be used to reconstruct a value of the value-type VT. For instance, to externalize a java.math.BigDecimal as a String we may use this: valueType java.math.BigDecimal { externalizeWith { String toString(); } } because the java.math.BigDecimal.toString() method creates an external representation of the BigDecimal that may be used to reconstruct the BigDecimal value again with new BigDecimal(external-representation-as-string) If, on the other hand, we have a class that has no pair getter/constructor that allows us to do this, such as the java.util.Currency class, but that has a static method that allows us to reconstruct a value of the class, then we may write it like this: valueType java.util.Currency { externalizeWith { String toString(); } internalizeWith getInstance(); } Also, besides these simple cases where a given value is externalized as another single value, it is possible to have value-types that may be externalized as more than one value. For instance, consider the case of a Money value-type that represents a given amount on some currency. If the amount and currency are sufficient to completely describe a value of Money, and assuming the appropriate methods and constructor on the Money class, we may use this in the DML specification: valueType Money { externalizeWith { long getAmount(); Currency getCurrency(); } } Finally, if a given value-type is implemented by a class that does not provide either a method to create an external representation of it, nor a method to reconstruct it from the external representation, we may still create static methods in some other class and use those methods in the externalization and internalization clauses. For instance, assume that we want to externalize a Money as a String in the form "amount currency", and that there is no appropriate methods in class Money. The skeleton of a possible solution is the following: class MoneyExternalization { public static String moneyAsString(Money money) { return String.valueOf(money.getAmount()) + " " + money.getCurrency().toString(); } public static Money moneyFromString(String moneyExtRep) { String[] parts = moneyExtRep.split(" ", 2); long amount = Long.parseLong(parts[0]); Currency currency = Currency.getInstance(parts[1]); return new Money(amount, currency); } } valueType Money { externalizeWith { String MoneyExternalization.moneyAsString(); } internalizeWith MoneyExternalization.moneyFromString(); } ** parametric value-types It is possible to use parametric value-types in the DML, both when declaring that a value-type exists (in a value-type declaration), and when specifying the properties of an entity-type. For instance, given a value-type declaration such as this: valueType my.package.MyType as MyType { ... } it is possible to use this in an entity-type declaration as shown below: class MyEntity { MyType prop1; } It is also possible, though, to declare the parametric type in the value-type declaration: valueType my.package.MyType as MyType { ... } and then use it like this: class MyEntity { MyType prop1; } The result in this case will be the same as above. This is useful when MyType is most often used with the type parameters A and B, even if in some cases it may be changed. For instance, given the last declaration for MyType, it is still possible to use like this: class MyEntity { MyType prop1; MyType prop2; MyType> prop3; } The Java class generated for MyEntity will have three properties, prop1 to prop3, with the following types: - my.package.MyType - my.package.MyType - my.package.MyType>