Kushal Likhi « Intelligrape Groovy & Grails Blogs
Subscribe via E-Mail:

kushal

http://kushal.likhi.me

Posts by kushal:

  • JavaScript: Hex String To Int64 conversion (similar to Int64.parse)

    30 Dec 2012 in Grails

    Recently in our Node.js application we had a task where we needed to convert the Windows hexadecimal Live Id (lid) to sighed 64 bit Integer such that it can be used in the API calls. But there was no direct way to convert that in JavaScript, but here i will discuss the workaround we took.

     

    The problem with 64 bit Integer in JavaScript

    Though javaScript numbers are 64 bit but they only use 53 bits to store the real value(mantissa), rest bits are used for exponent. Hence this makes holding of 64bit integer impossible in JavaScript.

     

    The workaround Solution

    The workaround is to use String/Arrays to hold large numbers and perform arithmetic operations on that. The final result has to be saved in a string as we can never save it as number data type. I know it is dirty, but that’s the only way.

     

    Example: Converting hex windows live id to Integer Live Id (Signed 64bit Integer)

    Following code will convert the received hex lid to intLid:

    var lidHex = "b4fb0acfc47086c1"; //The Input Hex Number.
    var lid64 = new HexStringToInt64StringConverter(true).convert(lidHex);  //"true" is passed for Signed Conversion.
    console.log(lid64); // output: -5405715040257931583
    

    Note: Implementation of HexStringToInt64StringConverter is discussed below.

     

    Example: Converting hex number to Integer (Unsigned 64bit Integer)

    Following code will convert the received hex lid to intLid:

    var intHex = "b4fb0acfc47086c1"; //The Input Hex Number.
    var int64 = new HexStringToInt64StringConverter(false).convert(intHex);  //"false" is passed for UnSigned Conversion.
    console.log(int64); // output: 13041029033451620033
    

    Note: Implementation of HexStringToInt64StringConverter is discussed below.

     

    Implementation: HexStringToInt64StringConverter

    This converter is implemented with following points in mind:

    1. 2′s Complement Signed Representation
    2. Number represented in Array for arithmetic manipulations.
    3. All Powers of 2 which are impossible to calculate in JavaScript are pre-calculated and hard coded for faster conversions.
    4. Output number to be represented as a string.
    5. Both signed and unsigned conversions.

     

    function HexStringToInt64StringConverter(signed) {
        var hexCode = {
            '0':"0000",
            '1':"0001",
            '2':"0010",
            '3':"0011",
            '4':"0100",
            '5':"0101",
            '6':"0110",
            '7':"0111",
            '8':"1000",
            '9':"1001",
            'a':"1010",
            'b':"1011",
            'c':"1100",
            'd':"1101",
            'e':"1110",
            'f':"1111"
        };
        var preComputedLongMath = {
            "20":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
            "21":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
            "22":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4],
            "23":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8],
            "24":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6],
            "25":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2],
            "26":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4],
            "27":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 8],
            "28":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 6],
            "29":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 2],
            "210":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 4],
            "211":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 8],
            "212":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 9, 6],
            "213":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 9, 2],
            "214":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 3, 8, 4],
            "215":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 7, 6, 8],
            "216":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 3, 6],
            "217":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 7, 2],
            "218":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 2, 1, 4, 4],
            "219":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 4, 2, 8, 8],
            "220":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 8, 5, 7, 6],
            "221":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 9, 7, 1, 5, 2],
            "222":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 9, 4, 3, 0, 4],
            "223":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 3, 8, 8, 6, 0, 8],
            "224":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 7, 7, 7, 2, 1, 6],
            "225":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 5, 5, 4, 4, 3, 2],
            "226":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 1, 0, 8, 8, 6, 4],
            "227":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 4, 2, 1, 7, 7, 2, 8],
            "228":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 8, 4, 3, 5, 4, 5, 6],
            "229":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 6, 8, 7, 0, 9, 1, 2],
            "230":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 3, 7, 4, 1, 8, 2, 4],
            "231":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 4, 7, 4, 8, 3, 6, 4, 8],
            "232":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 9, 4, 9, 6, 7, 2, 9, 6],
            "233":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 5, 8, 9, 9, 3, 4, 5, 9, 2],
            "234":[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 1, 7, 9, 8, 6, 9, 1, 8, 4],
            "235":[0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 3, 5, 9, 7, 3, 8, 3, 6, 8],
            "236":[0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 7, 1, 9, 4, 7, 6, 7, 3, 6],
            "237":[0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 4, 3, 8, 9, 5, 3, 4, 7, 2],
            "238":[0, 0, 0, 0, 0, 0, 0, 0, 2, 7, 4, 8, 7, 7, 9, 0, 6, 9, 4, 4],
            "239":[0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 9, 7, 5, 5, 8, 1, 3, 8, 8, 8],
            "240":[0, 0, 0, 0, 0, 0, 0, 1, 0, 9, 9, 5, 1, 1, 6, 2, 7, 7, 7, 6],
            "241":[0, 0, 0, 0, 0, 0, 0, 2, 1, 9, 9, 0, 2, 3, 2, 5, 5, 5, 5, 2],
            "242":[0, 0, 0, 0, 0, 0, 0, 4, 3, 9, 8, 0, 4, 6, 5, 1, 1, 1, 0, 4],
            "243":[0, 0, 0, 0, 0, 0, 0, 8, 7, 9, 6, 0, 9, 3, 0, 2, 2, 2, 0, 8],
            "244":[0, 0, 0, 0, 0, 0, 1, 7, 5, 9, 2, 1, 8, 6, 0, 4, 4, 4, 1, 6],
            "245":[0, 0, 0, 0, 0, 0, 3, 5, 1, 8, 4, 3, 7, 2, 0, 8, 8, 8, 3, 2],
            "246":[0, 0, 0, 0, 0, 0, 7, 0, 3, 6, 8, 7, 4, 4, 1, 7, 7, 6, 6, 4],
            "247":[0, 0, 0, 0, 0, 1, 4, 0, 7, 3, 7, 4, 8, 8, 3, 5, 5, 3, 2, 8],
            "248":[0, 0, 0, 0, 0, 2, 8, 1, 4, 7, 4, 9, 7, 6, 7, 1, 0, 6, 5, 6],
            "249":[0, 0, 0, 0, 0, 5, 6, 2, 9, 4, 9, 9, 5, 3, 4, 2, 1, 3, 1, 2],
            "250":[0, 0, 0, 0, 1, 1, 2, 5, 8, 9, 9, 9, 0, 6, 8, 4, 2, 6, 2, 4],
            "251":[0, 0, 0, 0, 2, 2, 5, 1, 7, 9, 9, 8, 1, 3, 6, 8, 5, 2, 4, 8],
            "252":[0, 0, 0, 0, 4, 5, 0, 3, 5, 9, 9, 6, 2, 7, 3, 7, 0, 4, 9, 6],
            "253":[0, 0, 0, 0, 9, 0, 0, 7, 1, 9, 9, 2, 5, 4, 7, 4, 0, 9, 9, 2],
            "254":[0, 0, 0, 1, 8, 0, 1, 4, 3, 9, 8, 5, 0, 9, 4, 8, 1, 9, 8, 4],
            "255":[0, 0, 0, 3, 6, 0, 2, 8, 7, 9, 7, 0, 1, 8, 9, 6, 3, 9, 6, 8],
            "256":[0, 0, 0, 7, 2, 0, 5, 7, 5, 9, 4, 0, 3, 7, 9, 2, 7, 9, 3, 6],
            "257":[0, 0, 1, 4, 4, 1, 1, 5, 1, 8, 8, 0, 7, 5, 8, 5, 5, 8, 7, 2],
            "258":[0, 0, 2, 8, 8, 2, 3, 0, 3, 7, 6, 1, 5, 1, 7, 1, 1, 7, 4, 4],
            "259":[0, 0, 5, 7, 6, 4, 6, 0, 7, 5, 2, 3, 0, 3, 4, 2, 3, 4, 8, 8],
            "260":[0, 1, 1, 5, 2, 9, 2, 1, 5, 0, 4, 6, 0, 6, 8, 4, 6, 9, 7, 6],
            "261":[0, 2, 3, 0, 5, 8, 4, 3, 0, 0, 9, 2, 1, 3, 6, 9, 3, 9, 5, 2],
            "262":[0, 4, 6, 1, 1, 6, 8, 6, 0, 1, 8, 4, 2, 7, 3, 8, 7, 9, 0, 4],
            "263":[0, 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8],
            "264":[1, 8, 4, 4, 6, 7, 4, 4, 0, 7, 3, 7, 0, 9, 5, 5, 1, 6, 1, 6],
            "265":[3, 6, 8, 9, 3, 4, 8, 8, 1, 4, 7, 4, 1, 9, 1, 0, 3, 2, 3, 2]
        };
        if (typeof(signed) != 'boolean') signed = false;
        function toBinary(hex) {
            hex = hex.toLowerCase();
            var binary = "";
            for (var i = 0; i < hex.length; i++) {
                binary += hexCode[hex[i]];
            }
            return binary;
        }
    
        function to1nsComplement(binary) {
            var compliment = "";
            for (var i = 0; i < binary.length; i++) {
                compliment += (binary.charAt(i) == "1" ? "0" : "1");
            }
            return compliment;
        }
    
        function arrayAdd(a, b) {
            var carry = 0;
            var number = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
            for (var i = 19; i >= 0; i--) {
                number[i] = a[i] + b[i] + carry;
                if (number[i].toString().length > 1) {
                    carry = parseInt(number[i].toString().substring(0, number[i].toString().length - 1), 10);
                    number[i] = parseInt(number[i].toString().substring(number[i].toString().length - 1), 10)
                } else {
                    carry = 0;
                }
            }
            return number;
        }
    
        function removeZeroPad(number) {
            var lock = false;
            var output = [];
            for (var i = 0; i < number.length; i++) {
                if (lock) {
                    output.push(number[i]);
                } else {
                    if (number[i] != 0) {
                        lock = true;
                        output.push(number[i]);
                    }
                }
            }
            return output;
        }
    
        function binaryToDec(binary) {
            var negative = false;
            if (signed && (binary.charAt(0) == 1)) {
                negative = true;
            }
            if (signed) {
                binary = binary.substring(1);
                if (negative) {
                    binary = to1nsComplement(binary);
                }
            }
            var pos = 0;
            var number = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
            for (var i = binary.length - 1; i >= 0; i--) {
                if (binary.charAt(i) == 1) {
                    number = arrayAdd(number, preComputedLongMath["2" + pos])
                }
                pos++;
            }
            if (negative) {
                number = removeZeroPad(arrayAdd(number, preComputedLongMath["20"]));
                number.splice(0, 0, "-");
            } else {
                number = removeZeroPad(number);
            }
            return number.join("");
        }
    
        this.convert = function (hex) {
            var binary = toBinary(hex);
            return binaryToDec(binary);
        };
    }
    
    

    Hope it helps!!
    Regards
    Kushal Likhi

  • HTML5 Offline Applications – IndicThreads Conference PPT

    31 Oct 2012 in HTML-UI-CSS

    Hi,

     

    Recently i presented in “IndicThreads 2012″ conference on the topic “HTML 5 Offline Applications”.

     

    You can view the slides at Slideshare at: http://www.slideshare.net/kushallikhi/indic-threads-delhisessionhtml5-offline-applications

     

    Topics which are discussed in this presentation are:

    1. Desktop Vs Web(HTML 4)
    2. Desktop Vs HTML4 Vs HTML5
    3. Why Offline Apps
    4. Why Local Storage of Data
    5. Type Of Caches
    6. The Manifest File (Resources Cache)
    7. Invalidating The Manifest
    8. DOM Events for Offline cache
    9. Debugging
    10. Local Storage vs Session Storage vs WebSQL vs Indexed Storage vs File System

     

    Hope it is useful.
    Regards
    Kushal Likhi

  • Cool way to get/set processed HTML Markup in filters

    27 Sep 2012 in Grails

    Hi,

     

    There was a case where i had to encrypt the HTML output of the GSP before displaying it to user. There are a lot of ways to do it, but i wanted to make is as simple as possible. Hence here is the pattern i used:

     

    Note: This is just an example, you can use this concept to do thousands of cool things, like: pdf export etc..

     

    ON THE GSP

    <html>
    <head>
    <meta name="encrypt" value="true" />   
        ...
    </head>
     .... misc code
    </html>
    

    Here what is did is, i created a GSP and just added a meta property to it saying “encrypt true”.

     

    Now here is the Code for the Grails Filters (See inline comments)

    def filters = {
            all(controller: '*', action: '*') {
                before = {                
                }
                after = { Map model ->
                    try {
                        //Get the Site Mesh Page Instance
                        GSPSitemeshPage sitemeshPage = response?.getContent() as GSPSitemeshPage
                       
                        //Check if it is actual sitemest page, not just plain rendered content
                        if (sitemeshPage && sitemeshPage.getPage()) {
                            //Get the meta property value.
                            String metaPropValue = sitemeshPage.getProperty("meta.encrypt")
                            if (metaPropValue && metaPropValue == "true") {
                                //This is how you can get html contents of head/body after all tags resolved.
                                String head = new String(sitemeshPage.getHead())
                                String body = new String(sitemeshPage.getBody())
    
                                //Buffer for new body
                                StreamCharBuffer writer = new StreamCharBuffer()
                                //Write to buffer new content
                                writer.getWriter().write(encryptionService.encrypt(body))
                                sitemeshPage.setBodyBuffer(writer)
                            }
                        }
                    } catch (Throwable ex) {
                        ex.printStackTrace()
                    }
                }
                afterView = { Exception e ->
    
                }
            }
        }
    

     

    And hence we have this processed content in response :)

     

     

    Regards
    Kushal Likhi

  • Fire Plugin OnChange/onConfigChange Event at Run Time Manually

    26 Sep 2012 in Grails

    Hi,

     

    Suppose you have implemented some logic in your application which updates the Config at runtime.

     

    Now after you have updated the config, you should notify the plugins about configChanges such that they reload their configurations. This can be done by firing the onConfigChange Event of the plugins.

     

    Similarly you can also fire the onChange event of the plugin(s) whenever required.

     

    We can do this via the pluginManager Bean. the Code is As follows:

    //Bean of plugin manager, it can be autowired by name in controllers/services etc. or can be fetched via the ApplicationContext:getBean() method.
    def pluginManager
    def grailsApplication
    
    //We will notify Config change to all plugins
    void notifyConfigChangeToAllPlugins(){
        pluginManager.allPlugins.each {
                it.notifyOfEvent(GrailsPlugin.EVENT_ON_CONFIG_CHANGE, grailsApplication.config) //Second parameter is Source of event, here we have just passed the ConfigObject for simplicity.
        }
    }
    
    

     

    Now, We will fire the event for a particular plugin:

    
    void notifyConfigChangeToPlugin(String name){
        pluginManager.getGrailsPlugin(name).notifyOfEvent(GrailsPlugin.EVENT_ON_CONFIG_CHANGE, grailsApplication.config) //Second parameter is Source of event, here we have just passed the ConfigObject for simplicity.
        }
    }
    
    

     

    Similarly If we want to fire the OnChange event then we can do as follows:

    void notifyOnChangeToAllPlugins(){
        pluginManager.allPlugins.each {
                it.notifyOfEvent(GrailsPlugin.EVENT_ON_CHANGE, myChangedArtifact) //Second parameter is Source of event, here we have just passed the object that has changed in simple terms, and its better if this object is an Artifact, as many plugins call the method .isArtifactOfType on this object as this object is passed in the "event" Map.
        }
    } 
    
    

     

     

    Hope It Helps!!
    Kushal Likhi

  • JavaScript: Currying in JavaScript

    25 Sep 2012 in Javascript/Ajax/JQuery

    Hi,

     

    Currying is a very simple and useful concept in JavaScript. Here we can set the context of the function to any object or variable.

     

    So let us study this concept using the practical examples and code as follows:

    //Let us first create a function "curry"
    function curry(thisObject, func){
        return function(){
              return func.apply(thisObject, arguments);
       };
    }
    
    //Lets make a function in which we have delegated the this arg. Such that this function is executed in the context of some other object.
    var myCurriedFunction = curry("This is a string object, it will be the 'this' object", function(){
        alert(this);
    });
    
    //Now lets call the function:
    myCurriedFunction(); //will alert "This is a string object, it will be the 'this' object"
    
    

     

     

    Hope it Helps!
    Kushal Likhi

  • JavaScript: Replacing Logically using String:replace() method

    25 Sep 2012 in Javascript/Ajax/JQuery

    Hi,

     

    When working with JavaScript, we might sometimes require to run some regEx on a string and replace its matches logically.
    This can be easily done using the String:replace() method.

     

    Lets Take an example to understand the concept: Suppose we want to write a function which converts the normal string to CamelCase String, then it can be implemented as:
    Test Cases

    1. Input: “hello world”, Output: “helloWorld”
    2. Input: “Hello_world”, Output: “helloWorld”

    Now lets write a function to satisfy the above test cases:

    function toCamelCase(string){
       return string.replace( /((\w)[ _](\w))|(^(\w))/g, 
        function( fullMatch,
                     spaceLetterSpace, 
                     letterBeforeSpace, 
                     letterAfterSpace, 
                     startLetterAndCharacter,  
                     firstCharacter) 
        {
            if(typeof spaceLetterSpace != 'undefined') return(letterBeforeSpace + letterAfterSpace.toUpperCase());
        
            if(typeof startLetterAndCharacter != 'undefined') return(firstCharacter.toLowerCase());
    
        })
    }
    

    Here what is happening is, if we pass a function in the second argument of .replace() function, then this function is executed against each match. Each group which is matched is passed in the argument. The first argument is the over all match and the further arguments are the matches corresponding to each group in the regular expression.

     

     

    Hope it Helps!
    Kushal Likhi

  • Inject Methods/Properties to be available in all GSP Pages

    25 Sep 2012 in Grails&Groovy

    Hi,

     

    There could be cases where we would need to inject some methods or properties in all GSP pages.

     

    As we know that the GSP pages extends GroovyPage class, hence injecting properties/methods in GroovyPage class can solve out purpose.

     

    Example: Lets add appVersion property and a method to provide logo link irrespective of the knowledge of containing module.

    //Adding property
    GroovyPage.metaClass.appVersion = "my app Version"
    
    //Adding the method to give the logo link
    GroovyPage.metaClass.logoLink = {
            resource(dir: 'images', file: 'logo.png',plugin: 'my-module-containing-logo')
    }
    

     

    Now in Any GSP in the application we can do:

    <div>
    <img src="${logoLink()}" />
    <p>App Version:- ${appVersion}</p>
    </div>
    
    

     

     

    Hope It Helps!
    Kushal Likhi

  • Dollar-Slashy Strings in Groovy [Ver 1.8+]

    25 Sep 2012 in Grails

    Hi,

     

    Groovy took another leap ahead in the methodology of defining Strings by providing us with “dollar-slashy” strings which further minimized the need of escaping any special character as compared to simple “slashy” Strings.

     

    In the Groovy ver:1.8+ you can define Strings as follows:

    //A dollar-slashy string
    String message = $/Hi! I am Kushal Likhi!/$
    
    println message
    //Output: Hi! I am Kushal Likhi!
    

     

    In the above example we saw that string is defined by using a dollar-Slash combination. The biggest advantage of this combination is that we don’t even have to escape slashes(“/”), which results in a cleaner better code.

     

    Dollar-slashy strings can be best used with regular expressions as it will enable us to write much cleaner regular expressions.
    An example of regular expression to find the protocol of the URL.

    //Using simple slashy strings
    String protocol = "http://www.intelligrape.com".find(/([^\/]+):\/\//){it[1]} 
    assert protocol == "http" //will be true
    
    //Now using dollar slashy Strings we can implement the same functionality by:
    String protocol = "http://www.intelligrape.com".find($/([^/]+):///$){it[1]}
    assert protocol == "http" //will be true
    
    //You can see that we have a much CLEANER RegEx using dollar slashy strings.
    

     

     

    Hope it helps!
    Kushal Likhi

  • GDSL Awesomeness – Setting a global context

    25 Sep 2012 in Grails&Groovy

    Hi,

    Sometimes we need to set the context for the GDSL contributor to all the possible files and scripts in the project scope.
    This is a rare case scenario, but could be handy on some implementations.

     

    This can be done by two techniques:

    1. Ignoring all filters passed to the “context” method.
    2. Setting the “ctype” parameter to “java.lang.Object” class.

     

    It is illustrated as follows:

    //To set the global context
    def globalContext = context() // No need to provide any filters.
    
    //Alternate method
    def globalContext = context(ctype: "java.lang.Object") // Contribute to Object class
    
    

     

    Read Further in the “GDSL AWESOMENESS” Series

    1. GDSL Awesomeness – Introduction to GDSL in IntelliJ Idea
    2. GDSL Awesomeness – Understanding Context And Contributors in Detail
    3. GDSL Awesomeness – Defining dynamic property in a class
    4. GDSL Awesomeness – Defining dynamic method in a class
    5. GDSL Awesomeness – Adding Hinting for missingMethod implementation
    6. GDSL Awesomeness – Setting a global context
    7. GDSL Awesomeness – Delegating Closure Calls
    8. GDSL Awesomeness – Defining methods in a closure passed to method of particular name
    9. GDSL Awesomeness – Defining Properties in a closure passed to method of particular name
    10. GDSL Awesomeness – Contributing to classes which match a path/name pattern
    11. GDSL Awesomeness – contributing methods with current class return types or parameters
    12. GDSL Awesomeness – AutoComplete Script for grails-Mail-Plugin “sendMail” closure
    13. GDSL Awesomeness – Getting Code of a method or Field in GDSL Script
    14. GDSL Awesomeness – Advanced Example showing domain properties implementation

     

    Hope it helps

    Kushal Likhi

  • GDSL Awesomeness – Introduction to GDSL in IntelliJ Idea

    25 Sep 2012 in Grails&Groovy

    Hi,
    One of the disadvantage of using metaprogramming and DSL is that we don’t get auto-completes in Our IDE.
    Hence IntelliJ provided us with an awesome and intelligent toolkit to handle dynamic properties and methods when writing code in groovy.

     

    In IntelliJ IDEA we can write GDSL Files in order to give us the auto-completes(code Completion) on the injected Methods/properties and closures.

     

    Advantages of GDSL files

    1. We can push these files with the code and all the developers in the team will start getting auto-completes for the dynamic code.
    2. Simple to write and understand as they use the groovy DSL format.
    3. These files can be packaged in a jar and all projects using that jar will start getting auto-completes and syntax hinting for the dynamic code.

     

    Illustration

    Image illustrating the auto-completes for the injected code. You can see that there is no property “log” defined in the project, but IDEA is showing syntax-hint for this property.

     

    Where to write GDSL Scripts

    We can create a file with an extension “.gdsl” anywhere in the classpath.
    For an example go to any package in your project src, and right click on it from within the IDE and select new>Groovy Script.
    Now a dialog will appear and then select “GroovyDSL Script” in the “kind” parameter.

    Now you have the script file and you can start coding GDSL in here.

     

    Read Further in the “GDSL AWESOMENESS” Series

    1. GDSL Awesomeness – Introduction to GDSL in IntelliJ Idea
    2. GDSL Awesomeness – Understanding Context And Contributors in Detail
    3. GDSL Awesomeness – Defining dynamic property in a class
    4. GDSL Awesomeness – Defining dynamic method in a class
    5. GDSL Awesomeness – Adding Hinting for missingMethod implementation
    6. GDSL Awesomeness – Setting a global context
    7. GDSL Awesomeness – Delegating Closure Calls
    8. GDSL Awesomeness – Defining methods in a closure passed to method of particular name
    9. GDSL Awesomeness – Defining Properties in a closure passed to method of particular name
    10. GDSL Awesomeness – Contributing to classes which match a path/name pattern
    11. GDSL Awesomeness – contributing methods with current class return types or parameters
    12. GDSL Awesomeness – AutoComplete Script for grails-Mail-Plugin “sendMail” closure
    13. GDSL Awesomeness – Getting Code of a method or Field in GDSL Script
    14. GDSL Awesomeness – Advanced Example showing domain properties implementation

     

     

    Hope It Helped.
    Kushal Likhi