1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package integration.forms;
24 
25 import com.sun.star.beans.PropertyState;
26 import com.sun.star.beans.PropertyValue;
27 import com.sun.star.beans.XPropertySet;
28 import com.sun.star.container.XChild;
29 import com.sun.star.container.XIndexContainer;
30 import com.sun.star.container.XNameContainer;
31 import com.sun.star.document.MacroExecMode;
32 import com.sun.star.drawing.XDrawPage;
33 import com.sun.star.drawing.XDrawPageSupplier;
34 import com.sun.star.drawing.XDrawPages;
35 import com.sun.star.drawing.XDrawPagesSupplier;
36 import com.sun.star.form.XFormsSupplier;
37 import com.sun.star.frame.XComponentLoader;
38 import com.sun.star.frame.XController;
39 import com.sun.star.frame.XFrame;
40 import com.sun.star.frame.XModel;
41 import com.sun.star.lang.XComponent;
42 import com.sun.star.lang.XMultiServiceFactory;
43 import com.sun.star.lang.XServiceInfo;
44 import com.sun.star.uno.UnoRuntime;
45 import com.sun.star.uno.XInterface;
46 import com.sun.star.util.XModifiable;
47 
48 /**************************************************************************/
49 
50 /**************************************************************************/
51 /** provides a small wrapper around a document
52 */
53 public class DocumentHelper
54 {
55     private XMultiServiceFactory    m_orb;
56     private XComponent              m_documentComponent;
57 
58     /* ================================================================== */
59     /* ------------------------------------------------------------------ */
DocumentHelper( XMultiServiceFactory orb, XComponent document )60     public DocumentHelper( XMultiServiceFactory orb, XComponent document )
61     {
62         m_orb = orb;
63         m_documentComponent = document;
64     }
65 
66     /* ------------------------------------------------------------------ */
implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL )67     protected static XComponent implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception
68     {
69 		return implLoadAsComponent( orb, documentOrFactoryURL, new PropertyValue[0] );
70 	}
71 
72     /* ------------------------------------------------------------------ */
implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args )73     protected static XComponent implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args ) throws com.sun.star.uno.Exception
74     {
75         XComponentLoader aLoader = (XComponentLoader)UnoRuntime.queryInterface(
76             XComponentLoader.class,
77             orb.createInstance( "com.sun.star.frame.Desktop" )
78         );
79 
80         XComponent document = dbfTools.queryComponent(
81             aLoader.loadComponentFromURL( documentOrFactoryURL, "_blank", 0, i_args )
82         );
83         return document;
84     }
85 
86     /* ------------------------------------------------------------------ */
implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL )87     private static DocumentHelper implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception
88     {
89 		return implLoadDocument( orb, documentOrFactoryURL, new PropertyValue[0] );
90 	}
91 
92     /* ------------------------------------------------------------------ */
implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args )93     private static DocumentHelper implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args ) throws com.sun.star.uno.Exception
94     {
95         XComponent document = implLoadAsComponent( orb, documentOrFactoryURL, i_args );
96 
97         XServiceInfo xSI = (XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class,
98             document );
99         if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
100             return new SpreadsheetDocument( orb, document );
101         return new DocumentHelper( orb, document );
102     }
103 
104     /* ------------------------------------------------------------------ */
loadDocument( XMultiServiceFactory orb, String documentURL )105     public static DocumentHelper loadDocument( XMultiServiceFactory orb, String documentURL ) throws com.sun.star.uno.Exception
106     {
107         return implLoadDocument( orb, documentURL );
108     }
109 
110     /* ------------------------------------------------------------------ */
blankTextDocument( XMultiServiceFactory orb )111     public static DocumentHelper blankTextDocument( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception
112     {
113         return blankDocument( orb, DocumentType.WRITER );
114     }
115 
116     /* ------------------------------------------------------------------ */
blankXMLForm( XMultiServiceFactory orb )117     public static DocumentHelper blankXMLForm( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception
118     {
119         return blankDocument( orb, DocumentType.XMLFORM );
120     }
121 
122     /* ------------------------------------------------------------------ */
blankDocument( XMultiServiceFactory orb, DocumentType eType )123     public static DocumentHelper blankDocument( XMultiServiceFactory orb, DocumentType eType ) throws com.sun.star.uno.Exception
124     {
125 		final PropertyValue[] args = new PropertyValue[] {
126 			new PropertyValue( "MacroExecutionMode", -1, MacroExecMode.ALWAYS_EXECUTE, PropertyState.DIRECT_VALUE )
127 		};
128         return implLoadDocument( orb, getDocumentFactoryURL( eType ), args );
129     }
130 
131     /* ================================================================== */
132     /* ------------------------------------------------------------------ */
getDocument( )133     public XComponent getDocument( )
134     {
135         return m_documentComponent;
136     }
137 
138     /* ------------------------------------------------------------------ */
isModified()139     public boolean isModified()
140     {
141         XModifiable modify = (XModifiable)query( XModifiable.class );
142         return modify.isModified();
143     }
144 
145     /* ------------------------------------------------------------------ */
query( Class aInterfaceClass )146     public Object query( Class aInterfaceClass )
147     {
148         return UnoRuntime.queryInterface( aInterfaceClass, m_documentComponent );
149     }
150 
151     /* ------------------------------------------------------------------ */
getOrb( )152     public XMultiServiceFactory getOrb( )
153     {
154         return m_orb;
155     }
156 
157     /* ------------------------------------------------------------------ */
158     /** retrieves the current view of the document
159         @return
160             the view component, queried for the interface described by aInterfaceClass
161     */
getCurrentView( )162     public DocumentViewHelper getCurrentView( )
163     {
164         // get the model interface for the document
165         XModel xDocModel = (XModel)UnoRuntime.queryInterface(XModel.class, m_documentComponent );
166         // get the current controller for the document - as a controller is tied to a view,
167         // this gives us the currently active view for the document.
168         XController xController = xDocModel.getCurrentController();
169 
170         if ( classify() == DocumentType.CALC )
171             return new SpreadsheetView( m_orb, this, xController );
172 
173         return new DocumentViewHelper( m_orb, this, xController );
174     }
175 
176     /* ------------------------------------------------------------------ */
177     /** reloads the document
178      *
179      *  The reload is done by dispatching the respective URL at a frame of the document.
180      *  As a consequence, if you have references to a view of the document, or any interface
181      *  of the document, they will become invalid.
182      *  The Model instance itself, at which you called reload, will still be valid, it will
183      *  automatically update its internal state after the reload.
184      *
185      *  Another consequence is that if the document does not have a view at all, it cannot
186      *  be reloaded.
187      */
reload()188     public void reload() throws Exception
189     {
190         DocumentViewHelper view = getCurrentView();
191         XFrame frame = view.getController().getFrame();
192         XModel oldModel = frame.getController().getModel();
193 
194         getCurrentView().dispatch( ".uno:Reload" );
195 
196         m_documentComponent = (XComponent)UnoRuntime.queryInterface( XComponent.class,
197             frame.getController().getModel() );
198 
199         XModel newModel = getCurrentView().getController().getModel();
200         if ( UnoRuntime.areSame( oldModel, newModel ) )
201             throw new java.lang.IllegalStateException( "reload failed" );
202     }
203 
204     /* ------------------------------------------------------------------ */
205     /** creates a new form which is a child of the given form components container
206 
207         @param xParentContainer
208             The parent container for the new form
209         @param sInitialName
210             The initial name of the form. May be null, in this case the default (which
211             is an implementation detail) applies.
212     */
createSubForm( XIndexContainer xParentContainer, String sInitialName )213     protected XIndexContainer createSubForm( XIndexContainer xParentContainer, String sInitialName )
214             throws com.sun.star.uno.Exception
215     {
216         // create a new form
217         Object xNewForm = m_orb.createInstance( "com.sun.star.form.component.DataForm" );
218 
219         // insert
220         xParentContainer.insertByIndex( xParentContainer.getCount(), xNewForm );
221 
222         // set the name if necessary
223         if ( null != sInitialName )
224         {
225             XPropertySet xFormProps = dbfTools.queryPropertySet( xNewForm );
226             xFormProps.setPropertyValue( "Name", sInitialName );
227         }
228 
229         // outta here
230         return (XIndexContainer)UnoRuntime.queryInterface( XIndexContainer.class, xNewForm );
231     }
232 
233     /* ------------------------------------------------------------------ */
234     /** creates a new form which is a child of the given form components container
235 
236         @param aParentContainer
237             The parent container for the new form
238         @param sInitialName
239             The initial name of the form. May be null, in this case the default (which
240             is an implementation detail) applies.
241     */
createSubForm( Object aParentContainer, String sInitialName )242     public XIndexContainer createSubForm( Object aParentContainer, String sInitialName )
243         throws com.sun.star.uno.Exception
244     {
245         XIndexContainer xParentContainer = (XIndexContainer)UnoRuntime.queryInterface(
246             XIndexContainer.class, aParentContainer );
247         return createSubForm( xParentContainer, sInitialName );
248     }
249 
250     /* ------------------------------------------------------------------ */
251     /** creates a form which is a sibling of the given form
252         @param aForm
253             A sinbling of the to be created form.
254 
255         @param sInitialName
256             The initial name of the form. May be null, in this case the default (which
257             is an implementation detail) applies.
258     */
createSiblingForm( Object aForm, String sInitialName )259     public XIndexContainer createSiblingForm( Object aForm, String sInitialName ) throws com.sun.star.uno.Exception
260     {
261         // get the parent
262         XIndexContainer xContainer = (XIndexContainer)dbfTools.getParent(
263             aForm, XIndexContainer.class );
264         // append a new form to this parent container
265         return createSubForm( xContainer, sInitialName );
266     }
267 
268     /* ------------------------------------------------------------------ */
269     /** retrieves the document model which a given form component belongs to
270     */
getDocumentForComponent( Object aFormComponent, XMultiServiceFactory orb )271     static public DocumentHelper getDocumentForComponent( Object aFormComponent, XMultiServiceFactory orb )
272     {
273         XChild xChild = (XChild)UnoRuntime.queryInterface( XChild.class, aFormComponent );
274         XModel xModel = null;
275         while ( ( null != xChild ) && ( null == xModel ) )
276         {
277             XInterface xParent = (XInterface)xChild.getParent();
278             xModel = (XModel)UnoRuntime.queryInterface( XModel.class, xParent );
279             xChild = (XChild)UnoRuntime.queryInterface( XChild.class, xParent );
280         }
281 
282         return new DocumentHelper( orb, xModel );
283     }
284 
285     /* ------------------------------------------------------------------ */
286     /** returns a URL which can be used to create a document of a certain type
287     */
getDocumentFactoryURL( DocumentType eType )288     public static String getDocumentFactoryURL( DocumentType eType )
289     {
290         if ( eType == DocumentType.WRITER )
291             return "private:factory/swriter";
292         if ( eType == DocumentType.CALC )
293             return "private:factory/scalc";
294         if ( eType == DocumentType.DRAWING )
295             return "private:factory/sdraw";
296         if ( eType == DocumentType.XMLFORM )
297             return "private:factory/swriter?slot=21053";
298         return "private:factory/swriter";
299     }
300 
301     /* ------------------------------------------------------------------ */
302     /** classifies a document
303     */
classify( )304     public DocumentType classify( )
305     {
306         XServiceInfo xSI = (XServiceInfo)UnoRuntime.queryInterface(
307             XServiceInfo.class, m_documentComponent );
308 
309         if ( xSI.supportsService( "com.sun.star.text.TextDocument" ) )
310             return DocumentType.WRITER;
311         else if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
312             return DocumentType.CALC;
313         else if ( xSI.supportsService( "com.sun.star.drawing.DrawingDocument" ) )
314             return DocumentType.DRAWING;
315 
316         return DocumentType.UNKNOWN;
317     }
318 
319     /* ------------------------------------------------------------------ */
320     /** retrieves a com.sun.star.drawing.DrawPage of the document, denoted by index
321      *  @param index
322      *      the index of the draw page
323      *  @throws
324      *      com.sun.star.lang.IndexOutOfBoundsException
325      *      com.sun.star.lang.WrappedTargetException
326      */
getDrawPage( int index )327     protected XDrawPage getDrawPage( int index ) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException
328     {
329         XDrawPagesSupplier xSuppPages = (XDrawPagesSupplier)UnoRuntime.queryInterface(
330             XDrawPagesSupplier.class, getDocument() );
331         XDrawPages xPages = xSuppPages.getDrawPages();
332 
333         return (XDrawPage)UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( index ) );
334     }
335 
336     /* ------------------------------------------------------------------ */
337     /** retrieves the <type scope="com.sun.star.drawing">DrawPage</type> of the document
338     */
getMainDrawPage( )339     protected XDrawPage getMainDrawPage( ) throws com.sun.star.uno.Exception
340     {
341         XDrawPage xReturn;
342 
343         // in case of a Writer document, this is rather easy: simply ask the XDrawPageSupplier
344         XDrawPageSupplier xSuppPage = (XDrawPageSupplier)UnoRuntime.queryInterface(
345             XDrawPageSupplier.class, getDocument() );
346         if ( null != xSuppPage )
347             xReturn = xSuppPage.getDrawPage();
348         else
349         {   // the model itself is no draw page supplier - okay, it may be a Writer or Calc document
350             // (or any other multi-page document)
351             XDrawPagesSupplier xSuppPages = (XDrawPagesSupplier)UnoRuntime.queryInterface(
352                 XDrawPagesSupplier.class, getDocument() );
353             XDrawPages xPages = xSuppPages.getDrawPages();
354 
355             xReturn = (XDrawPage)UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( 0 ) );
356 
357             // Note that this is no really error-proof code: If the document model does not support the
358             // XDrawPagesSupplier interface, or if the pages collection returned is empty, this will break.
359         }
360 
361         return xReturn;
362     }
363 
364     /* ------------------------------------------------------------------ */
365     /** retrieves the root of the hierarchy of form components
366     */
getFormComponentTreeRoot( )367     protected XNameContainer getFormComponentTreeRoot( ) throws com.sun.star.uno.Exception
368     {
369         XFormsSupplier xSuppForms = (XFormsSupplier)UnoRuntime.queryInterface(
370             XFormsSupplier.class, getMainDrawPage( ) );
371 
372         XNameContainer xFormsCollection = null;
373         if ( null != xSuppForms )
374         {
375             xFormsCollection = xSuppForms.getForms();
376         }
377         return xFormsCollection;
378     }
379 
380     /* ------------------------------------------------------------------ */
381     /** creates a component at the service factory provided by the document
382     */
createInstance( String serviceSpecifier )383     public XInterface createInstance( String serviceSpecifier ) throws com.sun.star.uno.Exception
384     {
385         XMultiServiceFactory xORB = (XMultiServiceFactory)UnoRuntime.queryInterface( XMultiServiceFactory.class,
386             m_documentComponent );
387         return (XInterface)xORB.createInstance( serviceSpecifier );
388     }
389 
390     /* ------------------------------------------------------------------ */
391     /** creates a component at the service factory provided by the document
392     */
createInstanceWithArguments( String serviceSpecifier, Object[] arguments )393     public XInterface createInstanceWithArguments( String serviceSpecifier, Object[] arguments ) throws com.sun.star.uno.Exception
394     {
395         XMultiServiceFactory xORB = (XMultiServiceFactory)UnoRuntime.queryInterface( XMultiServiceFactory.class,
396             m_documentComponent );
397         return (XInterface) xORB.createInstanceWithArguments( serviceSpecifier, arguments );
398     }
399 };
400 
401