/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



//***************************************************************************
// comment: Step 1: get the Desktop object from the office
//          Step 2: open an empty text document
//          Step 3: enter a example text
//          Step 4: insert some bookmarks
//
//          Chapter 5.1.1.4 Inserting bookmarks
//***************************************************************************

import com.sun.star.uno.UnoRuntime;

public class BookmarkInsertion {

    public static void main(String args[]) {
        // You need the desktop to create a document
        // The getDesktop method does the UNO bootstrapping, gets the
        // remote servie manager and the desktop object.
        com.sun.star.frame.XDesktop xDesktop = null;
        xDesktop = getDesktop();

        // create text document
        com.sun.star.text.XTextDocument xTextDocument = null;
        xTextDocument = createTextdocument(xDesktop);

        // put example text in document
        createExampleData(xTextDocument);


        String mOffending[] = { "negro(e|es)?","bor(ed|ing)?",
                                "bloody?", "bleed(ing)?" };
        String mBad[] = { "possib(le|ilit(y|ies))", "real(ly)+", "brilliant" };

        String sOffendPrefix = "Offending";
        String sBadPrefix = "BadStyle";

        markList(xTextDocument, mOffending, sOffendPrefix);
        markList(xTextDocument, mBad, sBadPrefix);

        System.out.println("Done");

        System.exit(0);
    }

    public static void markList(com.sun.star.text.XTextDocument xTextDocument,
                                String mList[], String sPrefix) {
        int iCounter=0;
        com.sun.star.uno.XInterface xSearchInterface = null;
        com.sun.star.text.XTextRange xSearchTextRange = null;

        try {
            for( iCounter = 0; iCounter < mList.length; iCounter++ ) {
                // the findfirst returns a XInterface
                xSearchInterface = (com.sun.star.uno.XInterface)FindFirst(
                    xTextDocument, mList[ iCounter ] );

                if( xSearchInterface != null ) {
                    // get the TextRange form the XInterface
                    xSearchTextRange = (com.sun.star.text.XTextRange)
                        UnoRuntime.queryInterface(
                            com.sun.star.text.XTextRange.class, xSearchInterface);

                    InsertBookmark(xTextDocument, xSearchTextRange,
                                   sPrefix + iCounter);
                }
            }
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }
    }


    public static void InsertBookmark(com.sun.star.text.XTextDocument xTextDocument,
                                      com.sun.star.text.XTextRange xTextRange,
                                      String sBookName) {
        // create a bookmark on a TextRange
        try {
            // get the MultiServiceFactory from the text document
            com.sun.star.lang.XMultiServiceFactory xDocMSF;
            xDocMSF = (com.sun.star.lang.XMultiServiceFactory)
                UnoRuntime.queryInterface(
                    com.sun.star.lang.XMultiServiceFactory.class, xTextDocument);

            // the bookmark service is a context dependend service, you need
            // the MultiServiceFactory from the document
            Object xObject = xDocMSF.createInstance("com.sun.star.text.Bookmark");

            // set the name from the bookmark
            com.sun.star.container.XNamed xNameAccess = null;
            xNameAccess = (com.sun.star.container.XNamed)
                UnoRuntime.queryInterface(
                    com.sun.star.container.XNamed.class, xObject);

            xNameAccess.setName(sBookName);

            // create a XTextContent, for the method 'insertTextContent'
            com.sun.star.text.XTextContent xTextContent = null;
            xTextContent = (com.sun.star.text.XTextContent)
                UnoRuntime.queryInterface(
                    com.sun.star.text.XTextContent.class, xNameAccess);

            // insertTextContent need a TextRange not a cursor to specify the
            // position from the bookmark
            xTextDocument.getText().insertTextContent(xTextRange, xTextContent, true);

            System.out.println("Insert bookmark: " + sBookName);
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
        }
    }

    protected static com.sun.star.uno.XInterface FindFirst(
        com.sun.star.text.XTextDocument xTextDocument, String sSearchString)
    {
        com.sun.star.util.XSearchDescriptor xSearchDescriptor = null;
        com.sun.star.util.XSearchable xSearchable = null;
        com.sun.star.uno.XInterface xSearchInterface = null;

        try {
            xSearchable = (com.sun.star.util.XSearchable)
                UnoRuntime.queryInterface(
                    com.sun.star.util.XSearchable.class, xTextDocument);
            xSearchDescriptor = (com.sun.star.util.XSearchDescriptor)
                xSearchable.createSearchDescriptor();

            xSearchDescriptor.setSearchString(sSearchString);

            com.sun.star.beans.XPropertySet xPropertySet = null;
            xPropertySet = (com.sun.star.beans.XPropertySet)
                UnoRuntime.queryInterface(
                    com.sun.star.beans.XPropertySet.class, xSearchDescriptor);

            xPropertySet.setPropertyValue("SearchRegularExpression",
                                          new Boolean( true ) );

            xSearchInterface = (com.sun.star.uno.XInterface)
                xSearchable.findFirst(xSearchDescriptor);
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
        }

        return xSearchInterface;
    }

    protected static void createExampleData(
        com.sun.star.text.XTextDocument xTextDocument )
    {
        com.sun.star.text.XTextCursor xTextCursor = null;

        try {
            xTextCursor = (com.sun.star.text.XTextCursor)
                xTextDocument.getText().createTextCursor();

            xTextCursor.setString( "He heard quiet steps behind him. That didn't bode well. Who could be following him this late at night and in this deadbeat part of town? And at this particular moment, just after he pulled off the big time and was making off with the greenbacks. Was there another crook who'd had the same idea, and was now watching him and waiting for a chance to grab the fruit of his labor?" );
            xTextCursor.collapseToEnd();
            xTextCursor.setString( "Or did the steps behind him mean that one of many bloody officers in town was on to him and just waiting to pounce and snap those cuffs on his wrists? He nervously looked all around. Suddenly he saw the alley. Like lightening he darted off to the left and disappeared between the two warehouses almost falling over the trash can lying in the middle of the sidewalk. He tried to nervously tap his way along in the inky darkness and suddenly stiffened: it was a dead-end, he would have to go back the way he had come" );
            xTextCursor.collapseToEnd();
            xTextCursor.setString( "The steps got louder and louder, he saw the black outline of a figure coming around the corner. Is this the end of the line? he thought pressing himself back against the wall trying to make himself invisible in the dark, was all that planning and energy wasted? He was dripping with sweat now, cold and wet, he could smell the brilliant fear coming off his clothes. Suddenly next to him, with a barely noticeable squeak, a door swung quietly to and fro in the night's breeze." );

            xTextCursor.gotoStart(false);
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
        }

    }

    public static com.sun.star.frame.XDesktop getDesktop() {
        com.sun.star.frame.XDesktop xDesktop = null;
        com.sun.star.lang.XMultiComponentFactory xMCF = null;

        try {
            com.sun.star.uno.XComponentContext xContext = null;

            // get the remote office component context
            xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();

            // get the remote office service manager
            xMCF = xContext.getServiceManager();
            if( xMCF != null ) {
                System.out.println("Connected to a running office ...");

                Object oDesktop = xMCF.createInstanceWithContext(
                    "com.sun.star.frame.Desktop", xContext);
                xDesktop = (com.sun.star.frame.XDesktop) UnoRuntime.queryInterface(
                    com.sun.star.frame.XDesktop.class, oDesktop);
            }
            else
                System.out.println( "Can't create a desktop. No connection, no remote office servicemanager available!" );
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }


        return xDesktop;
    }

    public static com.sun.star.text.XTextDocument createTextdocument(
        com.sun.star.frame.XDesktop xDesktop )
    {
        com.sun.star.text.XTextDocument aTextDocument = null;

        try {
            com.sun.star.lang.XComponent xComponent = CreateNewDocument(xDesktop,
                                                                        "swriter");
            aTextDocument = (com.sun.star.text.XTextDocument)
                UnoRuntime.queryInterface(
                    com.sun.star.text.XTextDocument.class, xComponent);
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
        }

        return aTextDocument;
    }


    protected static com.sun.star.lang.XComponent CreateNewDocument(
        com.sun.star.frame.XDesktop xDesktop,
        String sDocumentType )
    {
        String sURL = "private:factory/" + sDocumentType;

        com.sun.star.lang.XComponent xComponent = null;
        com.sun.star.frame.XComponentLoader xComponentLoader = null;
        com.sun.star.beans.PropertyValue xValues[] =
            new com.sun.star.beans.PropertyValue[1];
        com.sun.star.beans.PropertyValue xEmptyArgs[] =
            new com.sun.star.beans.PropertyValue[0];

        try {
            xComponentLoader = (com.sun.star.frame.XComponentLoader)
                UnoRuntime.queryInterface(
                    com.sun.star.frame.XComponentLoader.class, xDesktop);

            xComponent  = xComponentLoader.loadComponentFromURL(
                sURL, "_blank", 0, xEmptyArgs);
        }
        catch( Exception e) {
            e.printStackTrace(System.out);
        }

        return xComponent ;
    }
}
