The Source for Java Technology Collaboration
User: Password:



Krishnan Viswanath's Blog

Krishnan Viswanath Krishan Viswanath is currently working for JP Morgan Chase & Co. in Kansas City, MO. He has over 10 years of experience in IT area.



Open Office Java API

Posted by tchangu on December 30, 2005 at 06:20 AM | Permalink | Comments (0)

When I worked for a consulting firm I got an opportunity to work on a Strategy & Operations pursuit. The task was to fill up a 20 page MS Word report template with lots of data from MS Access and Oracle (which was backend to some ERP system). The requirement was to produce 10 or so reports quickly, which showed the client how the firm can help them to define a strategic sourcing model followed by a transformation roadmap.

Not being a fluent VB Scripter, I was totally frustrated trying different things - manually plugging in data, patchy VB Scripting, Apache POI - but nothing worked satisfactorily. Finally after looking around, I ended up discovering OpenOffice UNO Java API (Universal Network Objects). After going through an initial ramp, it worked out pretty good. With OO UNO and JDBC, ugly and complex reporting became a breeze!

Open Office UNO API is pretty involved in concept and is complex as well. Of course it’s pretty powerful and can do much more than what I made use of. However, there is very little general documentation like articles etc available online. But Sun’s Developer's guide and supplied samples is very good. For starters here is some code that helped me going.

First - Read an existing document, and this can be accomplished by
// get the remote office component context
xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
System.out.println("Connected to a running office ...");

// Get the remote office service manager
XMultiComponentFactory xMCF = xContext.getServiceManager();

// Get the root frame (i.e. desktop) of openoffice framework.
Object oDesktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);

// Desktop has 3 interfaces. The XComponentLoader interface provides ability to load
// components.
XComponentLoader xCompLoader = (XComponentLoader)
		UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, oDesktop);

// URL of the component to be loaded
String sUrl = "file:///[file name]";

// Load the document, which will be displayed. More param info in apidoc
XComponent xComp = xCompLoader.loadComponentFromURL(sUrl, "_blank", 0, new PropertyValue[0]);

// Get the textdocument
XTextDocument aTextDocument = (XTextDocument)UnoRuntime.queryInterface(
                  com.sun.star.text.XTextDocument.class, xComp);

Now that we have text document we can manipulate in how ever manner we want. In my particular case, I had to deal with data that were in tables. This was accomplished by
// Query the XTextTablesSupplier interface from our document
XTextTablesSupplier xTablesSupplier = (XTextTablesSupplier) UnoRuntime.queryInterface(
                 XTextTablesSupplier.class, aTextDocument );

// Get the tables collection
XNameAccess xNamedTables = xTablesSupplier.getTextTables();

// Query the XIndexAccess from the tables collection
XIndexAccess xIndexedTables = (XIndexAccess) UnoRuntime.queryInterface(
                 XIndexAccess.class, xNamedTables);

for (int i = 0; i < xIndexedTables.getCount(); i++) {
  Object table = xIndexedTables.getByIndex(i);
  XTextTable xTable = (XTextTable) UnoRuntime.queryInterface(
                  XTextTable.class, table);

  // Getting Table Rows
  XTableRows xRows = xTable.getRows();

  // Getting the right Table Cell (Hard Coded as B2).
   XText xCellText = (XText) UnoRuntime.queryInterface (
                  XText.class, xTable.getCellByName ( "B2" ) );

   // Make JDBC calls. Perform data tranformation and set it
   xCellText.setString("Hello Worlds");
}
The final task after all the transformation has been performed is to save the document.
// URL where the document is to be stored
String storeUrl = "file:///Test_97.rtf";

XStorable xStorable = (XStorable)UnoRuntime.queryInterface(XStorable.class, aTextDocument);
PropertyValue[] storeProps = new PropertyValue[1];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "FilterName";
storeProps[0].Value = "Rich Text Format";

xStorable.storeAsURL(storeUrl, storeProps);
Of course the document could be sent to the printer as well. Here is the code to do that
XPrintable xPrintable = (XPrintable)UnoRuntime.queryInterface(XPrintable.class, aTextDocument);
PropertyValue[] printerDesc = new PropertyValue[1];
printerDesc[0] = new PropertyValue();
printerDesc[0].Name = "Name";
printerDesc[0].Value = "PDFCreator";
xPrintable.setPrinter(printerDesc);

PropertyValue[] printOpts = new PropertyValue[1];
printOpts[0] = new PropertyValue();
printOpts[0].Name = "Pages";
printOpts[0].Value = "1";
xPrintable.print(printOpts);
Enjoy!

Dealing with Command Line Parameters

Posted by tchangu on December 19, 2005 at 09:43 AM | Permalink | Comments (5)

One of the things that keep popping up often is a need to write batch programs that is started from command line. Every single time its always been either reinvent the wheel or copy/paste from old code. So recently decided to put an end to this practice by looking at CLI solution from Apache.


CLI is a really nice utility and could be a potential enterprise reusable component. However while dealing with CLI, one will soon discover the verbosity especially while dealing with OptionBuilder
class. This means we are reverting back to old manner of programming (cut/paste) but in style.

But one could externalize this in a XML by hiding the plumbing of CLI that deals with verbosity. A simple framework around CLI framework would do this trick and this means a developer who wants to use CLI would write this simple XML


<cli-map>
   <cli-parser>org.apache.commons.cli.GnuParser</cli-parser>
   <cli-domain-obj>com.util.cli.domain.CommandObj</cli-domain-obj>
   <help>
    <help-formatter>org.apache.commons.cli.HelpFormatter</help-formatter>
      <print-help>true</print-help>
    <syntax-tip>java com.util.cli.TestDrive blah blah </syntax-tip>
   </help>
   <options>
            <option optName="file"  withArgName="file" 
        hasArgs="true" withDescription="use given file for log" />
            <option optName="logger" withArgName="classname"
        hasArgs="true" withDescription="the class which it to perform logging" />
            <option optName="listener" withArgName="classname"
        hasArgs="true" withDescription="add an instance of class as a project listener" />
            <option optName="buildfile" withArgName="file"
        hasArgs="true" withDescription ="use given buildfile" />
            <option optName="file" withArgName="file"
        hasArgs="true" withDescription="search for buildfile towards the root of the filesystem and use it" />
            <option optName="D" withArgName="property=value" 
    hasArgs="true" withValueSeparator="=" withDescription ="use value for given property" />
    </options>
</cli-map>


The com.util.cli.domain.CommandObj needs to have instance variables that is same as optName. Then, using reflection and XML processing one could do bulk of the CLI plumbing to figure out what the values are. The outcome of this simple exercise - No more need to go through drudgery of writing code to parse command line arguments.
Write a simple XML, create a POJO, and get values populated in the POJO that is needed for the batch program with just three lines of code.


String fileName = "cli-map.xml";
CommandProcessorExt cmdProcessor = new CommandProcessorExt(fileName);
CommandObj obj = (CommandObj)cmdProcessor.process(args);

Better yet, Commons Configuration could be used to implement something similar! too...
Of course if some one is interested in the rudimentary, but working, source code, please feel free to ping!



December 2005
Sun Mon Tue Wed Thu Fri Sat
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31


Search this blog:
  

Archives

December 2005
June 2005

Recent Entries

Open Office Java API

Dealing with Command Line Parameters

Hashmap Implementation

Articles

The New RMI
If you remember RMI from its earliest incarnations, then you understand its usefulness for distributed computing, but maybe not its latest innovations. In this article, Krishnan Viswanath looks at J2SE 5.0's new RMI features, including SSL-based secure RMI, launch-on-demand integration with xinetd, and stubless operation. Oct. 6, 2005

Robotics: Using Lego Mindstorms and Java
In this article we will explore the brain of Lego Mindstorms that will enable us to program the robot to perform the functions we intend. You will look at installing and using the Java-based leJOS firmware. Feb. 21, 2005

All articles by Krishnan Viswanath »



Powered by
Movable Type 3.01D


 XML java.net RSS