This documentation is a work in progress. If you have any questions or notice any features not documented and need to know about them, contact us, and we will respond and add to the documentation here.
Run SetupMetadrone.exe and follow the steps. The core application and all supported plugins are installed.
The application can run as a standalone executable. There are no dependant dll’s, except for the plugins.
The executable file size is small enough to be included with source code as a resource. Used this way, you may create a code generation script (such as a batch file) which can be automated (see command-line-usage).
The application currently has no configuration options.
Plugins only need to be copied into the same directory as the application executable. Any DLL’s located in the same directory as the executable are scanned and loaded at start-up if they are a valid Metadrone plugin.
View command line options. The output is sent to the console.
metadrone /?
Open a project on start-up.
metadrone "c:\dev\app1\codegen\classes.mdrone"
The IDE won’t be shown. A project file will be opened, code is generated, and the application exits. Output is sent to the console.
metadrone /build "c:\dev\app1\codegen\classes.mdrone"
To log the build output to a file. If the file does not exist a new one is created, otherwise the output is just appended to the existing file.
metadrone /build "c:\dev\app1\codegen\classes.mdrone" /log "c:\dev\app1\codegen\genoutput.txt"
A project is one single file in XML format. A project will have multiple file items, but they are serialised into a single XML format. Therefore the application is required to edit a project.
Future plans will enable a more traditional format of having multiple independent files, of which the project can be exported into the current XML format.
A source defines a connection to a model and the meta data to retrieve from that model. Models themselves would contain a full specification, but the connection can filter out the appropriate meta data – or retrieve its entirety.
Templates then connect to the source and can iterate through model components exposed by that source.
Model providers are implementations of specific meta data sources (such as different database systems). Each provider would have its own particular quirks, but for database providers there are four components.
Connection
Basically the connection string to the database.
Tables/Views Meta Data
This is meta data for tables and views. There are two ways to retrieve it (under the radio button selection group “approach”) although some providers may restrict the user to only one of these:
Routines Meta Data
This is for stored procedures and functions. SQL queries are the only known way to retrieve them. The result set returned in a single data set in order of stored procedures/functions and corresponding parameters with their information(type, size, precision, etc). Any select routines returning a dataset will have the column meta data retrieved internally without user specification. The .NET framework has support for this.
Templates can execute .Net code. The source is in managed code files supporting either Visual Basic or C Sharp. Code files are brought together and compiled into an individual assembly. One assembly for VB code, and a separate assembly for C# code.
This is possible via .Net codeDOM.
The language’s main goal is text output. Therefore many programming principles do not apply. For more sophisticated programming needs, managed .Net code can be executed within the script (see runcs or runvb).
Processing is much like ASP or PHP scripting where plain text is direct output and any text within tags is code used for controlling the logic.
Eg. This sample code looping through tables and columns within each table:
<<!for table tbl in sources.source1!>>
SELECT
<<!for column col in tbl!>>
<<!col!>>,
<<!end!>>
FROM <<!tbl!>>
<<!end!>>
can return this output:
SELECT
FirstName,
LastName,
Address1,
Address2,
FROM Customer
The plain text outside of the <<! tags !>> are output as it is; ‘SELECT’, ‘FROM’, the comma, each appropriate line-feed.
Any text preceded with a double forward slash “//” on a line are ignored by the compiler. There is no support for multi-line commenting (such as a /* comment like this */).
Statements are separated by a newline. To have more than one statement on a line, each statement can be separated by a semicolon “;”.
Variables are declared by using the set keyword. There is no explicit typing, variable types are determined dynamically. Additionally there are no classes, enumerations, etc. The system types provided are:
There are no function calls, however templates can be treated as functions and are run by using call.
There is a simple variable scope concept, without any object oriented information hiding principles deliberately being used. There are no access modifiers such as public, private, friend, etc. Three different kinds of references have this behaviour.
In Main, text preceded by a hash “#” symbol indicates a directive. Directives apply to the scope of the package. This includes processing of transformations from within that package. Directives cannot be specified in templates.
Specifies case sensitivity for string comparisons. The switch is either “on” or “off. If not specified the default is “on”.
Eg:
#ignorecase on //String comparisons are not case sensitive.
#ignorecase off //String comparisons are case sensitive.
Specify safe zone identifiers.
Eg:
#safebegin = "// safe begin" #safeend = "// safe end"
Template headers are defined using a header block containing specifiers for three main template behaviours:
header is [template_name](argument,list) [for_statement] return [output_expression] end
Eg, for a single file output writing to the file “the-output.txt”:
header is Template1 return "the-output.txt" end
The template can be called thus:
call template1
For multiple outputs:
(note the use of the for iterator variable in the return expression).
header is Template2(connection) for table tbl in connection return "the-output-" + tbl + ".txt" end
The template is called and parameter is passed:
call Template2(sources.Source1)
Execute a template by calling it. There is no return value; templates output generated code to a file.
call [template_name](argument,list)
Eg:
call template1 call template2(tablevar,colvar)
Output a string. Out will output a string expression. Outln will output a string expression followed by a new line.
out(arg1)
outln(arg1)
Eg:
<<! out("text value") outln(1 + 2) !>>
The out function is actually unnecessary since an expression will resolve to a string output. However it is supplied for completeness and can assist with code readability in some situations.
Output a string to the debug console. Cout will output a string expression. Coutln will output a string expression followed by a new line.
cout(arg1)
coutln(arg1)
Eg:
<<! coutln("current table is" + tbl) !>>
Clears the debug console.
clcon()
Eg:
<<!clcon!>>
Create a directory. Relative paths are valid.
Directories are not created in preview mode.
makedir(arg1)
Eg:
makedir("create\directory") makedir("c:\create\rooted\directory")
Copy a file. Relative paths are valid.
Files are not copied in preview mode.
filecopy(arg1, arg2)
Eg:
filecopy("source.txt", "..\dest.txt") filecopy("c:\source.txt", "c:\dest.txt")
Execute a command line operation.
Not executed in preview mode.
command(arg1, arg2)
Eg:
command("cmd", "/c delete c:\dev\file.txt") command("c:\dev\postbuild.bat", "")
Execute C Sharp code. The source is located independently and compiled when the project is built. The function is typically referenced with the appropriate namespace and class qualifications.
runcs(arg1)
Eg:
runcs("namespace.class.method(args,etc)") runcs("CS.MyClass.DoThis(123, ""myargval"")")
Execute Visual Basic code. The source is located independently and compiled when the project is built. The function is typically referenced with the appropriate namespace and class qualifications.
runvb(arg1)
Eg:
runvb("namespace.class.method(args,etc)") runvb("VB.MyClass.DoThis(123, ""myargval"")")
Execute script file against a connection source. This will typically be a SQL query.
runscript(arg1, arg2)
Eg:
runscript(sources.source1, "script.sql")
Convert expression to numeric.
This is useful for mathematical expressions where you want to avoid string concatenation if a variable’s type is a string.
cnum(arg1)
Eg:
coutln(cnum("1") + 2)
Sine maths function.
sin(arg1)
Eg:
sin(90)
Cosine maths function.
cos(arg1)
Eg:
cos(180)
Tangent maths function.
tan(arg1)
Eg:
tan(45)
Square root maths function.
sqrt(arg1)
Eg:
sqrt(64)
To avoid having customisations overwritten by regeneration, content can be preserved within safe zones.
For example here is some sample generated code:
public double Seconds { get { return _Seconds; } set { _Seconds = value; } } public string Location { get { return _Location; } set { _Location = value; } }
Defining safe zone identifiers in main:
#safebegin = "//safe start" #safeend = "//safe end"
And then in the generated output file, add customisations within safe zones:
public double Seconds { get { return _Seconds; } set { _Seconds = value; } } //safe start public double Hours { get { return Seconds / 3600; } set { Seconds = value * 3600; } } public double Minutes { get { return Seconds / 60; } set { Seconds = value * 60; } } public double Minutes { get { return Seconds; } set { Seconds = value; } } //safe end public string Location { get { return _Location; } set { _Location = value; } }
When the code is regenerated, content inside the safe zones are not overwritten.