AmourSpirit

Lo.java

Jun 15th, 2023 (edited)
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 44.65 KB | Source Code | 0 0
  1. // For Python see https://github.com/Amourspirit/python_ooo_dev_tools
  2. // and, https://github.com/Amourspirit/python_ooo_dev_tools/blob/main/ooodev/utils/inst/lo/lo_inst.py
  3. //
  4. // Lo.java
  5. // Andrew Davison, [email protected], February 2015
  6.  
  7. /* A growing collection of utility functions to make Office
  8.    easier to use. They are currently divided into the following
  9.    groups:
  10.  
  11.      * interface object creation (uses generics)
  12.  
  13.      * office starting
  14.      * office shutdown
  15.  
  16.      * document opening
  17.      * document creation
  18.      * document saving
  19.      * document closing
  20.  
  21.      * initialization via Addon-supplied context
  22.      * initialization via script context
  23.  
  24.      * dispatch
  25.      * UNO cmds
  26.  
  27.      * use Inspectors extension
  28.  
  29.      * color methods
  30.      * other utils
  31.  
  32.      * container manipulation
  33. */
  34.  
  35.  
  36. import java.io.*;
  37. import java.util.*;
  38. import java.net.URLClassLoader;
  39.  
  40.  
  41. import com.sun.star.beans.*;
  42. import com.sun.star.comp.helper.*;
  43. import com.sun.star.frame.*;
  44. import com.sun.star.connection.*;
  45. import com.sun.star.bridge.*;
  46. import com.sun.star.lang.*;
  47. import com.sun.star.uno.*;
  48. import com.sun.star.awt.*;
  49. import com.sun.star.util.*;
  50. import com.sun.star.document.*;
  51.  
  52. import com.sun.star.view.*;
  53. import com.sun.star.container.*;
  54. import com.sun.star.linguistic2.*;
  55.  
  56. import com.sun.star.uno.Exception;
  57. import com.sun.star.io.IOException;
  58.  
  59. import com.sun.star.script.provider.XScriptContext;
  60. import com.sun.star.reflection.*;
  61.  
  62. import com.sun.star.comp.beans.*;
  63.  
  64.  
  65.  
  66.  
  67. public class Lo
  68. {
  69.   // docType ints
  70.   public static final int UNKNOWN = 0;
  71.   public static final int WRITER = 1;
  72.   public static final int BASE = 2;
  73.   public static final int CALC = 3;
  74.   public static final int DRAW = 4;
  75.   public static final int IMPRESS = 5;
  76.   public static final int MATH = 6;
  77.  
  78.   // docType strings
  79.   public static final String UNKNOWN_STR = "unknown";
  80.   public static final String WRITER_STR = "swriter";
  81.   public static final String BASE_STR = "sbase";
  82.   public static final String CALC_STR = "scalc";
  83.   public static final String DRAW_STR = "sdraw";
  84.   public static final String IMPRESS_STR = "simpress";
  85.   public static final String MATH_STR = "smath";
  86.  
  87.   // docType service names
  88.   public static final String UNKNOWN_SERVICE = "com.sun.frame.XModel";
  89.   public static final String WRITER_SERVICE = "com.sun.star.text.TextDocument";
  90.   public static final String BASE_SERVICE = "com.sun.star.sdb.OfficeDatabaseDocument";
  91.   public static final String CALC_SERVICE = "com.sun.star.sheet.SpreadsheetDocument";
  92.   public static final String DRAW_SERVICE = "com.sun.star.drawing.DrawingDocument";
  93.   public static final String IMPRESS_SERVICE = "com.sun.star.presentation.PresentationDocument";
  94.   public static final String MATH_SERVICE = "com.sun.star.formula.FormulaProperties";
  95.  
  96.   // connect to locally running Office via port 8100
  97.   private static final int SOCKET_PORT = 8100;
  98.  
  99.  
  100.   // CLSIDs for Office documents
  101.   // defined in <OFFICE>\officecfg\registry\data\org\openoffice\Office\Embedding.xcu
  102.   public static final String WRITER_CLSID = "8BC6B165-B1B2-4EDD-aa47-dae2ee689dd6";
  103.   public static final String CALC_CLSID = "47BBB4CB-CE4C-4E80-a591-42d9ae74950f";
  104.   public static final String DRAW_CLSID = "4BAB8970-8A3B-45B3-991c-cbeeac6bd5e3";
  105.   public static final String IMPRESS_CLSID = "9176E48A-637A-4D1F-803b-99d9bfac1047";
  106.   public static final String MATH_CLSID = "078B7ABA-54FC-457F-8551-6147e776a997";
  107.   public static final String CHART_CLSID = "12DCAE26-281F-416F-a234-c3086127382e";
  108.  
  109. /* unsure about these:
  110.      chart2 "80243D39-6741-46C5-926E-069164FF87BB"
  111.           service: com.sun.star.chart2.ChartDocument
  112.  
  113.      applet "970B1E81-CF2D-11CF-89CA-008029E4B0B1"
  114.           service: com.sun.star.comp.sfx2.AppletObject
  115.  
  116.      plug-in "4CAA7761-6B8B-11CF-89CA-008029E4B0B1"
  117.            service: com.sun.star.comp.sfx2.PluginObject
  118.  
  119.      frame "1A8A6701-DE58-11CF-89CA-008029E4B0B1"
  120.            service: com.sun.star.comp.sfx2.IFrameObject
  121.  
  122.      XML report chart "D7896D52-B7AF-4820-9DFE-D404D015960F"
  123.            service: com.sun.star.report.ReportDefinition
  124.  
  125. */
  126.  
  127.  
  128.   // remote component context
  129.   private static XComponentContext xcc = null;
  130.  
  131.   // remote desktop UNO service
  132.   private static XDesktop xDesktop = null;
  133.  
  134.   // remote service managers
  135.   private static XMultiComponentFactory mcFactory = null;  
  136.                                    // has replaced XMultiServiceFactory
  137.   private static XMultiServiceFactory msFactory = null;
  138.  
  139.   private static XComponent bridgeComponent = null;
  140.       // this is only set if office is opened via a socket
  141.  
  142.   private static boolean isOfficeTerminated = false;
  143.  
  144.  
  145.  
  146.   public static XComponentContext getContext()
  147.   {  return xcc;  }
  148.  
  149.   public static XDesktop getDesktop()
  150.   {  return xDesktop;  }
  151.  
  152.   public static XMultiComponentFactory getComponentFactory()
  153.   {  return mcFactory;  }
  154.  
  155.   public static XMultiServiceFactory getServiceFactory()
  156.   {  return msFactory;  }
  157.  
  158.   public static XComponent getBridge()
  159.   {  return bridgeComponent;  }
  160.  
  161.  
  162.  
  163.   @SuppressWarnings("deprecation")
  164.   public static void setOOoBean(OOoBean oob)
  165.   // use OOoBean to initialize Lo globals
  166.   {
  167.     try {
  168.       OfficeConnection conn = oob.getOOoConnection();   // OfficeConnection is deprecated
  169.       if (conn == null)
  170.         System.out.println("No office connection found in OOoBean");
  171.       else {
  172.         xcc = conn.getComponentContext();
  173.         if (xcc == null)
  174.           System.out.println("No component context found in OOoBean");
  175.         else
  176.           mcFactory = xcc.getServiceManager();
  177.  
  178.         xDesktop = oob.getOOoDesktop();
  179.         msFactory = oob.getMultiServiceFactory();
  180.       }
  181.     }
  182.     catch (java.lang.Exception e) {
  183.       System.out.println("Couldn't initialize LO using OOoBean: " + e);
  184.     }
  185.   }  // end of setOOoBean()
  186.  
  187.  
  188.  
  189.   // ====== interface object creation (uses generics) ===========
  190.  
  191.   public static <T> T qi(Class<T> aType, Object o)
  192.   // the "Loki" function -- reduces typing
  193.   {  return UnoRuntime.queryInterface(aType, o);  }
  194.  
  195.  
  196.  
  197.   public static <T> T createInstanceMSF(Class<T> aType, String serviceName)
  198.   /* create an interface object of class aType from the named service;
  199.      uses 'old' XMultiServiceFactory, so a document must have already been loaded/created
  200.   */
  201.   {
  202.     if (msFactory == null) {
  203.       System.out.println("No document found");
  204.       return null;
  205.     }
  206.  
  207.     T interfaceObj = null;
  208.     try {
  209.       Object o = msFactory.createInstance(serviceName);     // create service component
  210.       interfaceObj = Lo.qi(aType, o);
  211.            // uses bridge to obtain proxy to remote interface inside service;
  212.            // implements casting across process boundaries
  213.     }
  214.     catch (Exception e) {
  215.       System.out.println("Couldn't create interface for \"" + serviceName + "\": " + e);
  216.     }
  217.     return interfaceObj;
  218.   }  // end of createInstanceMSF()
  219.  
  220.  
  221.  
  222.   public static <T> T createInstanceMSF(Class<T> aType, String serviceName,
  223.                                                              XMultiServiceFactory msf)
  224.   /* create an interface object of class aType from the named service;
  225.      uses 'old' XMultiServiceFactory, so a document must have been already loaded/created
  226.   */
  227.   {
  228.     if (msf == null) {
  229.       System.out.println("No document found");
  230.       return null;
  231.     }
  232.  
  233.     T interfaceObj = null;
  234.     try {
  235.       Object o = msf.createInstance(serviceName);   // create service component
  236.       interfaceObj = Lo.qi(aType, o);
  237.            // uses bridge to obtain proxy to remote interface inside service;
  238.            // implements casting across process boundaries
  239.     }
  240.     catch (Exception e) {
  241.       System.out.println("Couldn't create interface for \"" + serviceName + "\":\n  " + e);
  242.     }
  243.     return interfaceObj;
  244.   }  // end of createInstanceMSF()
  245.  
  246.  
  247.  
  248.   public static <T> T createInstanceMCF(Class<T> aType, String serviceName)
  249.   /* create an interface object of class aType from the named service;
  250.      uses XComponentContext and 'new' XMultiComponentFactory
  251.      so only a bridge to office is needed
  252.   */
  253.   {
  254.     if ((xcc == null) || (mcFactory == null)) {
  255.       System.out.println("No office connection found");
  256.       return null;
  257.     }
  258.  
  259.     T interfaceObj = null;
  260.     try {
  261.       Object o = mcFactory.createInstanceWithContext(serviceName, xcc);    
  262.            // create service component using the specified component context
  263.       interfaceObj = Lo.qi(aType, o);    
  264.            // uses bridge to obtain proxy to remote interface inside service;
  265.            // implements casting across process boundaries
  266.     }
  267.     catch (Exception e) {
  268.       System.out.println("Couldn't create interface for \"" + serviceName + "\": " + e);
  269.     }
  270.     return interfaceObj;
  271.   }  // end of createInstanceMCF()
  272.  
  273.  
  274.  
  275.   public static <T> T createInstanceMCF(Class<T> aType, String serviceName, Object[] args)
  276.   /* create an interface object of class aType from the named service and arguments;
  277.      uses XComponentContext and 'new' XMultiComponentFactory
  278.      so only a bridge to office is needed
  279.   */
  280.   {
  281.     if ((xcc == null) || (mcFactory == null)) {
  282.       System.out.println("No office connection found");
  283.       return null;
  284.     }
  285.  
  286.     T interfaceObj = null;
  287.     try {
  288.       Object o = mcFactory.createInstanceWithArgumentsAndContext(serviceName, args, xcc);    
  289.            // create service component using the specified args and component context
  290.       interfaceObj = Lo.qi(aType, o);    
  291.            // uses bridge to obtain proxy to remote interface inside service;
  292.            // implements casting across process boundaries
  293.     }
  294.     catch (Exception e) {
  295.       System.out.println("Couldn't create interface for \"" + serviceName + "\": " + e);
  296.     }
  297.     return interfaceObj;
  298.   }  // end of createInstanceMCF()
  299.  
  300.  
  301.  
  302.  
  303.  
  304.   public static <T> T getParent(Object aComponent, Class<T> aType)
  305.   // retrieves the parent of the given object
  306.   {
  307.     XChild xAsChild = Lo.qi(XChild.class, aComponent);
  308.     return Lo.qi(aType, xAsChild.getParent());
  309.   }
  310.  
  311.  
  312.  
  313.  
  314.   // ======================== start office ==============
  315.  
  316.  
  317.   public static XComponentLoader loadOffice()
  318.   {  return loadOffice(true);  }    // default is to using office via pipes
  319.  
  320.  
  321.   public static XComponentLoader loadSocketOffice()
  322.   {  return loadOffice(false);  }
  323.  
  324.  
  325.   public static XComponentLoader loadOffice(boolean usingPipes)
  326.   /* Creation sequence: remote component content (xcc) -->
  327.                         remote service manager (mcFactory) -->
  328.                         remote desktop (xDesktop) -->
  329.                         component loader (XComponentLoader)
  330.     Once we have a component loader, we can load a document.
  331.     xcc, mcFactory, and xDesktop are stored as static globals.
  332.   */
  333.   {
  334.     System.out.println("Loading Office...");
  335.     if (usingPipes)
  336.       xcc = bootstrapContext(); // connects to office via pipes
  337.     else
  338.       xcc = socketContext();    // connects to office via a socket
  339.     if (xcc == null) {
  340.       System.out.println("Office context could not be created");
  341.       System.exit(1);
  342.     }
  343.  
  344.     // get the remote office service manager
  345.     mcFactory = xcc.getServiceManager();
  346.     if (mcFactory == null) {
  347.       System.out.println("Office Service Manager is unavailable");
  348.       System.exit(1);
  349.     }
  350.  
  351.     // desktop service handles application windows and documents
  352.     xDesktop = createInstanceMCF(XDesktop.class, "com.sun.star.frame.Desktop");
  353.     if (xDesktop == null) {
  354.       System.out.println("Could not create a desktop service");
  355.       System.exit(1);
  356.     }
  357.  
  358.     // XComponentLoader provides ability to load components
  359.     return Lo.qi(XComponentLoader.class, xDesktop);
  360.   }  // end of loadOffice()
  361.  
  362.  
  363.  
  364.   private static XComponentContext bootstrapContext()
  365.   // connect pipes to office using the Bootstrap class
  366.   // i.e. see code at http://svn.apache.org/repos/asf/openoffice/symphony/trunk/main/
  367.   //                    javaunohelper/com/sun/star/comp/helper/Bootstrap.java
  368.   {
  369.     XComponentContext xcc = null;   // the remote office component context
  370.     try {
  371.       xcc = Bootstrap.bootstrap();  //  get remote office component context
  372.         // Connect to office, if office is not running then it's started
  373.     }
  374.     catch (BootstrapException e) {
  375.       System.out.println("Unable to bootstrap Office");
  376.     }
  377.     return xcc;
  378.   }  // end of bootstrapContext()
  379.  
  380.  
  381.  
  382.   private static XComponentContext socketContext()
  383.   // use socket connection to Office
  384.   // https://forum.openoffice.org/en/forum/viewtopic.php?f=44&t=1014
  385.   {
  386.     XComponentContext xcc = null;   // the remote office component context
  387.     try {
  388.       String[] cmdArray = new String[3];
  389.       cmdArray[0] = "soffice";    
  390.                 // requires soffice to be in Windows PATH env var.
  391.       cmdArray[1] = "-headless";
  392.       cmdArray[2] = "-accept=socket,host=localhost,port=" +
  393.                                                SOCKET_PORT + ";urp;";
  394.       Process p = Runtime.getRuntime().exec(cmdArray);
  395.       if (p != null)
  396.         System.out.println("Office process created");
  397.       delay(5000);
  398.              // Wait 5 seconds, until office is in listening mode
  399.  
  400.       // Create a local Component Context
  401.       XComponentContext localContext =
  402.                         Bootstrap.createInitialComponentContext(null);
  403.  
  404.       // Get the local service manager
  405.       XMultiComponentFactory localFactory = localContext.getServiceManager();
  406.  
  407.       // connect to Office via its socket
  408. /*
  409.       Object urlResolver = localFactory.createInstanceWithContext(
  410.                                   "com.sun.star.bridge.UnoUrlResolver", localContext);
  411.       XUnoUrlResolver xUrlResolver = Lo.qi(XUnoUrlResolver.class, urlResolver);
  412.       Object initObject = xUrlResolver.resolve(
  413.             "uno:socket,host=localhost,port=" + SOCKET_PORT +
  414.                                           ";urp;StarOffice.ServiceManager");
  415. */
  416.       XConnector connector = Lo.qi(XConnector.class,
  417.               localFactory.createInstanceWithContext(
  418.                           "com.sun.star.connection.Connector", localContext));
  419.  
  420.       XConnection connection = connector.connect(
  421.                          "socket,host=localhost,port=" + SOCKET_PORT);
  422.  
  423.       // create a bridge to Office via the socket
  424.       XBridgeFactory bridgeFactory = Lo.qi(XBridgeFactory.class,
  425.                 localFactory.createInstanceWithContext(
  426.                          "com.sun.star.bridge.BridgeFactory", localContext));
  427.  
  428.       // create a nameless bridge with no instance provider
  429.       XBridge bridge = bridgeFactory.createBridge("socketBridgeAD", "urp", connection, null);
  430.  
  431.       bridgeComponent = Lo.qi(XComponent.class, bridge);
  432.  
  433.       // get the remote service manager
  434.       XMultiComponentFactory serviceManager = Lo.qi(XMultiComponentFactory.class,
  435.                                      bridge.getInstance("StarOffice.ServiceManager"));
  436.  
  437.       // retrieve Office's remote component context as a property
  438.       XPropertySet props = Lo.qi(XPropertySet.class, serviceManager);
  439.                                                      // initObject);
  440.       Object defaultContext = props.getPropertyValue("DefaultContext");
  441.  
  442.       // get the remote interface XComponentContext
  443.       xcc = Lo.qi(XComponentContext.class, defaultContext);
  444.     }
  445.     catch (java.lang.Exception e) {
  446.       System.out.println("Unable to socket connect to Office");
  447.     }
  448.  
  449.     return xcc;
  450.   }  // end of socketContext()
  451.  
  452.  
  453.  
  454.   // ================== office shutdown =========================
  455.  
  456.  
  457.   public static void closeOffice()
  458.   // tell office to terminate
  459.   {
  460.     System.out.println("Closing Office");
  461.     if (xDesktop == null) {
  462.       System.out.println("No office connection found");
  463.       return;
  464.     }
  465.  
  466.     if(isOfficeTerminated) {
  467.       System.out.println("Office has already been requested to terminate");
  468.       return;
  469.     }
  470.  
  471.     int numTries = 1;
  472.     while (!isOfficeTerminated && (numTries < 4)) {
  473.       delay(200);
  474.       isOfficeTerminated = tryToTerminate(numTries);
  475.       numTries++;
  476.     }
  477.   }  // end of closeOffice()
  478.  
  479.  
  480.  
  481.   public static boolean tryToTerminate(int numTries)
  482.   {
  483.     try {
  484.       boolean isDead = xDesktop.terminate();
  485.       if (isDead) {
  486.         if (numTries > 1)
  487.           System.out.println(numTries + ". Office terminated");
  488.         else
  489.           System.out.println("Office terminated");
  490.       }
  491.       else
  492.         System.out.println(numTries + ". Office failed to terminate");
  493.       return isDead;
  494.     }
  495.     catch(com.sun.star.lang.DisposedException e)
  496.     {  System.out.println("Office link disposed");  
  497.        return true;
  498.     }
  499.     catch(java.lang.Exception e)
  500.     {  System.out.println("Termination exception: " + e);  
  501.        return false;
  502.     }
  503.   }  // end of tryToTerminate()
  504.  
  505.  
  506.  
  507.   public static void killOffice()
  508.   // kill office processes using a batch file
  509.   // or use JNAUtils.killOffice()
  510.   {
  511.     try {
  512.       Runtime.getRuntime().exec("cmd /c lokill.bat");
  513.       System.out.println("Killed Office");
  514.     }
  515.     catch (java.lang.Exception e) {
  516.       System.out.println("Unable to kill Office: " + e);
  517.     }
  518.   }  // end of killOffice()
  519.  
  520.  
  521.  
  522.   // ======================== document opening ==============
  523.  
  524.  
  525.   public static XComponent openFlatDoc(String fnm, String docType,
  526.                                        XComponentLoader loader)
  527.   { String nm = XML.getFlatFilterName(docType);
  528.     System.out.println("Flat filter Name: " + nm);
  529.     return openDoc(fnm, loader, Props.makeProps("FilterName", nm));
  530.   }
  531.  
  532.  
  533.   public static XComponent openDoc(String fnm, XComponentLoader loader)
  534.   {  return openDoc(fnm, loader, Props.makeProps("Hidden", true) );  }
  535.  
  536.  
  537.   public static XComponent openReadOnlyDoc(String fnm, XComponentLoader loader)
  538.   {  return openDoc(fnm, loader, Props.makeProps("Hidden", true, "ReadOnly", true) );  }
  539.  
  540.  
  541.  
  542.   public static XComponent openDoc(String fnm, XComponentLoader loader,
  543.                                                            PropertyValue[] props)
  544.   // open the specified document
  545.   // the possibly props for a document are listed in the MediaDescriptor service
  546.   {
  547.     if (fnm == null) {
  548.       System.out.println("Filename is null");
  549.       return null;
  550.     }
  551.  
  552.     String openFileURL = null;
  553.     if (!FileIO.isOpenable(fnm)) {
  554.       if (isURL(fnm)) {
  555.         System.out.println("Will treat filename as a URL: \"" + fnm + "\"");
  556.         openFileURL = fnm;
  557.       }
  558.       else
  559.         return null;
  560.     }
  561.     else {
  562.       System.out.println("Opening " + fnm);
  563.       openFileURL = FileIO.fnmToURL(fnm);
  564.       if (openFileURL == null)
  565.        return null;
  566.     }
  567.  
  568.  
  569.     XComponent doc = null;
  570.     try {
  571.       doc = loader.loadComponentFromURL(openFileURL, "_blank", 0, props);
  572.       msFactory =  Lo.qi(XMultiServiceFactory.class, doc);
  573.     }
  574.     catch (Exception e) {
  575.       System.out.println("Unable to open the document");
  576.     }
  577.     return doc;
  578.   }  // end of openDoc()
  579.  
  580.  
  581.  
  582.  
  583.   public static boolean isURL(String fnm)
  584.   {
  585.     try {
  586.       java.net.URL u = new java.net.URL(fnm);   // check for the protocol
  587.       u.toURI();                                // check validation of URI
  588.       return true;
  589.     }
  590.     catch (java.net.MalformedURLException e)
  591.     {  return false;  }
  592.     catch (java.net.URISyntaxException e)
  593.     {  return false;  }
  594.   }  // end of isURL()
  595.  
  596.  
  597.  
  598.  
  599.   // ======================== document creation ==============
  600.  
  601.  
  602.   public static String ext2DocType(String ext)
  603.   {
  604.     switch (ext) {
  605.       case "odt": return WRITER_STR;
  606.       case "odp": return IMPRESS_STR;
  607.       case "odg": return DRAW_STR;
  608.       case "ods": return CALC_STR;
  609.       case "odb": return BASE_STR;
  610.       case "odf": return MATH_STR;
  611.       default:
  612.         System.out.println("Do not recognize extension \"" + ext + "\"; using writer");
  613.         return WRITER_STR;    // could use UNKNOWN_STR
  614.     }
  615.   }  // end of ext2DocType()
  616.  
  617.  
  618. /* docType (without the ""private:factory/") is:
  619.     "private:factory/swriter"       Writer document
  620.     "private:factory/simpress"      Impress presentation document
  621.     "private:factory/sdraw"         Draw document
  622.     "private:factory/scalc"         Calc document
  623.     "private:factory/sdatabase"     Base document
  624.     "private:factory/smath"         Math formula document
  625.  
  626.   These are not handled:
  627.     "private:factory/schart"                    Chart
  628.     "private:factory/swriter/web"               Writer HTML Web document
  629.     "private:factory/swriter/GlobalDocument"    Master document
  630.      
  631.     ".component:Bibliography/View1"       Bibliography-Edit the bibliography entries
  632.      
  633.     ".component:DB/QueryDesign"           Database comp
  634.     ".component:DB/TableDesign"
  635.     ".component:DB/RelationDesign"
  636.     ".component:DB/DataSourceBrowser"
  637.     ".component:DB/FormGridView"
  638. */
  639.  
  640.  
  641.   public static String docTypeStr(int docTypeVal)
  642.   {
  643.     switch (docTypeVal) {
  644.       case WRITER: return WRITER_STR;
  645.       case IMPRESS: return IMPRESS_STR;
  646.       case DRAW: return DRAW_STR;
  647.       case CALC: return CALC_STR;
  648.       case BASE: return BASE_STR;
  649.       case MATH: return MATH_STR;
  650.       default:
  651.         System.out.println("Do not recognize extension \"" + docTypeVal + "\"; using writer");
  652.         return WRITER_STR;    // could use UNKNOWN_STR
  653.     }
  654.   }  // end of docTypeStr()
  655.  
  656.  
  657.  
  658.   public static XComponent createDoc(String docType, XComponentLoader loader)
  659.   {  return createDoc(docType, loader, Props.makeProps("Hidden", true) );  }
  660.  
  661.  
  662.   public static XComponent createMacroDoc(String docType, XComponentLoader loader)
  663.   {  return createDoc(docType, loader, Props.makeProps("Hidden", false,
  664.              //"MacroExecutionMode", MacroExecMode.ALWAYS_EXECUTE) );  }
  665.         "MacroExecutionMode", MacroExecMode.ALWAYS_EXECUTE_NO_WARN) );  }
  666.  
  667.  
  668.  
  669.  
  670.   public static XComponent createDoc(String docType, XComponentLoader loader,
  671.                                                              PropertyValue[] props)
  672.   // create a new document of the specified type
  673.   {
  674.     System.out.println("Creating Office document " + docType);
  675.     // PropertyValue[] props = Props.makeProps("Hidden", true);
  676.           // if Hidden == true, office will not terminate properly
  677.     XComponent doc = null;
  678.     try {
  679.       doc = loader.loadComponentFromURL("private:factory/"+docType, "_blank", 0, props);
  680.       msFactory =  Lo.qi(XMultiServiceFactory.class, doc);
  681.     }
  682.     catch (Exception e) {
  683.        System.out.println("Could not create a document");
  684.     }
  685.     return doc;
  686.   }  // end of createDoc()
  687.  
  688.  
  689.  
  690.   public static XComponent createDocFromTemplate(String templatePath,
  691.                                                  XComponentLoader loader)
  692.   // create a new document using the specified template
  693.   {
  694.     if (!FileIO.isOpenable(templatePath))
  695.       return null;
  696.     System.out.println("Opening template " + templatePath);
  697.     String templateURL = FileIO.fnmToURL(templatePath);
  698.     if (templateURL == null)
  699.       return null;
  700.  
  701.     PropertyValue[] props = Props.makeProps("Hidden", true, "AsTemplate", true);
  702.     XComponent doc = null;
  703.     try {
  704.       doc = loader.loadComponentFromURL(templateURL, "_blank", 0, props);
  705.       msFactory =  Lo.qi(XMultiServiceFactory.class, doc);
  706.     }
  707.     catch (Exception e) {
  708.        System.out.println("Could not create document from template: " + e);
  709.     }
  710.     return doc;
  711.   }  // end of createDocFromTemplate()
  712.  
  713.  
  714.  
  715.   // ======================== document saving ==============
  716.  
  717.  
  718.   public static void save(Object odoc)
  719.   // was XComponent
  720.   {
  721.     XStorable store = Lo.qi(XStorable.class, odoc);
  722.     try {
  723.       store.store();
  724.       System.out.println("Saved the document by overwriting");
  725.     }
  726.     catch (IOException e) {
  727.        System.out.println("Could not save the document");
  728.     }
  729.   }  // end of save()
  730.  
  731.  
  732.   public static void saveDoc(Object odoc, String fnm)
  733.   // was XComponent
  734.   {
  735.     XStorable store = Lo.qi(XStorable.class, odoc);
  736.     XComponent doc = Lo.qi(XComponent.class, odoc);
  737.     int docType = Info.reportDocType(doc);
  738.     storeDoc(store, docType, fnm, null);   // no password
  739.   }
  740.  
  741.  
  742.   public static void saveDoc(Object odoc, String fnm, String password)
  743.   // was XComponent
  744.   {
  745.     XStorable store = Lo.qi(XStorable.class, odoc);
  746.     XComponent doc = Lo.qi(XComponent.class, odoc);
  747.     int docType = Info.reportDocType(doc);
  748.     storeDoc(store, docType, fnm, password);
  749.   }
  750.  
  751.  
  752.   public static void saveDoc(Object odoc, String fnm, String format, String password)
  753.   // was XComponent
  754.   { XStorable store = Lo.qi(XStorable.class, odoc);
  755.     storeDocFormat(store, fnm, format, password);
  756.   }
  757.  
  758.  
  759.  
  760.   //public static void storeDoc(XStorable store, int docType, String fnm)
  761.   //{  saveDoc(store, docType, fnm, null);  }     // no password
  762.  
  763.  
  764.   public static void storeDoc(XStorable store, int docType, String fnm, String password)
  765.   // Save the document using the file's extension as a guide.
  766.   {
  767.     String ext = Info.getExt(fnm);
  768.     String format = "Text";
  769.     if (ext == null)
  770.       System.out.println("Assuming a text format");
  771.     else
  772.       format = ext2Format(docType, ext);
  773.     storeDocFormat(store, fnm, format, password);
  774.   }  // end of storeDoc()
  775.  
  776.  
  777.  
  778.   public static String ext2Format(String ext)
  779.   {  return ext2Format(Lo.UNKNOWN, ext);  }
  780.  
  781.  
  782.   public static String ext2Format(int docType, String ext)
  783.   /* convert the extension string into a suitable office format string.
  784.      The formats were chosen based on the fact that they
  785.      are being used to save (or export) a document.
  786.  
  787.      The names were obtained from
  788.      http://www.oooforum.org/forum/viewtopic.phtml?t=71294
  789.      and by running my DocInfo application on files.
  790.  
  791.      I use the docType to distinguish between the various meanings of the PDF ext.
  792.  
  793.      This could be a lot more extensive.
  794.  
  795.      Use Info.getFilterNames() to get the filter names for your Office
  796.      (the last time I tried it, I got back 246 names!)
  797.   */
  798.   {
  799.     switch (ext) {
  800.       case "doc": return "MS Word 97";
  801.       case "docx": return "Office Open XML Text";   // "MS Word 2007 XML"
  802.       case "rtf":
  803.         if (docType == Lo.CALC)
  804.           return "Rich Text Format (StarCalc)";
  805.         else
  806.           return "Rich Text Format";   // assume writer
  807.  
  808.       case "odt": return "writer8";
  809.       case "ott": return "writer8_template";
  810.  
  811.       case "pdf":
  812.         if (docType == Lo.WRITER)
  813.           return "writer_pdf_Export";
  814.         else if (docType == Lo.IMPRESS)
  815.           return "impress_pdf_Export";
  816.         else if (docType == Lo.DRAW)
  817.           return "draw_pdf_Export";
  818.         else if (docType == Lo.CALC)
  819.           return "calc_pdf_Export";
  820.         else if (docType == Lo.MATH)
  821.           return "math_pdf_Export";
  822.         else
  823.           return "writer_pdf_Export";    // assume we are saving a writer doc
  824.  
  825.       case "txt": return "Text";
  826.  
  827.       case "ppt": return "MS PowerPoint 97";
  828.       case "pptx": return "Impress MS PowerPoint 2007 XML";
  829.       case "odp": return "impress8";
  830.       case "odg": return "draw8";
  831.  
  832.       case "jpg":
  833.         if (docType == Lo.IMPRESS)
  834.            return "impress_jpg_Export";
  835.         else
  836.           return "draw_jpg_Export";    // assume Draw doc
  837.  
  838.       case "png":
  839.         if (docType == Lo.IMPRESS)
  840.            return "impress_png_Export";
  841.         else
  842.           return "draw_png_Export";    // assume Draw doc
  843.  
  844.       case "xls": return "MS Excel 97";
  845.       case "xlsx": return "Calc MS Excel 2007 XML";
  846.       case "csv": return "Text - txt - csv (StarCalc)";   // "Text CSV";
  847.       case "ods": return "calc8";
  848.       case "odb": return "StarOffice XML (Base)";
  849.  
  850.       case "htm":
  851.       case "html":
  852.         if (docType == Lo.WRITER)
  853.           return "HTML (StarWriter)";  // "writerglobal8_HTML";
  854.         else if (docType == Lo.IMPRESS)
  855.           return "impress_html_Export";
  856.         else if (docType == Lo.DRAW)
  857.           return "draw_html_Export";
  858.         else if (docType == Lo.CALC)
  859.            return "HTML (StarCalc)";
  860.         else
  861.           return "HTML";
  862.  
  863.       case "xhtml":
  864.         if (docType == Lo.WRITER)
  865.           return "XHTML Writer File";
  866.         else if (docType == Lo.IMPRESS)
  867.           return "XHTML Impress File";
  868.         else if (docType == Lo.DRAW)
  869.           return "XHTML Draw File";
  870.         else if (docType == Lo.CALC)
  871.           return "XHTML Calc File";
  872.         else
  873.           return "XHTML Writer File";    // assume we are saving a writer doc
  874.  
  875.       case "xml":
  876.         if (docType == Lo.WRITER)
  877.           return "OpenDocument Text Flat XML";
  878.         else if (docType == Lo.IMPRESS)
  879.           return "OpenDocument Presentation Flat XML";
  880.         else if (docType == Lo.DRAW)
  881.           return "OpenDocument Drawing Flat XML";
  882.         else if (docType == Lo.CALC)
  883.           return "OpenDocument Spreadsheet Flat XML";
  884.         else
  885.           return "OpenDocument Text Flat XML";    // assume we are saving a writer doc
  886.  
  887.  
  888.       default:   // assume user means text
  889.         System.out.println("Do not recognize extension \"" + ext + "\"; using text");
  890.         return "Text";
  891.     }
  892.   }  // end of ext2Format()
  893.  
  894.  
  895.  
  896.  
  897.   public static void storeDocFormat(XStorable store, String fnm, String format, String password)
  898.   // save the document in the specified file using the supplied office format
  899.   {
  900.     System.out.println("Saving the document in " + fnm);
  901.     System.out.println("Using format: " + format);
  902.     try {
  903.       String saveFileURL = FileIO.fnmToURL(fnm);
  904.       if (saveFileURL == null)
  905.         return;
  906.  
  907.       PropertyValue[] storeProps;
  908.       if (password == null)  // no password supplied
  909.         storeProps = Props.makeProps("Overwrite", true, "FilterName", format);
  910.       else {
  911.         String[] nms = new String[] {"Overwrite", "FilterName", "Password"};
  912.         Object[] vals = new Object[] { true, format, password};
  913.         storeProps = Props.makeProps(nms, vals);
  914.       }
  915.       store.storeToURL(saveFileURL, storeProps);
  916.     }
  917.     catch (IOException e) {
  918.        System.out.println("Could not save " + fnm + ": " + e);
  919.     }
  920.   } // end of storeDocFormat()
  921.  
  922.  
  923.  
  924.   // ======================== document closing ==============
  925.  
  926.  
  927.   public static void closeDoc(Object doc)
  928.   // was XComponent
  929.   {
  930.     try {
  931.       XCloseable closeable = Lo.qi(XCloseable.class, doc);
  932.       close(closeable);
  933.     }
  934.     catch (com.sun.star.lang.DisposedException e) {
  935.        System.out.println("Document close failed since Office link disposed");
  936.     }
  937.   }
  938.  
  939.  
  940.   public static void close(XCloseable closeable)
  941.   {
  942.     if (closeable == null)
  943.       return;
  944.     System.out.println("Closing the document");
  945.     try {
  946.       closeable.close(false);   // true to force a close
  947.       // set modifiable to false to close a modified doc without complaint setModified(False)
  948.     }
  949.     catch (CloseVetoException e) {
  950.        System.out.println("Close was vetoed");
  951.     }
  952.   }  // end of close()
  953.  
  954.  
  955.  
  956.   // ================= initialization via Addon-supplied context ====================
  957.  
  958.  
  959.   public static XComponent addonInitialize(XComponentContext addonXcc)
  960.   {
  961.     xcc = addonXcc;
  962.     if (xcc == null)  {
  963.       System.out.println("Could not access component context");
  964.       return null;
  965.     }
  966.  
  967.     mcFactory = xcc.getServiceManager();
  968.     if (mcFactory == null) {
  969.       System.out.println("Office Service Manager is unavailable");
  970.       return null;
  971.     }
  972.  
  973.     try {
  974.       Object oDesktop = mcFactory.createInstanceWithContext(
  975.                                        "com.sun.star.frame.Desktop", xcc);
  976.       xDesktop = Lo.qi(XDesktop.class, oDesktop);
  977.     }
  978.     catch (Exception e) {
  979.       System.out.println("Could not access desktop");
  980.       return null;
  981.     }
  982.  
  983.     XComponent doc = xDesktop.getCurrentComponent();
  984.     if (doc == null)  {
  985.       System.out.println("Could not access document");
  986.       return null;
  987.     }
  988.  
  989.     msFactory =  Lo.qi(XMultiServiceFactory.class, doc);
  990.     return doc;
  991.   }  // end of addonInitialize()
  992.  
  993.  
  994.  
  995.   // ============= initialization via script context ======================
  996.  
  997.  
  998.   public static XComponent scriptInitialize(XScriptContext sc)
  999.   {
  1000.     if (sc == null) {
  1001.       System.out.println("Script Context is null");
  1002.       return null;
  1003.     }
  1004.  
  1005.     xcc = sc.getComponentContext();
  1006.     if (xcc == null)  {
  1007.       System.out.println("Could not access component context");
  1008.       return null;
  1009.     }
  1010.     mcFactory = xcc.getServiceManager();
  1011.     if (mcFactory == null) {
  1012.       System.out.println("Office Service Manager is unavailable");
  1013.       return null;
  1014.     }
  1015.  
  1016.     xDesktop = sc.getDesktop();
  1017.     if (xDesktop == null)  {
  1018.       System.out.println("Could not access desktop");
  1019.       return null;
  1020.     }
  1021.  
  1022.     XComponent doc = xDesktop.getCurrentComponent();
  1023.     if (doc == null)  {
  1024.       System.out.println("Could not access document");
  1025.       return null;
  1026.     }
  1027.  
  1028.     msFactory =  Lo.qi(XMultiServiceFactory.class, doc);
  1029.     return doc;
  1030.   }  // end of scriptInitialize()
  1031.  
  1032.  
  1033.  
  1034.  
  1035.   // ==================== dispatch ===============================
  1036.   // see https://wiki.documentfoundation.org/Development/DispatchCommands
  1037.  
  1038.  
  1039.   public static boolean dispatchCmd(String cmd)
  1040.   {  return dispatchCmd(xDesktop.getCurrentFrame(), cmd, null);   }
  1041.  
  1042.  
  1043.   public static boolean dispatchCmd(String cmd, PropertyValue[] props)
  1044.   {  return dispatchCmd(xDesktop.getCurrentFrame(), cmd, props);   }
  1045.  
  1046.  
  1047.   public static boolean dispatchCmd(XFrame frame, String cmd, PropertyValue[] props)
  1048.   // cmd does not include the ".uno:" substring; e.g. pass "Zoom" not ".uno:Zoom"
  1049.   {
  1050.     XDispatchHelper helper =
  1051.          createInstanceMCF(XDispatchHelper.class, "com.sun.star.frame.DispatchHelper");
  1052.     if (helper == null) {
  1053.       System.out.println("Could not create dispatch helper for command " + cmd);
  1054.       return false;
  1055.     }
  1056.  
  1057.     try {
  1058.       XDispatchProvider provider = Lo.qi(XDispatchProvider.class, frame);
  1059.  
  1060.       /* returns failure even when the event works (?), and an illegal value
  1061.          when the dispatch actually does fail */
  1062.       /*
  1063.       DispatchResultEvent res =  (DispatchResultEvent)
  1064.                   helper.executeDispatch(provider, (".uno:" + cmd), "", 0, props);
  1065.       if (res.State == DispatchResultState.FAILURE)
  1066.         System.out.println("Dispatch failed for \"" + cmd + "\"");
  1067.       else if (res.State == DispatchResultState.DONTKNOW)
  1068.         System.out.println("Dispatch result unknown for \"" + cmd + "\"");
  1069.       */
  1070.       helper.executeDispatch(provider, (".uno:" + cmd), "", 0, props);
  1071.       return true;
  1072.     }
  1073.     catch(java.lang.Exception e)
  1074.     {  System.out.println("Could not dispatch \"" + cmd + "\":\n  " + e); }  
  1075.     return false;
  1076.   }  // end of dispatchCmd()
  1077.  
  1078.  
  1079.  
  1080.   // ================= Uno cmds =========================
  1081.  
  1082.  
  1083.   public static String makeUnoCmd(String itemName)
  1084.   // use a dummy Java class name, Foo
  1085.   {  return "vnd.sun.star.script:Foo/Foo." + itemName +
  1086.                            "?language=Java&location=share";  }
  1087.  
  1088.  
  1089.  
  1090.   public static String extractItemName(String unoCmd)
  1091.   /* format is:
  1092.        "vnd.sun.star.script:Foo/Foo." + itemName +
  1093.                                   "?language=Java&location=share";
  1094.   */
  1095.   {
  1096.     int fooPos = unoCmd.indexOf("Foo.");
  1097.     if (fooPos == -1) {
  1098.       System.out.println("Could not find Foo header in command: \"" + unoCmd + "\"");
  1099.       return null;
  1100.     }
  1101.  
  1102.     int langPos = unoCmd.indexOf("?language");
  1103.     if (langPos == -1) {
  1104.       System.out.println("Could not find language header in command: \"" + unoCmd + "\"");
  1105.       return null;
  1106.     }
  1107.  
  1108.     return unoCmd.substring(fooPos+4, langPos);
  1109.   }  // end of extractItemName()
  1110.  
  1111.  
  1112.  
  1113.  
  1114.   // ======================== use Inspector extensions ====================
  1115.  
  1116.  
  1117.   public static void inspect(Object obj)
  1118.   /* call XInspector.inspect() in the Inspector.oxt extension
  1119.      Available from https://wiki.openoffice.org/wiki/Object_Inspector
  1120.   */
  1121.   {
  1122.     if ((xcc == null) || (mcFactory == null)) {
  1123.       System.out.println("No office connection found");
  1124.       return;
  1125.     }
  1126.  
  1127.     try {
  1128.       Type[] ts = Info.getInterfaceTypes(obj);   // get class name for title
  1129.       String title = "Object";
  1130.       if ((ts != null) && (ts.length > 0))
  1131.         title = ts[0].getTypeName() + " " + title;
  1132.  
  1133.       Object inspector = mcFactory.createInstanceWithContext(
  1134.                                   "org.openoffice.InstanceInspector", xcc);
  1135.                // hangs on second use
  1136.       if (inspector == null) {
  1137.         System.out.println("Inspector Service could not be instantiated");
  1138.         return;
  1139.       }
  1140.        
  1141.       System.out.println("Inspector Service instantiated");
  1142. /*
  1143.       // report on inspector
  1144.       XServiceInfo si = Lo.qi(XServiceInfo.class, inspector);
  1145.       System.out.println("Implementation name: " + si.getImplementationName());
  1146.       String[] serviceNames = si.getSupportedServiceNames();
  1147.       for(String nm : serviceNames)
  1148.          System.out.println("Service name: " + nm);
  1149. */
  1150.       XIntrospection intro = createInstanceMCF(XIntrospection.class,
  1151.                                                "com.sun.star.beans.Introspection");
  1152.       XIntrospectionAccess introAcc = intro.inspect(inspector);
  1153.       XIdlMethod method = introAcc.getMethod("inspect", -1);   // get ref to XInspector.inspect()
  1154. /*
  1155.       // alternative, low-level way of getting the method
  1156.       Object coreReflect = mcFactory.createInstanceWithContext(
  1157.                                      "com.sun.star.reflection.CoreReflection", xcc);
  1158.       XIdlReflection idlReflect = Lo.qi(XIdlReflection.class, coreReflect);
  1159.       XIdlClass idlClass = idlReflect.forName("org.openoffice.XInstanceInspector");
  1160.       XIdlMethod[] methods = idlClass.getMethods();
  1161.       System.out.println("No of methods: " + methods.length);
  1162.       for(XIdlMethod m : methods)
  1163.          System.out.println("  " + m.getName());
  1164.  
  1165.       XIdlMethod method = idlClass.getMethod("inspect");
  1166. */
  1167.       System.out.println("inspect() method was found: " + (method != null));
  1168.  
  1169.       Object[][] params =  new Object[][]{new Object[]{obj, title}};
  1170.       method.invoke(inspector, params);
  1171.     }
  1172.     catch(Exception e)
  1173.     { System.out.println("Could not access Inspector: " + e); }
  1174.   }  // end of accessInspector()
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.   public static void mriInspect(Object obj)
  1181.   /* call MRI's inspect()
  1182.      Available from http://extensions.libreoffice.org/extension-center/mri-uno-object-inspection-tool
  1183.                   or http://extensions.services.openoffice.org/en/project/MRI
  1184.      Docs: https://github.com/hanya/MRI/wiki
  1185.      Forum tutorial: https://forum.openoffice.org/en/forum/viewtopic.php?f=74&t=49294
  1186.   */
  1187.   {
  1188.     XIntrospection xi = createInstanceMCF(XIntrospection.class, "mytools.Mri");
  1189.     if (xi == null) {
  1190.       System.out.println("MRI Inspector Service could not be instantiated");
  1191.       return;
  1192.     }
  1193.  
  1194.     System.out.println("MRI Inspector Service instantiated");
  1195.     xi.inspect(obj);
  1196.   }  // end of mriInspect()
  1197.  
  1198.  
  1199.  
  1200.  
  1201.   // ------------------ color methods ---------------------
  1202.  
  1203.  
  1204.   public static int getColorInt(java.awt.Color color)
  1205.   // return the color as an integer, ignoring the alpha channel
  1206.   {  
  1207.     if (color == null) {
  1208.       System.out.println("No color supplied");
  1209.       return 0;
  1210.     }
  1211.     else
  1212.       return (color.getRGB() & 0xffffff);
  1213.   } // end of getColorInt()
  1214.  
  1215.  
  1216.  
  1217.   public static int hexString2ColorInt(String colStr)
  1218.   // e.g. "#FF0000", "0xFF0000"
  1219.   {
  1220.     java.awt.Color color = java.awt.Color.decode(colStr);
  1221.     return getColorInt(color);
  1222.   }
  1223.  
  1224.  
  1225.   public static String getColorHexString(java.awt.Color color)
  1226.   {
  1227.     if (color == null) {
  1228.       System.out.println("No color supplied");
  1229.       return "#000000";
  1230.     }
  1231.     else
  1232.       return int2HexString(color.getRGB() & 0xffffff);
  1233.   }  // end of getColorHexString()
  1234.  
  1235.  
  1236.    
  1237.   public static String int2HexString(int val)
  1238.   {
  1239.     String hex = Integer.toHexString(val);
  1240.     if (hex.length() < 6)
  1241.       hex = "000000".substring(0, 6 - hex.length()) + hex;
  1242.     return "#" + hex;
  1243.   }  // end of int2HexString()
  1244.  
  1245.  
  1246.  
  1247.   // ================== other utils =============================
  1248.  
  1249.  
  1250.   public static void wait(int ms)    // I can never remember the name :)
  1251.   {  delay(ms);  }
  1252.  
  1253.  
  1254.   public static void delay(int ms)
  1255.   { try {
  1256.       Thread.sleep(ms);
  1257.     }
  1258.     catch(InterruptedException e){}
  1259.   }
  1260.  
  1261.  
  1262.   public static boolean isNullOrEmpty(String s)
  1263.   {  return ((s == null) || (s.length() == 0));  }
  1264.  
  1265.  
  1266.   public static void waitEnter()
  1267.   {
  1268.     System.out.println("Press Enter to continue...");
  1269.     try {
  1270.       System.in.read();
  1271.     }
  1272.     catch(java.io.IOException e){}
  1273.   }  // end of waitEnter()
  1274.  
  1275.  
  1276.  
  1277.   public static String getTimeStamp()
  1278.   { java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  1279.     return sdf.format(new java.util.Date());
  1280.   }
  1281.  
  1282.  
  1283.  
  1284.   public static void printNames(String[] names)
  1285.   {  printNames(names, 4);  }
  1286.  
  1287.  
  1288.   public static void printNames(String[] names, int numPerLine)
  1289.   // print a large array with <numPerLine> strings/line, indented by 2 spaces
  1290.   {
  1291.     if (names == null)
  1292.       System.out.println("  No names found");
  1293.     else {
  1294.       Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);
  1295.       int nlCounter = 0;
  1296.       System.out.println("No. of names: " + names.length);
  1297.       for (String name : names) {
  1298.         System.out.print("  \"" + name + "\"");
  1299.         nlCounter++;
  1300.         if (nlCounter % numPerLine == 0) {
  1301.           System.out.println();
  1302.           nlCounter = 0;
  1303.         }
  1304.       }
  1305.       System.out.println("\n\n");
  1306.     }
  1307.   }  // end of printNames()
  1308.  
  1309.  
  1310.  
  1311.   public static void printTable(String name, Object[][] table)
  1312.   {
  1313.     System.out.println("-- " + name + " ----------------");
  1314.     for (int i=0; i < table.length; i++) {
  1315.       for(int j=0; j < table[i].length; j++)
  1316.         System.out.print("  " + table[i][j]);
  1317.       System.out.println();
  1318.     }
  1319.     System.out.println("-----------------------------\n");
  1320.   } // end of printTable()
  1321.  
  1322.  
  1323.   public static String capitalize(String s)
  1324.   {
  1325.     if ((s == null) || (s.length() == 0))
  1326.       return null;
  1327.     else if (s.length() == 1)
  1328.       return s.toUpperCase();
  1329.     else
  1330.       return Character.toUpperCase(s.charAt(0)) + s.substring(1);
  1331.   }  // end of capitalize()
  1332.  
  1333.  
  1334.   public static int parseInt(String s)
  1335.   {
  1336.     if (s == null)
  1337.       return 0;
  1338.     try {
  1339.       return Integer.parseInt(s);
  1340.     }
  1341.     catch (NumberFormatException ex){
  1342.       System.out.println(s + " could not be parsed as an int; using 0");
  1343.       return 0;
  1344.     }
  1345.   }  // end of parseInt()
  1346.  
  1347.  
  1348.   public static void addJar(String jarPath)
  1349.   // load this JAR into the classloader at run time
  1350.   // from http://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime
  1351.   {
  1352.     try {
  1353.       URLClassLoader classLoader =
  1354.                   (URLClassLoader)ClassLoader.getSystemClassLoader();
  1355.       java.lang.reflect.Method m =
  1356.             URLClassLoader.class.getDeclaredMethod("addURL", java.net.URL.class);
  1357.       m.setAccessible(true);
  1358.       m.invoke(classLoader, new java.net.URL(jarPath));
  1359.     }
  1360.     catch(java.lang.Exception e)
  1361.     {  System.out.println(e);  }
  1362.   }  // end of addJar()
  1363.  
  1364.  
  1365.  
  1366.   // ------------------- container manipulation --------------------
  1367.  
  1368.  
  1369.  
  1370.   public static String[] getContainerNames(XIndexAccess con)
  1371.   // extract the names of the elements in the indexed container
  1372.   {
  1373.     if (con == null) {
  1374.       System.out.println("Container is null");
  1375.       return null;
  1376.     }
  1377.  
  1378.     int numElems = con.getCount();
  1379.     if (numElems == 0) {
  1380.       System.out.println("No elements in the container");
  1381.       return null;
  1382.     }
  1383.  
  1384.     ArrayList<String> namesList = new ArrayList<String>();
  1385.     for (int i=0; i < numElems; i++) {
  1386.       try {
  1387.         XNamed named = Lo.qi(XNamed.class, con.getByIndex(i));
  1388.         namesList.add(named.getName());
  1389.       }
  1390.       catch(Exception e)
  1391.       {  System.out.println("Could not access name of element " + i);  }
  1392.     }
  1393.  
  1394.     int sz = namesList.size();
  1395.     if (sz == 0) {
  1396.       System.out.println("No element names found in the container");
  1397.       return null;
  1398.     }
  1399.  
  1400.     String[] names = new String[sz];
  1401.     for (int i=0; i < sz; i++)
  1402.       names[i] = namesList.get(i);
  1403.  
  1404.     return names;
  1405.   }  // end of getContainerNames()
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.   public static XPropertySet findContainerProps(XIndexAccess con, String nm)
  1412.   {
  1413.     if (con == null) {
  1414.       System.out.println("Container is null");
  1415.       return null;
  1416.     }
  1417.  
  1418.     for (int i=0; i < con.getCount(); i++) {
  1419.       try {
  1420.         Object oElem = con.getByIndex(i);
  1421.         XNamed named = Lo.qi(XNamed.class, oElem);
  1422.         if (named.getName().equals(nm)) {
  1423.           return (XPropertySet) Lo.qi(XPropertySet.class, oElem);
  1424.         }
  1425.       }
  1426.       catch(Exception e)
  1427.       {  System.out.println("Could not access element " + i);  }
  1428.     }
  1429.  
  1430.     System.out.println("Could not find a \"" + nm + "\" property set in the container");
  1431.     return null;
  1432.   }  // end of findContainerProps()
  1433.  
  1434.  
  1435.  
  1436.  
  1437. }  // end of Lo class
  1438.  
  1439.  
Add Comment
Please, Sign In to add comment