Friday, April 27, 2012

Samsung Note autocorrect typing

Depending on your settings, when you are typing a word, the phone replaces the word while you type. How do you ignore that and type what you really want? The autocorrect typing on Samsung Note is not documented well, afaik.

It is easy. Just keep typing, the word you are really typing will be shown below as the first option even though the phone is showing what it thinks you really want. Click the word you definitely did want in the list of suggested words. You have to have "Touch to correct words" setting turned on.

I'm sure there is a better way to explain this.

Voice Input is very powerful. The phone understands my wife. But, when I try it the result is always: "Huh? W r u saying?" Just kidding.

Thursday, March 29, 2012

Run Groovy from Ant's script task?

There is a minor lack of documentation regarding the Ant script task and running scripts using Groovy. On the Ant manual page for the "script" task, it says you can run something like this snippet:
<project>

  <target name="run">
   <script language="groovy">
    println "Hello world!"
   </script>
  </target>

</project>

It won't work. You'll get "Unable to create javax script engine for groovy".
So then you read further about library dependencies, but no real example of how to get it to work. This is the lack I'm writing about. No examples.

You have to include the groovy library jars or the single embeddable, groovy-all-x.x.x.jar.

So, to run the above script you would do something like:

ant -lib \java\GroovyVersions\Groovy-1.8.6\embeddable\groovy-all-1.8.6.jar run

Buildfile: C:\temp\build.xml

run:

[script] Hello world!

BUILD SUCCESSFUL

Total time: 0 seconds

Or modify the classpath, or use Ant's lib extension capability. Of course, why would you use the 'script' task when the 'groovy' task is available? You wouldn't.

Further Reading

Ant script task

Groovy Ant task

Sunday, August 14, 2011

Ant InputHandler GUI Using Groovy

Intro

With Apache Ant you can get input from the user using the "input" task. When you run Ant in a console window, the DefaultInputHandler is used. This handler just uses the console's error and input streams. When you run Ant in a graphical IDE, a Graphical User Interface based input handler may be used. This handler will use the graphics toolkit (on Eclipse that would SWT) to pop up dialog boxes.

GUI in console? Can you use GUI input dialogs when running in a command shell? Yes, and it is very easy. First you create an InputHandler subclass that will be used with the Ant command option "-inputhandler <class>".

GUI InputHandler subclass

Below in listing 1, there is example Groovy source: AntGuiInputHandler.groovy

Much harder is actually getting Ant to use this handler.

Build file

First lets create an Ant build file that will get some input:

<project name="AntGui" default="all" basedir=".">
<target name="all">

    <input message="What is your name?"       addproperty="got.response"/>  
    <echo>${got.response}</echo>  
</target>

</project>
Compiling
Now, compile the Groovy source as follows: 
groovyc AntGuiInputHandler.groovy
Running There are many ways to actually run the Ant build. The simplest but not the best way is to set up your CLASSPATH and then run Ant as usual, for example:

C:\temp\AntGui>set classpath=.;\java\groovy\embeddable\groovy-all-1.8.1.jar

C:\temp\AntGui>ant -inputhandler AntGuiInputHandler Buildfile: C:\temp\AntGui\build.xml

all: [input] prompt=What is your name? [input] Josef [echo] Josef from Groovy InputHandler

BUILD SUCCESSFUL Total time: 11 seconds

C:\temp\AntGui>ant -inputhandler AntGuiInputHandler Buildfile: C:\temp\AntGui\build.xml

all: [input] prompt=What is your name? [input] Josef [echo] Josef from Groovy InputHandler

BUILD SUCCESSFUL Total time: 5 minutes 35 seconds

The resulting input dialog is: image
import java.awt.event.WindowEvent
import javax.swing.ActionPropertyChangeListener;

import groovy.swing.SwingBuilder;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.input.InputHandler;
import org.apache.tools.ant.input.InputRequest;
import org.apache.tools.ant.input.MultipleChoiceInputRequest;

import javax.swing.*


/**
* @author jbetancourt
*
*/
class AntGuiInputHandler implements InputHandler {

   /* (non-Javadoc)
    * @see org.apache.tools.ant.input.InputHandler#handleInput(org.apache.tools.ant.input.InputRequest)
    */
   @Override
   public void handleInput(InputRequest request) throws BuildException {
       def response = ''
       println "prompt=${request.getPrompt()}"
     
       if(request instanceof org.apache.tools.ant.input.MultipleChoiceInputRequest){
           response =     getMultipleChoiceInput(request)
       }else{
           response = getTextInput(request)
       }
     
       println response
       request.setInput("${response} from Groovy InputHandler");
   }
 
   String getTextInput(InputRequest request){
       def swingBuilder = new SwingBuilder()
       def response = ''
       def prompt = request.getPrompt()
       response = JOptionPane.showInputDialog(null, 'Dialog',prompt, 
          JOptionPane.OK_OPTION)

       return response  
     
   }
 
 
   String getMultipleChoiceInput(InputRequest request){
       def swingBuilder = new SwingBuilder()
       def req = (MultipleChoiceInputRequest)request;
     
       def choices = req.getChoices()
       def defaultValue = req.getDefaultValue()      
       def prompt = request.getPrompt()
     
       def pane = swingBuilder.optionPane(message:prompt, 
           selectionValues:choices as Object[], 
           optionType:JOptionPane.CLOSED_OPTION)
       def dialog = pane.createDialog(null, 'dialog')
       dialog.show()
     
       def response = pane.getInputValue()
     
       println "input: ${response}"      
     
       return response
   }

   static main(args) {
       def swing = new SwingBuilder()
       def frame = swing.frame(title:'Dialog'){
           panel {
               textField(id:'message',columns:25)
               button(text:'ok',actionPerformed:{ println swing.message.text })
           }
       }
       frame.pack()
       frame.setVisible(true)
   }
}

Pretty groovy use of Groovy!

Wednesday, November 03, 2010

Cascading Configuration Pattern

Synopsis

Load configuration files in cascade to reduce duplicate data.

Keywords: SCM, CM, Properties, Groovy, Config, CSS

Content: Context, Forces, Solution, Consequences, Implementation, Code Example, Related Patterns, Related Intellectual Property, Further Reading

Context

A business system uses property (configuration) files to configure particular environments or subsystems. Many environments share the same properties and values, however, some are different and crucial. To avoid missing any properties, all the properties are duplicated in each file, and required differences are changed appropriately.

For example, if there are 100 properties required and there are 23 possible environments, that is 2300 lines of source to manage. If there are any duplicated properties that do not vary between environments, then there is an opportunity to simplify the configuration system. In this case, if we make only a "root" file have the full set of properties, the total size is given by: T = L+npL; where T is total size, n is number of files, and p is percent of each file that is overridden. Here the value is 560=100+23*.2*100). The reduction over the duplicated data is 75%.

Forces

There are many issues with having the same properties in multiple locations. One obvious disadvantage, is adding a new property would require changing multiple files. Also the files are larger and not really cohesive. Tracking errors is also complicated, especially run-time errors due to configuration settings. Any solution should not add its own complexity. Thus, we should not require new types of configuration files and requirements.

Even when configuration could be isolated or systems modularized, there may be a need to have duplicated properties or reassignment to satisfy software development life cycle (SDLC). A system will be different in dev, test, and production environments.

Solution

A hierarchy of property sources and a system that can load each source and override properties at a prior level will provide a partial solution. This is the approach already taken in many systems. For example, in software applications and servers, the final properties used are composed of those taken from various standard locations in a particular Operating System host. In Windows for example, the Environment Variables are composed of those found in System and User name space. In software tools, such as Mercurial DVCS, there is a command to show the results of the final configuration after all configuration sources are loaded: showconfig show combined config settings from all hgrc files

Many build systems such as Ant and Maven, allow and expect the cascading of property files. Note that in Ant, the inverse policy is used, the first property assignment wins.

And, of course, this cascading is seen in the Cascading Style Sheet (CSS) technology.

Consequences

There is now the requirement that the cascade order is well known, non-variable, and robust. Any intervening file must be loaded, else the system may destabilize. Adding a new property or changing a property will require extra care since an environment or subsystem may be effected if the file contents are not properly designed beforehand.

To provide management and debugging support the implementation should provide traceability of configuration. Thus, during use, the system must report (log) what was overridden, not changed, what is missing, etc.

Implementation

Using this pattern is very easy. One just has to determine how the system handles reassignment in the configuration loader subsystem. If it allows resetting then the file hierarchy is from global to specific.

Where complexity may come is when one wants to satisfy more sophisticated requirements. For example, a property may need to be appended. In OS paths, for instance, paths are combined to create the final path. Thus, the operations on properties could be a combination of:

  • create: initial assignment of a property
  • update: a new value is assigned
  • delete: the property is removed
  • append: append to existing value
  • merge: use a pattern to merge a new value
  • locked: allow no change
  • fail on replace: if a value already assigned throw an exception.

Code Example

In Java the java.util.Properties class will overwrite an existing property with the same key value. Thus, to cascade properties, one just reuses the same instantiated Properties Object via the various load(...) methods.

Shown in listing one is a simple implementation written in Groovy, a dynamic language on the JVM. The PropCascade class extends Properties and adds methods to load a list of sources. The first source in the list is the root of the "cascade". In addition, a few methods explicitly specify the root source. From a traceability point of view, reusing java.util.Properties class may not be optimal. It gives no access to low level capture of the actual "put" action. Even with the use AOP, there is no joinpoint available to add it.

[sourcecode language="groovy"]
/**
* File: CascadedProperties.groovy
* Date: 23OCT10T18:13-05
* Author: JBetancourt
*/

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

/**
* An extension of Properties that adds Convenience
* methods to load lists of sources.
*
* @author jbetancourt
*/
class CascadedProperties extends Properties {
 //private Properties rootProperties = new Properties();
 //private boolean firstWins = true;
 //private boolean failOnDuplicate = false;
 //private boolean isTrace = false;

 /**
  * Load a list of properties sources.
  * @param list
  */
 public void load(List list) throws IOException, IllegalArgumentException {
  list.each {
   load(it)
  }
 }

 /**
  * Explicit file path is specified.
  * @param path
  */
 public void load(String path) throws IOException, IllegalArgumentException {
  load(new File(path).newInputStream());
 }

 /**
  * A load method that explicitly specifies the "default" source in
  * the cascade order.
  *
  * @param inStream
  * @param list
  */
 public void load(InputStream inStream, List list) throws IOException, IllegalArgumentException {
  load inStream
  load list
 }

 /**
  * A load method that explicitly specifies the "default" source in
  * the cascade order.
  *
  * @param reader
  * @param list
  */
 public void load(Reader reader, List list) throws IOException, IllegalArgumentException {
  load reader
  load list
 }

 /**
  * A load method that explicitly specifies the "default" source in
  * the cascade order.
  *
  * @param path
  * @param list
  */
 public void load(String path, List list) throws IOException, IllegalArgumentException {
  load path
  load list
 }

} // end of CascadedProperties
[/sourcecode]

In listing two, the JUnit test class is shown.

[sourcecode language="groovy"]
/**
* File: CascadedPropertiesTest.groovy
* Date: 23OCT10T18:13-05
* Author: JBetancourt
*/

import java.io.File;
import java.io.FileInputStream;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import groovy.util.GroovyTestCase;

/**
* Test the {@link CascadedProperties} class.
*/
class CascadedPropertiesTest extends GroovyTestCase{
 private CascadedProperties cp;

 /** excuted before each test method run */
 public void setUp() throws Exception {
  cp = new CascadedProperties();
 }

 public void testloadListPaths() throws Exception {
  List list = new ArrayList();
  list.add path1
  list.add path2

  cp.load(list);

  assertEquals("v2",cp.get("k1"));
 }

 public void testloadListReaders() throws Exception {
  List list = new ArrayList();
  list.add reader1
  list.add reader2

  cp.load(list);

  assertEquals("v2",cp.get("k1"));
 }

 public void testloadListStreams() throws Exception {
  List list = new ArrayList();
  list.add iStream1
  list.add iStream2

  cp.load(list);

  assertEquals("v2",cp.get("k1"));
 }

 public void testloadStreamAndListStreams() throws Exception {
  List list = new ArrayList();
  list.add iStream2
  list.add iStream3

  cp.load(iStream1,list);

  assertEquals("v3",cp.get("k1"));
 }

 public void testloadPathAndListStreams() throws Exception {
  List list = new ArrayList();
  list.add iStream2
  list.add iStream3

  cp.load("data\\file1.properties",list);

  assertEquals("v3",cp.get("k1"));
 }

 public void testloadReaderAndListStreams() throws Exception {
  List list = new ArrayList();
  list.add reader2
  list.add reader3

  cp.load(reader1,list);

  assertEquals("v3",cp.get("k1"));
 }

 public void testPutAgain() {
  cp.put("k1", "v1")
  cp.put("k1", "v2")
  assertEquals(cp.get("k1"), "v2");
 }

 public void testLoadOneFilePath() throws Exception {
  cp.load("data\\file1.properties");
  assertEquals("v1",cp.get("k1"));
 }

 public void testLoadTwoFiles() throws Exception {
  cp.load(iStream1)
  cp.load(iStream2)

  assertEquals("v2",cp.get("k1"));
 }

 //
 // class fields
 //
 String path1 = "data\\file1.properties"
 String path2 = "data\\file2.properties"
 String path3 = "data\\file3.properties"
 File file1 = new File(path1)
 File file2 = new File(path2)
 File file3 = new File(path3)

 InputStream iStream1 = file1.newInputStream()
 InputStream iStream2 = file2.newInputStream()
 InputStream iStream3 = file3.newInputStream()
 Reader reader1 = file1.newReader()
 Reader reader2 = file2.newReader()
 Reader reader3 = file3.newReader()

}
[/sourcecode]

Related Patterns

Related Intellectual Property

"Cascading configuration using one or more configuration trees", U.S. Patent number 7760746, 30Nov2004, http://patft.uspto.gov/netacgi/nph-Parser?Sect2=PTO1&Sect2=HITOFF&p=1&u=%2Fnetahtml%2FPTO%2Fsearch-bool.html&r=1&f=G&l=50&d=PALL&RefSrch=yes&Query=PN%2F7760746

Further Reading

Wednesday, May 06, 2009

Ubuntu 9.04 on Dell Inspiron 1100 laptop

So, I tried to load Linux on an old Dell Inspiron 1100 laptop at home. This time Ubuntu 9.04, code name "Jaunty Jackalope" worked. It was actually easy. Well, have not tackled getting the Wireless card working yet. Ubuntu looks great and fast considering how underpowered the laptop. That fan is too loud!!!! One nice touch is I can control the Ubuntu laptop from my Windows XP laptop by using Synergy. I just move the mouse across monitors and the same mouse and keyboard are used on the other laptop. That is sweet. Would I recommend Ubuntu? If pre-installed, sure. Also, one must be very computer savy if one must install and configure the system. For example, I thought I knew how to set up the network manually, but it did not work. Found out I had to set the 'route' too. None of the self-help forums I visited mentioned that. Another example, I installed the Google Toolbar on FireFox 3.0.10 and it worked fine. Then the toolbar stopped working. No clue what happened; reinstall of toolbar did not fix it. I can type a search string in the search box, hit enter and nothing happens, though I still get the dropdown list too. I also can't click on options to change toolbar settings. Update 2011JAN23: I just tried to install Ubuntu on this laptop again. No luck yet. Ubuntu Release 9.04 (jaunty) Kernel Linux 2.6.28-11-generic GNOME 2.26.1 Hardware Memory: 496.0 MiB Processor: Intel(R) Celeron CPU 2.00GHz System Status Available disk space: 13.7 GiB I already installed a few things on it. Synergy FTP server PersonalBrain Mercurial etckeeper KeePassX Now the wireless card. I'm dreading this.......

Sunday, February 22, 2009

A missing feature in Facebook I finally succumbed and got my own Facebook account. The result was great (in regards to family matters). However, there is one thing I don't like about Facebook, you only have one presence or persona. Lets say you want to use your actual name and a real profile (like I'm not tall, handsome, and a genius), but I also like to segregate my personal from my business "friends". As far as I know, besides creating a bogus account, I can't do that in Facebook. My whole family now becomes accessible to people who really don't have any business asking my family members for friendship (in the Facebook way). There is a simple solution to this. Let people create aspects. These are personalities or concerns that one can use to reduce overlap. Thus, I can create a professional aspect and a family aspect, and these can have their own lists. Further, one can control what profile information or other content is shared by each aspect. This could conceivably even allow Facebook to encroach on LinkedIn social network. Ok, Facebook, if you use this you owe me, or at least offer me a job. I'm not handsome or a genuis, but am good looking and creative.

Friday, February 20, 2009

The incredible headache of filing taxes

So I went to file a tax return online. I see that they offer the Free e-filer program. I click some links and am confronted by a warning page that I will be sent to an external company site. Wait a minute that sounds weird. Let me try again. I go the page where I can pick a company or have the site recommend a company. First I look at some of the company names. They look like those that appear on spam lists. Now I'm thinking why would a company offer a free service like this? Is it to collect info, altruistic, product sales, spyware, and so forth. Am I being too careful? Anyway, I filled out a paper form available as a PDF file and think this is not good; there should be a modern way of doing this. So I try the http://www.irs.gov/app/freeFile/jsp/wizard.jsp?ck link to get a recommendation. I fill out the form, hit submit and get: That is too funny. I think I'll stick to paper for now.