Pages

Sunday, June 22, 2014

XQCodeGen- An automated XQuery code generator


Why automated code generation ?           

- Code generation is often little more than copy and paste programming.

- An automatic code generation tool always helps developers in all programming languages to get the standard template before writing actual code.  

- This standard template will have basic code standards already defined in the generated files.

- It helps developers to follow the already given standards in their future development.
               
*****************************************************************************                                                     

1 Overview


Problem statement:

For XQuery programming language we do not have such kind of tool that produces the standard template for development.

Solution:
For automated code generation I have designed “XQCodeGen” tool.

Features:

  • Reduce the time spent in writing the code which is repetitive. For example: If developer is working in MVC then he has to design  model and controller code every-time a new feature is added. 
  • XQCodeGen is very easy to use, it can be easily configured on developer machine.
  • XQCodeGen can be easily integrated ant script.
  • XQCodeGen takes XML as an input to generate the template so, developers can easily configure the tool as per their need.
  • If developer will not provide the custom configuration, XQCodeGen will generate the code using its built-in rule-sets.
  • Using XQCodeGen developers can generate MVC (Model, View & Controller) code template for XQuery.
  • Generated MVC can be directly deployed into MarkLogic app server without any modification in url-rewriter and front controller.
  • Using XQCodeGen developers can generate XQuery library modules and main modules.
  • Developers can edit the generated template and add their business logics to the generated templates and can deploy to MarkLogic app server.
 \
2- Using this tool:

1- Modify the config xml (codegenmapping.xml) as per your requirement. Note, do not change the element names.

2- If you want to generate the code for a generic MVC then make the "enabled" attribute of MVC element to true.

3- If you want to get url-rewrter with main controller the make the "enabled" attribute of optional element to true.

4- If you want to generate the main module and library module then make the "enabled" attribute of main-module and lib-module element to true.

5- If you want to disable any of the code generation logic for MVC/library module/main module, you can do it by just putting the value of 'enabled' attribute to 'false'.

Console based UI:


















Config XML:


GUI:

1- Open “XQCodeGen.exe”


2- Select the target output directory and configuration XML file.



3- Click on “Generate Code”, to generate the code



4- Open the target directory to view the generated code.




3Important instructions about MVC.

·         All controller xquery files should go inside the controller directory as mapped in mapping xml file.
·        All model xquery files should go inside the model directory as mapped in mapping xml file.
·         All view xquery files should go inside the view directory; you can also keep views inside a separate        directory for specific components (or with name of controller).
 In this case you need to modify the view-resolver code little bit to append directory name in the uri.
            Line of code needs to be modified in the above case is:
            let $view-uri := fn:concat("/view/",$controller,"/",$controller,"-",$view,".xqy")
            This will create an uri as given below.
            For example:
if controller is 'test-controller' then views can be kept inside /view/test/test-default.xqy


Naming convention for namespaces in model, view and controller XQuery files:-

Follow the naming conventions as given below while mapping the namespaces in mapping config xml file, which will be passed to the tool to generate the code.

1.      In model XQuery file namespace should have 'model' followed by the model name and file name should be same as model name given in namespace.

For example:
            ModelName: test.xqy [file name containing the same name as model name in namespace]
            Then Namespace: http://www.example.com/model/test

2.      In view XQuery file namespace should have 'view' followed by the view name and file  name should be same as view name given in namespace.

            For example:
ViewName: test-default.xqy
 [file name containing the same name as view name in namespace]
 Then Namespace: http://www.example.com/view/test/default
   
             ViewName: test-custom.xqy
  [file name containing the same name as view name in namespace]
              Then Namespace: http://www.example.com/view/test/custom

[Note: default and custom in the view namespace denotes the type of view such as tree view, custom view , abstract view etc.]
   
3.      In controller XQuery file namespace should have 'controller' followed by the controller name and file  name should be same as controller name given in namespace.

  For example:
  ControllerName: test-controller.xqy
  [file name containing the same name as controller name in namespace]
  Then Namespace: http://www.example.com/controller/test


4.      Namespace URI before '/model/','/view/' and '/controller/' should be unique

 For example: 'http://www.example.com' is unique for model,view and controller URIs.
  
 model-- http://www.example.com/model/test
   
 view-- http://www.example.com/view/test/xxxx
 [Note: xxxx in the view namespace denotes the type of view i.e tree view, custom view ,    abstract view. Framework will generate view with 'viewname/default']
   
 controller-- http://www.example.com/controller/test

Follow the naming conventions as given below while mapping the module-names in mapping config xml file, which will be passed to the tool to generate the code.


1.      Controller name should always ends with "-controller.xqy"
             For example: test-controller.xqy
  
2.      If want to handle binary data in the request, then controller name should ends with "-binary-controller.xqy"
            For example: test-binary-controller.xqy
  
3.      Model name could be any name. But name should tell that, which module it belongs to.
   
            For example:
            Modelname: test.xqy
[Here, name 'test' saying that it belongs to test related module where controller name is test-controller and view is test-default]
   
4.      All view xqy files should ends with a type of view
For example: test-default.xqy

Here, -default in the view namespace denotes the type of view such as tree view, custom    view , abstract view etc. Framework will generate view as 'viewname-default.xqy'


4- Using the generated MVC:

 
Suppose you have generated the MVC based on the above given example.

1.      Let say your controller name is: test-controller.xqy and having method as get($params as element(uit:params)).
2.      Let say your model name is: test.xqy and having method as get($id as xs:unsignedLong)
3.      Let say your view name is: test-default.xqy

         So, to send the request to above controller follow the given naming convention.
  
         Your REST url should have controller name followed by the method you want to access.
   
         For example:
           
         http://localhost:8080/test/get?id=1254
           
Here, 'test' is the name of controller and 'get' is the name of the controller you want to access.
           
            It will return the default view i.e whatever written in test-default.xqy
If you want to fetch an specific view then for that a view should already be present. You need to pass the parameter as view=viewname
           
            To call a specific view:
            http://localhost:8080/test/get?id=1254&view=custom
            It will return the custom view i.e whatever written in test-custom.xqy
    
       
Method written inside the 'test-controller' will intern call the model. After the processing the request from the model view will be invoked.
       
For example:
       
 (:sample method in controller:)
declare function get($params as element(uit:params)) as element() {
    (:Calls the model:)             
    get($params/uit:id); (:Method declared in model, as given below which accepts Id as param:)
};
   
  (:sample method in model:)
 declare function get($id as xs:unsignedLong) as element() {
     (:Do something:)
 };
   
           
 (:View sample code:)
           
 declare namespace test-default="http://www.example.com/view/test/default";

declare variable $response-to-process as element() external;
declare variable $view as xs:string external;
           
  try{
     (:TODO-Process the view as required:)
    <default-view>{$response-to-process}</default-view>
} catch ($excp){
xdmp:log(fn:concat("VIEW-EXCEPTION: Exception occurred in view : ",$view," , Returning the original response!"),"error"),
            xdmp:log($excp,"error"),
    $response-to-process

}

2 comments: