LAB-5569: ODFDOM - Changing ODF documents using the new opensourced multi-tiered API

Expected Duration: 100 minutes

Exercise 1: Exploring the ODFDOM layers (20 minutes)

 

The goal of this exercise is to get an impression of the ODFDOM layers following step by step instructions.


Steps to Follow

 

Step 1: Opening the Project

  1. If NetBeans is not already running, start it.
    1. Select File Menu
    2. Select New Project
    3. Select Category 'Java' and Project 'Java Application'
    4. Press 'Next'

    Figure-01: New Project: Choose Project

  2. In the next dialog, do the following
    1. Set 'Project Name' to OdfdomLayers
    2. Set 'Project Location' to '<lab_root>' - note for JavaOne attendees: this is correct as it is - just keep the default.
    3. Enter 'odfdom.example1.RunExample1' as main class.
    4. Press 'Finish'

    Figure-02: New Java Application: Name and Location

  3. We are adding some jar libraries to our project - for future usage.

    Right-click the OdfdomLayers project and choose 'Properties'. In the 'Libraries' category, click 'Add JAR/Folder'. Add the following libraries to the project:

    • <lab_root>/resources/odfdom/jars/xercesImpl.jar
    • <lab_root>/resources/odfdom/jars/odfdom.jar

    For JavaOne attendees, the libraries are here:

    • /export/home/lab5569/odfdom/resources/odfdom/jars/xercesImpl.jar
    • /export/home/lab5569/odfdom/resources/odfdom/jars/odfdom.jar

    Click "OK" afterwards.


    Figure-03: Add required libraries to the project

  4. After the project creation, the main class is automatically opened by NetBeans. When you enter the following code inside of the main(...) method, do not forget to set the LAB_ROOT variable. For JavaOne attendees, the line in the following code snippet is already correct. The second part of the exercise is commented at first since this project will be run twice.

        // For JavaOne the place for the project is this; change it for your machine
        private static final String LAB_ROOT = "/export/home/lab5569/odfdom/";
        private static final Logger LOG = Logger.getLogger(RunExample1.class.getName());
    
        /**
         *  Executes the first lab exercise.
         * 
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            try {
                // 1st ODFDOM LAYER - PACKAGE / PHYSICAL LAYER:
                // Creating an ODF package containing an image not shown in the text
                firstExercicePart1();
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, "Something weired happened in the first part..", ex);
            }
    
    //        try {
    //            // 2nd ODFDOM LAYER - TYPED DOM / XML LAYER:
    //            // Creating an ODF Text document showing the image from the package
    //            firstExercicePart2();
    //        } catch (Exception ex) {
    //            LOG.log(Level.SEVERE, "Something weired happened in the second part..", ex);
    //        }
    //
    //        try {
    //            // 3rd ODFDOM LAYER - CONVENIENCE LAYER:
    //            // Quite similar to the previous DOM handling, as a DOC layer is always a child
    //            // of a DOM layer object therefore as well a DOM tree.
    //            //
    //            //
    //            // Two things are done for the user behind the scene:
    //            //
    //            // 1) The package handling to insert the image file
    //            //
    //            // 2) The default size is received from the image via AWT helper and
    //            // added to the attributes of the sourrounding draw:frame.
    //            firstExercicePart3();
    //        } catch (Exception ex) {
    //            LOG.log(Level.SEVERE, "Something weired happened in the third part..", ex);
    //        }
        }
    
                                  
  5. Now implement the first exercise method. Notice that the output directory without path is the root of your current NetBeans project.
    The file is saved twice here with different extensions. With the .odt extension, you can open the file in OpenOffice.org, and with the .zip extension, the content can be viewed in NetBeans.

      
        /**
         * 1st ODFDOM LAYER - PACKAGE / PHYSICAL LAYER:
         * Creating an ODF package containing an image not shown in the text
         *
         * @throws java.lang.Exception
         */
        private static void firstExercicePart1() throws Exception {
            // ODF KNOW-HOW: One ODF Package is only a zipped container for arbitrary files of some document.
            OdfPackage pkg = OdfPackage.loadPackage(LAB_ROOT + "resources/e1-input.odt");
            // Inserting an image into the 'Pictures' directory within the ODF package.
            pkg.insert(new FileInputStream(LAB_ROOT + "resources/e1-01_DukeToEmbed.png"), 
                    "Pictures/e1-01_DukeToEmbed.png");
    
            // Save the package with the picture; no path used here, will be stored in project root
            pkg.save("output_1_seems-empty.odt");
            // zip can be opened with NetBeans
            pkg.save("output_1_seems-empty.zip");
    
            // ODF-KNOW-HOW: Only images referenced from the text will be viewed in ODF.
            //              Therefore if the document is being opened (for instance with OpenOffice.org)
            //              The document appears to be empty.
            LOG.info("SUCCESS: You were able to save an ODF Package containing an image, which is not shown!");
        }
                                  
  6. Press CTRL+S to save your file. Then press CTRL+SHIFT+I to fix the missing imports from the libraries.
  7. Your project should now be able to run. Press F6 for this. If it does not work, verify your code or ask a proctor. The result is shown in Figure-04. Activate the "Files" tab where the resulting document is displayed. NetBeans offers a simple way to browse into zip files: just click on the symbol before the file, then open the "Pictures" folder.
    You can open the .odt file in OpenOffice.org from here, too: click right on the document and select "Open With OpenOffice.org"


    Verify the correct document

    Figure-04: Verify the correct document in Netbeans

  8. We implement the second exercise method. Please uncomment the execution of firstExercisePart2(); in the main(...) method and implement the method like this:

    
        /**
         * 2nd ODFDOM LAYER - TYPED DOM / XML LAYER
         * Creating an ODF Text document showing the image from the package
         *
         * @throws java.lang.Exception
         */
        private static void firstExercicePart2() throws Exception {
            // ODF-KNOW-HOW: An ODF Package contains one or more ODF Documents.
            //               The ODF XML elements part of an ODF Document.
            // Load the ODF Package as an ODF Document.
            OdfDocument odfDoc = OdfDocument.loadDocument("output_1_seems-empty.odt");
    
            // Get the ODF XML content as DOM tree representation.
            OdfFileDom odfContent = odfDoc.getContentDom();
    
            // ODF KNOW-HOW: The element name of a paragraph is <text:p>
            // Receiving the first paragraph  "//text:p[1]" (using XPath functionality from JDK).
            XPath xpath = getXPathForODF();
            OdfParagraphElement para = (OdfParagraphElement) xpath.evaluate("//text:p[1]", odfContent, XPathConstants.NODE);
    
            // ODF KNOW-HOW: An image consists always of a <draw:frame> parent and an embedded <draw:image> child.
            // Create the <draw:frame> ODF element.
            OdfFrameElement odfFrame = (OdfFrameElement) OdfElementFactory.createOdfElement(odfContent,        
            OdfFrame.ELEMENT_NAME);
    
            // Add the created frame to the earlier found first paragraph.
            para.appendChild(odfFrame);
    
            // create the <draw:image> ODF element viewing the previous (Part1 )inserted image
            OdfImageElement odfImage = (OdfImageElement) OdfElementFactory.createOdfElement(odfContent,
            OdfImage.ELEMENT_NAME);
    
            // Add the created image to the earlier created frame.
            odfFrame.appendChild(odfImage);
    
            // setting the xlink:href attribute
            odfImage.setHref(new OdfAnyURI("Pictures/e1-01_DukeToEmbed.png"));
    
            // Save the document; no path used here, will be stored in project root
            odfDoc.save("output_2_image-visible-small.odt");
            // zip can be opened with NetBeans
            odfDoc.save("output_2_image-visible-small.zip");
            LOG.info("SUCCESS: You were able to save an ODF Document again, now showing the earlier added image (small)!!");
    
        }
                                
  9. For the second exercise method to work, we need some helper. This is the helper function:

        private static XPath mXPath;
    
        private static XPath getXPathForODF() {
            if (mXPath == null) {
                // W3C XPath initialization (i.e. JDK5 functionality)  -
                // XPath is the path within the XML file
                mXPath = XPathFactory.newInstance().newXPath();
                mXPath.setNamespaceContext(new OdfNamespace());
            }
            return mXPath;
        }
                                
  10. Again press CTRL+S to save your file, followed by CTRL+SHIFT+I to fix the missing imports. This time you will be asked for correct classes. Figure-05 shows the correct imports.


    The correct imports

    Figure-05: Correct imports for the used classes

  11. Your project should again be able to run. Press F6 for this. If it does not work, verify your code or ask a proctor. The result is shown in Figure-06. This time we use OpenOffice.org to verify: Open OpenOffice.org and click on "File - Open". Browse to your NetBeans project and open the file "e1-output-2.odt":


    Verify the correct document

    Figure-06: Image is visiable, but small

  12. In the last layer, the convenient layer ODFDOM adds enhanced functionality and eases the developer's life. We implement the third exercise method. Please uncomment the execution of firstExercisePart3(); in the main(...) method and implement the method like this:

      /**
         * 3rd ODFDOM LAYER - CONVENIENCE LAYER:
         * Quite similar to the previous DOM handling, as a DOC layer is always a child
         * of a DOM layer object therefore as well a DOM tree.
         *
         *
         * Two things are done for the user behind the scene:
         *
         * 1) The package handling to insert the image file
         * 
         * 2) The default size is received from the image via AWT helper and
         * added to the attributes of the sourrounding draw:frame.
         *
         * @throws java.lang.Exception
         */
        private static void firstExercicePart3() throws Exception {
    
            OdfTextDocument odfText = OdfTextDocument.createTextDocument();
            // Get the ODF XML content as DOM tree representation.
            OdfFileDom odfContent = odfText.getContentDom();
    
            // ODF KNOW-HOW: The element name of a paragraph is <text:p>
            // Receiving the first paragraph  "//text:p[1]" (using XPath functionality from JDK).
            XPath xpath = getXPathForODF();
            OdfParagraph para = (OdfParagraph) xpath.evaluate("//text:p[1]", odfContent, XPathConstants.NODE);
    
            // ODF KNOW-HOW: An image consists always of a <draw:frame> parent and an embedded <draw:image> child.
            // Create the <draw:frame> ODF element.
            OdfFrame odfFrame = (OdfFrame) OdfElementFactory.createOdfElement(odfContent, OdfFrame.ELEMENT_NAME);
    
            // Add the created frame to the earlier found first paragraph.
            para.appendChild(odfFrame);
    
            // create the <draw:image> ODF element to view the similar image file
            OdfImage odfImage = (OdfImage) OdfElementFactory.createOdfElement(odfContent, OdfImage.ELEMENT_NAME);
    
            // Add the created image to the earlier created frame.
            odfFrame.appendChild(odfImage);
    
            // NOTE: Loading the image (relativ to <LABROOT>/solution/solution1
            // Adding the image to the package, getting the default
            // size via AWT helper and setting the size at the draw:frame parent.
            odfImage.insertImage(new URI("../../odfdom/resources/e1-01_DukeToEmbed.png"));
    
            // Save the document; no path used here, will be stored in project root
            odfText.save("output_3_image-visible-big.odt");
            // zip can be opened with NetBeans
            odfText.save("output_3_image-visible-big.zip");
            LOG.info("SUCCESS: You were able to add an image into an ODF Text Document using the convenient API!!");
    
    
        }            
                
  13. Again press CTRL+S to save your file, followed by CTRL+SHIFT+I to fix the missing imports.


  14. Your project should again be able to run. Press F6 for this. If it does not work, verify your code or ask a proctor. The result is shown in Figure-07. This time we use OpenOffice.org to verify: Open OpenOffice.org and click on "File - Open". Browse to your NetBeans project and open the file "e1-output-3.odt":


    Verify the correct document

    Figure-07: Image is visable with it's default size

  15. For troubleshooting, the complete example should look like this (with first example method enabled):

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    

Summary

 

In this exercise, you learned what the different layers of ODFDOM offer in regard of inserting an image file.

 

Back to top
Next exercise