Difference between revisions of "Documentation/DevGuide/OfficeDev/Filter"

From Apache OpenOffice Wiki
Jump to: navigation, search
(Initial author Sun Microsystems, Inc.)
 
 
(24 intermediate revisions by 7 users not shown)
Line 5: Line 5:
 
|ShowPrevNext=block
 
|ShowPrevNext=block
 
|PrevPage=Documentation/DevGuide/OfficeDev/Filtering Process
 
|PrevPage=Documentation/DevGuide/OfficeDev/Filtering Process
|NextPage=Documentation/DevGuide/OfficeDev/Filter Options
+
|NextPage=Documentation/DevGuide/OfficeDev/Configuring a Filter in OpenOffice.org
 
}}
 
}}
{{DISPLAYTITLE:Filter}}
+
{{Documentation/DevGuideLanguages|Documentation/DevGuide/OfficeDev/{{SUBPAGENAME}}}}
Most of the services described before are used for loading. Normally, they are not necessary for saving, except the <code>MediaDescriptor</code>. Only filters are fixed members of both processes.
+
{{DISPLAYTITLE:Filters}}
  
These objects also represent a service. Their task is to import or export the content of a type into or from a model. Accordingly, import filters are distinguished from export filters. It is possible to provide both functionality in the same implementation.
+
As described in the previous chapter, filters are objects that can be used to import or export content into or from {{AOo}} documents. The API defines the two services <idl>com.sun.star.document.ImportFilter</idl> and <idl>com.sun.star.document.ExportFilter</idl>. A filter implementation can support one or both of them. If a particular filter that only supports import is used, the imported document is modified by the user and then the user presses the "Save" button, a "Save As" operation will be carried out instead as {{AOo}} must assume that the filter component is "import only" and so storing must be done in a different format. It doesn't help to have a different export filter for the same content. If a direct "Save" operation should be possible, both filter services must be supported at the same filter object.
  
A filter is acquired from the factory service <idl>com.sun.star.document.FilterFactory</idl>. It provides a low-level access to the configuration that knows all registered filters of {{PRODUCTNAME}}, supports search functionality, and creates and initializes filter components. The description of this factory and its configuration are provided below.  
+
A filter is created from the factory service <idl>com.sun.star.document.FilterFactory</idl>. This service also provides a low-level access to the configuration that knows all registered filters of {{AOo}} and their properties, supports search and query functionality, and creates and initializes filter components. As an example, if the type name of a content is known, a query at the FilterFactory can be used to retrieve one or more internal filter names of possible filters and after choosing one of them the filter can be created using this name.
  
If a filter wants to be initialized with its own configuration data or get existing parameters of the corresponding create request, it implements the interface <idl>com.sun.star.lang.XInitialization</idl>. The method <code>initialize()</code> is used directly after creation by the factory and is the first request on a new filter instance. The parameter list of <code>initialize()</code> uses the following protocol:
+
{{Note|Many existing filters are legacy filters. The component loader or <code>XStorable</code> implementation does not use the <code>FilterFactory</code> to create them, but triggers filtering by internal C++ calls. So asking the FilterFactory to create such filter is not possible.}}
  
* The first item in the list is a sequence of <idl>com.sun.star.beans.PropertyValue</idl> structs, that describe the configuration properties of the filter.
+
Filters can be initialized if they implement the interface <idl>com.sun.star.lang.XInitialization</idl>. The method <code>initialize()</code> is used by the filter factory service directly after creation of the filter object, before the filter is returned to the code that requested the filter. It passes the configuration data of the filter and all parameters and options that have been specified by the creation request to the factory. These properties usually originate from the "FilterOptions" property of the MediaDescriptor and have been put there either by the code requesting the loading or storing or by user input in a filter options dialog. How such filter dialog can be implemented is explained in the chapter about [[Documentation/DevGuide/OfficeDev/Filter_Options|filter options]].
* All other items are directly copied from the parameter Arguments of the factory interface method [http://api.openoffice.org/docs/common/ref/com/sun/star/lang/XMultiServiceFactory.html#createInstanceWithArguments com.sun.star.lang.XMultiServiceFactory:createInstanceWithArguments]().
+
  
A filter should be initialized, because one generic implementation is registered to handle different types, it must know which specialization is required. The simplest way to achieve this for the filter is to know its own configuration data, especially the unique internal name.
+
The parameter list of <code>initialize()</code> uses the following protocol:
  
This information is used internally then, or it is provided by the interface <idl>com.sun.star.container.XNamed</idl>. An owner of a filter uses the provided name to find specific information about this component by using the <code>FilterFactory</code> service.
+
* The first item in the list is a sequence of <idl>com.sun.star.beans.PropertyValue</idl> structs, that describe the configuration properties of the filter.
 +
* All other items are directly copied from the parameter Arguments of the factory interface method <idlm>com.sun.star.lang.XMultiServiceFactory:createInstanceWithArguments</idlm>().
  
{{Documentation/Caution|The interface provides functionality for reading and writing of this name. It is not allowed to change an internal filter name during runtime of {{PRODUCTNAME}}, because all filter names must be unique and it is not possible for a filter instance to alter its name. Calls to [http://api.openoffice.org/docs/common/ref/com/sun/star/container/XNamed.html#setName com.sun.star.container.XNamed:setName]() should be ignored or forwarded to the <tt>FilterFactory</tt> service, which knows all unique names and can solve ambiguities!}}
+
{{Warn|The interface provides functionality for reading and writing of this name. It is not allowed to change an internal filter name during runtime of {{AOo}}, because all filter names must be unique, and it is not possible for a filter instance to alter its name. Calls to <idlm>com.sun.star.container.XNamed:setName</idlm>() should be ignored or forwarded to the <tt>FilterFactory</tt> service, which knows all unique names and can solve ambiguities!}}
  
This code snippet initializes a filter instance:
+
The fact that a filter gets its own name passed as an argument can be used to use one filter implementation to act as several filters in the configuration. This is shown in the following code snippet of the implementation of a filter initialization:
  
 +
<syntaxhighlight lang="java">
 
   private String m_sInternalName;
 
   private String m_sInternalName;
 
   public void initialize( Object[] lArguments )   
 
   public void initialize( Object[] lArguments )   
Line 66: Line 67:
 
           }  
 
           }  
 
   }
 
   }
 +
</syntaxhighlight>
  
Furthermore, depending on its action a filter supports the services <idl>com.sun.star.document.ImportFilter</idl> for import or <idl>com.sun.star.document.ExportFilter</idl> for export functionality.
+
In one single workflow filters can act as an import or an export filter. If content is loaded, the creator of the filter will use the <idl>com.sun.star.document.XImporter</idl> interface and its method <code>setTargetDocument()</code> to bind the filter to the document it should import into. If content is stored, the interface <idl>com.sun.star.document.XExporter</idl> and its method <code>setSourceDocument()</code> will bind the filter to the document it shall get data from. The filtering process is done by the same method in both cases: it's the <code>filter()</code> method of the <idl>com.sun.star.document.XFilter</idl> interface that both kinds of filters must support. Here the <code>MediaDescriptor</code> is passed to the filter.
  
The common interface of both services is <idl>com.sun.star.document.XFilter</idl> starts or cancels the filter process. How the canceling is implemented is an internal detail of the filter implementation, however a thread is a good solution.  
+
{{Tip|In an object that implements both import and export it is necessary to decide whether importing or exporting is asked for when the <tt>filter()</tt> method is called. The differentiator is whether setTargetDocument or setSourceDocument has been called before (see sample code below). The user of a filter is responsible to make this call in a valid order.}}
  
On calling [http://api.openoffice.org/docs/common/ref/com/sun/star/document/XFilter.html#filter com.sun.star.document.XFilter:filter](), the already mentioned <code>MediaDescriptor<//code> is passed to the service. It includes the necessary information about the content, for example, the URL or the stream, but not the source or the target model for the filter process.
+
This example code shows how the required filter operation can be tracked inside the filter implementation easily:
  
Additional interfaces are part of the service description, <idl>com.sun.star.document.XImporter</idl> and <idl>com.sun.star.document.XExporter</idl> to get this information. These interfaces are used directly before the filter operation is started. A filter saves the model set by <code>setTargetDocument()</code> and <code>setSourceDocument()</code>, and uses it inside its filter operation.
 
 
{{Documentation/Tip|The <tt>filter()</tt> method does not include any information about the required import or export functionality. It seems that it is not possible to implement both at the same object. The interfaces <tt>XImporter</tt>/<tt>XExporter</tt> are used to solve this conflict. Only one of them is called for one <tt>filter()</tt> request. So an internal flag that indicates the using of an interface helps.}}
 
 
This example code detects the required filter operation:
 
 
<!--[SOURCE:OfficeDev/FilterDevelopment/AsciiFilter/AsciiReplaceFilter.java]-->
 
<!--[SOURCE:OfficeDev/FilterDevelopment/AsciiFilter/AsciiReplaceFilter.java]-->
 
+
<syntaxhighlight lang="java">
 
   private boolean m_bImport;
 
   private boolean m_bImport;
 
    
 
    
Line 102: Line 99:
 
     com.sun.star.beans.PropertyValue[] lDescriptor )  
 
     com.sun.star.beans.PropertyValue[] lDescriptor )  
 
   {  
 
   {  
       boolean bState = false;  
+
       boolean bState;  
       if (m_bImport==true)  
+
       if (m_bImport)  
 
         bState = impl_import( lDescriptor );  
 
         bState = impl_import( lDescriptor );  
 
       else  
 
       else  
Line 109: Line 106:
 
       return bState;  
 
       return bState;  
 
   }
 
   }
 +
</syntaxhighlight>
  
The <code>MediaDescriptor</code> does not include the model, but it should include the already opened stream, true for the current implementation in {{PRODUCTNAME}}. If it is there, it must be used. Only if a stream does not exist, it indicates that someone else uses this filter service, for example, outside {{PRODUCTNAME}}, it creates a stream of your own by using the URL parameter of the descriptor.
+
{{PDL1}}
  
In general, a filter must not change the position of an incoming stream without reading or writing data. The position inside the stream is 0. Follow the previously mentioned rules for handling streams of the section about the <code>MediaDescriptor</code> above. We can make these rules easier, because currently there are no external filters used inside office. See descriptions of the chapter "MediaDescriptor" before ... )).
+
[[Category:Documentation/Developer's Guide/Office Development]]
 
+
{{PDL1}}
+
[[Category: Office Development]]
+

Latest revision as of 12:09, 3 January 2021



As described in the previous chapter, filters are objects that can be used to import or export content into or from Apache OpenOffice documents. The API defines the two services com.sun.star.document.ImportFilter and com.sun.star.document.ExportFilter. A filter implementation can support one or both of them. If a particular filter that only supports import is used, the imported document is modified by the user and then the user presses the "Save" button, a "Save As" operation will be carried out instead as Apache OpenOffice must assume that the filter component is "import only" and so storing must be done in a different format. It doesn't help to have a different export filter for the same content. If a direct "Save" operation should be possible, both filter services must be supported at the same filter object.

A filter is created from the factory service com.sun.star.document.FilterFactory. This service also provides a low-level access to the configuration that knows all registered filters of Apache OpenOffice and their properties, supports search and query functionality, and creates and initializes filter components. As an example, if the type name of a content is known, a query at the FilterFactory can be used to retrieve one or more internal filter names of possible filters and after choosing one of them the filter can be created using this name.

Documentation note.png Many existing filters are legacy filters. The component loader or XStorable implementation does not use the FilterFactory to create them, but triggers filtering by internal C++ calls. So asking the FilterFactory to create such filter is not possible.

Filters can be initialized if they implement the interface com.sun.star.lang.XInitialization. The method initialize() is used by the filter factory service directly after creation of the filter object, before the filter is returned to the code that requested the filter. It passes the configuration data of the filter and all parameters and options that have been specified by the creation request to the factory. These properties usually originate from the "FilterOptions" property of the MediaDescriptor and have been put there either by the code requesting the loading or storing or by user input in a filter options dialog. How such filter dialog can be implemented is explained in the chapter about filter options.

The parameter list of initialize() uses the following protocol:

Documentation caution.png The interface provides functionality for reading and writing of this name. It is not allowed to change an internal filter name during runtime of Apache OpenOffice, because all filter names must be unique, and it is not possible for a filter instance to alter its name. Calls to setName() should be ignored or forwarded to the FilterFactory service, which knows all unique names and can solve ambiguities!

The fact that a filter gets its own name passed as an argument can be used to use one filter implementation to act as several filters in the configuration. This is shown in the following code snippet of the implementation of a filter initialization:

  private String m_sInternalName;
  public void initialize( Object[] lArguments )  
          throws com.sun.star.uno.Exception 
  {  
          // no arguments - no initialization  
          if (lArguments.length<1)
                  return;
          // Arguments[0] = own configuration data
          com.sun.star.beans.PropertyValue[] lConfig =
                  (com.sun.star.beans.PropertyValue[])lArguments[0];
 
          // Arguments[1..n] = optional arguments of create request 
          for (int n=1; n<lArguments.length; ++n)
          {
                  ...
          }  
 
          // analyze own configuration data for our own internal  
          // filter name! Important for generic filter services,  
          // which are registered more then once. They can use this  
          // information to find out, which specialization of it  
          // is required.  
          for (int i=0; i<lConfig.length; ++i)  
          {   
                  if (lConfig[i].Name.equals("Name"))   
                  {    
                          m_sInternalName =     
                                  AnyConverter.toString(lConfig[i].Value);
 
                          // Tip: A generic filter implementation can use this internal    
                          // name at runtime, to detect which specialization of it is required.
                          if (m_sInternalName=="filter_format_1")     
                                  m_eHandle = E_FORMAT_1;    
                          else     
                          if (m_sInternalName=="filter_format_2")
                                  ...   
                  }  
          } 
  }

In one single workflow filters can act as an import or an export filter. If content is loaded, the creator of the filter will use the com.sun.star.document.XImporter interface and its method setTargetDocument() to bind the filter to the document it should import into. If content is stored, the interface com.sun.star.document.XExporter and its method setSourceDocument() will bind the filter to the document it shall get data from. The filtering process is done by the same method in both cases: it's the filter() method of the com.sun.star.document.XFilter interface that both kinds of filters must support. Here the MediaDescriptor is passed to the filter.

Tip.png In an object that implements both import and export it is necessary to decide whether importing or exporting is asked for when the filter() method is called. The differentiator is whether setTargetDocument or setSourceDocument has been called before (see sample code below). The user of a filter is responsible to make this call in a valid order.


This example code shows how the required filter operation can be tracked inside the filter implementation easily:

  private boolean m_bImport;
 
  // used to tell us: "you will be used for import" 
  public void setTargetDocument( 
    com.sun.star.lang.XComponent xDocument ) 
      throws com.sun.star.lang.IllegalArgumentException 
  { 
      m_bImport = true;
  }
 
  // used to tell us: "you will be used for export" 
  public void setSourceDocument( 
    com.sun.star.lang.XComponent xDocument ) 
      throws com.sun.star.lang.IllegalArgumentException 
  { 
      m_bImport = false; 
  }  
 
  // detect required type of filter operation 
  public boolean filter( 
    com.sun.star.beans.PropertyValue[] lDescriptor ) 
  { 
       boolean bState; 
       if (m_bImport) 
         bState = impl_import( lDescriptor ); 
       else 
         bState = impl_export( lDescriptor ); 
       return bState; 
  }
Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages