Closest Matching NameToken Algo

Recently worked on a GWT app. This app has a components laid out in a hierarchy. A Primary Page has a set of Tabs. Each Tab has a primary Section listing primary objects and a secondary section listing contents for the selected primary object. Also each tab has a command bar to which commands can be contributed. Since this is a GWT app, every section here is a GWT Presenter widget.


The requirement here was to be able to contribute commands in one or more sections mentioned above using wildcards in a GIN module. And in the code for the given section, we should be able to retrieve commands contributed for that section.

Here was my  solution to this problem :

Every Presenter is assigned a unique ID (let say PresenterContext) based on where its contributed. E.g.
"Inbox:_:SignOff:_:SecondaryWorkArea" signifies a presenter in Inbox (Primary Page) > SignOff (Tab) > SecondaryWorkArea.

Commands are contributed in GIN module using such presenter context IDs. And same command can be contributed to multiple Presenter Contexts. Here are different examples of Contributions for a command :



private String m_contributions[] = new String[] { "", 
            "Inbox", 
            "Inbox:_:PrimaryWorkArea", 
            "Inbox:_:SecondaryWorkArea", 
            "Inbox:_:SecondaryWorkArea:_:SignOff", 
            "Inbox:_:SignOff:_:PrimaryWorkArea", 
            "Inbox:_:SignOff:_:SecondaryWorkArea", 
            "Inbox:_:SignOff", 
            "Inbox:_:MyTasks", 
            "Inbox:_:MyTasks:_:SignOff",  
            "Inbox:_:MyTasks:_:SecondaryWorkArea", 
            "Inbox:_:MyTasks:_:SecondaryWorkArea:_:SignOff", 
            "PrimaryWorkArea", 
            "SecondaryWorkArea", 
            "SecondaryWorkArea:_:SignOff",  
            "SignOff", 
            "ShowObject:_:SecondaryWorkArea:_:Attachments"  
    };
And here is a test method with desired output :
    @Test
    public void testGetClosestMatchingContext()
    {
        String input = "Inbox:_:AllTasks:_:SecondaryWorkArea:_:Attachments"; 
        String matchingContribution = .getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "Inbox:_:SecondaryWorkArea", matchingContribution ); 

        input = "Inbox:_:AllTasks:_:SignOff"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "Inbox:_:SignOff", matchingContribution ); 

        input = "MyTasks:_:SecondaryWorkArea:_:SignOff"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "SecondaryWorkArea:_:SignOff", matchingContribution ); 

        input = "AllTasks:_:SecondaryWorkArea:_:SignOff"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "SecondaryWorkArea:_:SignOff", matchingContribution ); 

        input = "Inbox:_:AllTasks:_:SecondaryWorkArea:_:SignOff"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "Inbox:_:SecondaryWorkArea:_:SignOff", matchingContribution ); 

        input = "ShowObject:_:Attachements"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertNull( matchingContribution );

        input = "ShowObject:_:PrimaryWorkArea:_:Attachements"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "PrimaryWorkArea", matchingContribution ); 

        input = "ShowObject:_:SignOff"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "SignOff", matchingContribution ); 

        input = "ShowObject:_:SecondaryWorkArea:_:SignOff"; 
        matchingContribution = getClosestMatchingContext( input, m_contributions );
        Assert.assertEquals( "SecondaryWorkArea:_:SignOff", matchingContribution ); 
    }
Here is the Algo to get closest matching context for an input presenter context:
   
    public String getClosestMatchingContext( String targetContext, String[] contributedContextIDs )
    {
        String tokens[] = split( targetContext );
        String[] lastMatch = contributedContextIDs;
        String result = null;

        int index = 0;

        for( String token : tokens )
        {
            String[] currentMatch = startingWithToken( token, lastMatch, index );
            if( currentMatch != null && currentMatch.length > 0 )
            {
                String match = endingWithToken( token, currentMatch );
                if( match != null )
                {
                    result = match;
                }
                if( result != null )
                {
                    lastMatch = currentMatch;
                    index++;
                }
            }
        }

        return result;
    }

    /**
     * Splits the context id into separate tokens
     * 
     * @param contextID presenter context ID
     * @return array of tokens
     */
    private String[] split( String contextID )
    {
        String[] tokens = contextID.split( IPresenterContext.ID_SEPARATOR );
        if( tokens == null )
        {
            tokens = new String[0];
        }
        return tokens;

    }

    /**
     * Finds the contributions that end with given token
     * 
     * @param token context token
     * @param contributions contributed context IDs
     * @return closest matching context contribution for the specified token, else null is returned.
     */
    private String endingWithToken( String token, String[] contributions )
    {
        assert token != null;
        assert contributions != null;

        String tokenWithSperator = IPresenterContext.ID_SEPARATOR + token;

        for( String contribution : contributions )
        {
            if( contribution.equals( token ) || contribution.endsWith( tokenWithSperator ) )
            {
                return contribution;
            }
        }

        return null;
    }

    /**
     * Finds the contributions that start with specified token.
     * 
     * @param iToken input token
     * @param contributions context contributions
     * @param index index in the specified contributions array to search for in the contributions array
     * @return contributions starting with specified token, else an empty Array is returned.
     */
    private String[] startingWithToken( String iToken, String[] contributions, int index )
    {
        assert iToken != null;
        assert contributions != null;
        assert index >= 0;

        List<String> matches = new ArrayList<>();
        for( String contribution : contributions )
        {
            String[] tokens = split( contribution );
            if( tokens.length > index && tokens[index].equals( iToken ) )
            {
                matches.add( contribution );
            }
        }
        return matches.toArray( new String[0] );
    }

JNA : Get window handle at mouse cusor position


    public static final int POINT_Y(long i)
    {
        return (int) (i  >> 32);
    }
    
    public static final int POINT_X(long i)
    {
        return (int) (i & 0xFFFF);
    }

    public interface User32Ex extends W32APIOptions 
    {  
     User32Ex instance = (User32Ex) Native.loadLibrary("user32", User32Ex.class, DEFAULT_OPTIONS);  
     boolean GetCursorPos(long[] lpPoint); //use macros POINT_X() and POINT_Y() on long lpPoint[0]
        HWND WindowFromPoint(long point);
    }

    long[] getPos = new long [1];
    User32Ex.instance.GetCursorPos(getPos);
    HWND hwnd = User32Ex.instance.WindowFromPoint(getPos[0]);


https://groups.google.com/forum/#!topic/jna-users/jVSfNCHMQ-M

Scrum.. make sure you get it right

http://scrumtrainingseries.com/DailyScrumMeeting/DailyScrumMeeting.htm

http://scrumtrainingseries.com/

export/ copy maven project with its dependencies

Command to export a maven plugin with its dependencies
cd to maven project / module with pom.xml
and simple run
mvn org.apache.maven.plugins:maven-dependency-plugin:2.8:copy-dependencies

under target/dependency copies all the dependency jars

Character Encoding : JSON, Java

http://stackoverflow.com/questions/17487058/how-to-solve-json-parse-bad-control-character-in-string-literal-in-this-code


GWT's JSONParser.parseStrict() doesn;'t allow control and private for use characters. So if you have input fields in your form where you take input form the user and parse it using JSON parser, make sure that you check for invalid chars as  below :

if(Character.isISOControl( c ) || c >= 0xE000 && c <= 0xF8FF ))
    //flag error


For java apps, you can use java.nio.charset.CharsetEncoder class to check if input stinrg is valid for your encoding.. use CharsetEncoder.canEncode() method.

Wanna Test Natives from Java ?

For quite a few years I have been working on an application which is native UI (written in C++) embedded in Eclipse SWT / Swing panels / composites. While I wrote some JUnit Tests for the GUI automation using SWTBot, I could not write test cases for native UI dialogs since SWTBot doesn't support for Windows Native UI components.

While looking for some open source library / framework for the same.. I came across a nice white paper by some VMWare guy which solved my problem :
http://istabg.org/adding-capabilities-for-windows-native-gui-to-your-test-automation-framework-based-on-java/

All you need is couple of JNA libraries and a handful of classes in the white paper.