Overview
The priint:comet InDesign Desktop Plug-Ins support custom find statements for the product panel. In the priint:publishing server environment, find statements are implemented as priint:publishing server plug-ins or plug-in methods, each method corresponding one find statement.
This documentation shows how to implement find statement methods.
Requirements
To implement custom find statements, you need
- a recent priint:publishing server installation (version 4.0.3 and above)
- the PubServerSDK
- Java development environment, such as Eclipse
- PublishingServer version 4.1.5 Build #1199 or above
HelloWorld
Step by step
To demonstrate the principle of implementing custom find statements, we start with a simple step by step example.
- open an existing priint:publishing server plug-in library project or create a new plug-in library project
If unsure, how to create or use a plug-in library project, please refer to the How to create a plug-in library guide. - add an priint:publishing server plug-in class to this project, e.g.
package com.priint.pubserver.comet.findstatement; @Stateless(mappedName="com.priint.pubserver.comet.findstatement.HelloWorld") @LocalBean @PubServerPlugin public class HelloWorld extends PluginControlDefault { }
- create a new priint:publishing server method like shown below:
@PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT ) public List<Bucket> findRootBucketsByLabel( @PubServerMethodParameter String modelId, @PubServerMethodParameter Context context, @PubServerMethodParameter String searchLabel) throws CometException { try { String sessionId = PluginControlDefault.getSessionId(); EntityManagerLocal em = PluginUtils.getPlugin(Constants.MANAGER_ENTITY, sessionId, EntityManagerLocal.class); List
buckets = em.getEntityRootBuckets(sessionId, modelId, "", context, ""); List result = new ArrayList (); for (Bucket bucket : buckets) { if (bucket.getLabel().contains(searchLabel)) { result.add(bucket); } } return result; } catch (CometException e) { throw e; } catch (Exception e) { throw new CometException(this, "Unable to find buckets: " + e.getMessage(), e); } } - export the plug-in library to an EJB jar file and deploy it on your priint:publishing server
- login with InDesign Desktop and open the product panel. You should now see a new find statement like shown in this screenshot:
- By selecting the entry "findRootBucketsByLabel", the method implemented above will be invoked immediately with searchLabel set to an emtpy string.
Conclusion
- a find statement is defined, by implementing a Java method annotated as @PluginMethod with type=PluginMethod.MethodType.FIND_STATEMENT
- several find statements are defined by implementing more than one Java method (i.e.: each find statement has it's Java method counterpart)
- there are no restrictions concerning the way data is accessed and processed in a find statement, though the way shown above (using EntityManager and filter the results in Java) may be a good and reliable choice, if the amount of data is not too big
Find statements / Java method details
Java find statement methods must meet the following requirements:
- the method must be annotated as a @PubServerMethod with type=PluginMethod.MethodType.FIND_STATEMENT
- return type is a list (java.util.List) with elements of types derived from com.priint.pubserver.plugin.entitydata.Bucket or com.priint.pubserver.comet.bridge.entitydata.Product
- type and order of parameters is mandatory as shown in the next section
Parameters
Find statement methods must accept two parameters and up to four optional / additional parameters:
- the first parameter is of type String and should be called modelId
- the second parameter is of type com.priint.pubserver.plugin.entitydata.Context and should be called context
- optionally up to 4 additional String parameters can be provided, which will be set to the search criteria entered by the user
- all parameters must be annotated as @PubServerMethodParameter
The modelId parameter is set to the identifier of the entity model associated to the Comet project, the current session is connected to.
The context parameter is initialized according to the product panel configuration.
Additional parameters (up to 4 Strings) are set to the value entered by the user in text input fields 1 to 4. Empty fields will result in an empty String, the value will never be null.
Examples
// valid: mandatory 1st and 2nd parameter plus one search criteria @PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Search by label" ) public List<Bucket> findRootBucketsByLabel( @PubServerMethodParameter String modelId, @PubServerMethodParameter Context context, @PubServerMethodParameter( name="Product label") String searchLabel) throws CometException
// invalid: missing some @PubServerMethodParameter annotation @PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Search by label" ) public List<Bucket> findRootBucketsByLabel( String modelId, @PubServerMethodParameter Context context, String searchLabel) throws CometException
// invalid: wrong type of second parameter @PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Search by label" ) public List<Bucket> findRootBucketsByLabel( @PubServerMethodParameter String modelId, @PubServerMethodParameter String context, @PubServerMethodParameter( name="Product label") String searchLabel) throws CometException
Return Type
The return type of a find statement method must be java.util.List, element types must be either
- com.priint.pubserver.entitydata.Bucket or
- com.priint.pubserver.comet.bridge.entitydata.Product
Examples
// EntityData return type List<EntityData> result = new ArrayList<>(); result.add (new Bucket()); // etc. // for all entries, the default product data mapping or the data mapping // configured for this project will be used: return result;
// Product result type List<Product> result = new ArrayList<>(); com.priint.pubserver.comet.bridge.entitydata.Product product = new Product(); product.setId(1); product.setPageTemplateId(123); // ... set more particular values result.add (product); return result;
Hierarchy
Starting with PublishingServer version 4.1.5 Build #1199, developers can control the hierarchy for the find statment result, i.e:
- use the Bucket Tree hierarchy or
- use hierarchy based on Planning data
To define the type of hierarchy, the annotation @CometFindStatement was introduced, which can be applied to find statement methods in addition to the @PubServerMethod annotation.
Example for Bucket hierarchy
@PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Show planning content", description="Find planning records to given document in Planning & Briefing") @CometFindStatement(hierarchy=Hierarchy.BUCKET) public List<Product> showPlanningContent ( @PubServerMethodParameter String modelId, @PubServerMethodParameter Context context) throws CometException { List<Product> result = new ArrayList<>(); String sessionId = getSessionId(); if (context.getDocumentId() != null && !context.getDocumentId().isEmpty()) { try { EntityManagerLocal em = getEntityManager(); List<Planning> plannings = em.getEntityPlanningsOfDocument( sessionId, modelId, "", "", context.copy(), ""); if (plannings != null) { // get the project default data mapping ProductDataMapping dataMapping = ProductDataMappingUtils.getProductDataMapping(); // use the project default product data mapping: result = dataMapping.entitiesToProducts(plannings, null, // no parent ProductDataMappingUtils.getEntityModel(modelId), context.copy(), // use Id Builder for Buckets CometIdBuilderFactory.useBucketId()); } } catch (Exception e) { throw new CometException(this, "An error occured when requesting planning data for document.", e); } } else { throw new CometException(this, "Document Id is null or empty."); } return result; }
With only very slight changes, the method will show the Planning hierarchy
@PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Show planning hierarchy", description="Find planning records to given document in Planning & Briefing") @CometFindStatement(hierarchy=Hierarchy.PLANNING) public List<Product> showPlanningHierarchy ( @PubServerMethodParameter String modelId, @PubServerMethodParameter Context context) throws CometException { List<Product> result = new ArrayList<>(); String sessionId = getSessionId(); if (context.getDocumentId() != null && !context.getDocumentId().isEmpty()) { try { EntityManagerLocal em = getEntityManager(); List<Planning> plannings = em.getEntityPlanningsOfDocument( sessionId, modelId, "", "", context.copy(), ""); if (plannings != null) { // get the project default data mapping ProductDataMapping dataMapping = ProductDataMappingUtils.getProductDataMapping(); // use the project default product data mapping: result = dataMapping.entitiesToProducts(plannings, null, // no parent ProductDataMappingUtils.getEntityModel(modelId), context.copy(), // use Id Builder for Planning CometIdBuilderFactory.usePlanningId()); } } catch (Exception e) { throw new CometException(this, "An error occured when requesting planning data for document.", e); } } else { throw new CometException(this, "Document Id is null or empty."); } return result; }
Find statement label
You may want to have a user readable label for your find statement instead of the Java method name. This can easily be achieved with the @PubServerMethod label attribute:
@PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Search by label" ) public List<Bucket> findRootBucketsByLabel( // etc. ...See screenshot below for the effect.
Search field label
By using the @PubServerMethodParameter name attribute, the label of search input fields can be defined:
@PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Search by label" ) public List<Bucket> findRootBucketsByLabel( @PubServerMethodParameter String modelId, @PubServerMethodParameter Context context, @PubServerMethodParameter( name="Product label") String searchLabel) throws CometException { // etc. ...
Note: the space for labels is very limited in the InDesign product panel, only about 7 to 10 characters can be shown. The full label is always shown in the tooltip, when the mouse pointer is moved over the label text field.
Default value
Default values for the input text fields can be set with the @PubServerMethodParameter defaultValue attribute:
@PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Search by label" ) public List<Bucket> findRootBucketsByLabel( @PubServerMethodParameter String modelId, @PubServerMethodParameter Context context, @PubServerMethodParameter( name="Product label", defaultValue=Please enter search criteria") String searchLabel) throws CometException { // etc. ...
More search criteria
Find statement methods support up to 4 search parameters. In addition to the (mandatory) modelId and context parameter, you may define zero to four String parameters for search criteria.
@PubServerMethod( type=PluginMethod.MethodType.FIND_STATEMENT, label="Detail search") public List<Bucket> productDetailSearch( @PubServerMethodParameter String modelId, @PubServerMethodParameter Context context, @PubServerMethodParameter(name="ID") String id, @PubServerMethodParameter(name="Label") String label, @PubServerMethodParameter(name="Label") String alternativeLabel, @PubServerMethodParameter(name="Market") String market ) throws CometException { // etc. ...Note: you can use the same label for several search parameters (like shown in this example), but of course not the same Java parameter name.
ProductDataMapping
Starting with PublishingServer version 4.1.5 Build #1199, you can implement custom data mapping classes for products.
These classes can be configured as the project default data mapping, and will be used in all situations, when EntityData is mapped to Product (unless implemented inline in find statements as shown above in some examples).
Basically, a ProductDataMapping implementation is
- a PubServerMethod with type PluginMethod.MethodType.PRODUCT_DATA_MAPPING
- implementation of the ProductDataMapping interface defined in the com.priint.pubserver.comet.bridge.datamapping package
Interface Overview
The ProductDataMapping interface defines
- one method to map list of data derived from EntityData to a list of products
- one method for each type derived from EntityData to map a particular instance of this type to a product
public interface ProductDataMapping { public <T extends EntityData> List<Product> entitiesToProducts( List<T> entities, EntityData parent, EntityModel model, Context context, CometIdBuilder idBuilder) throws CometException; public Product createProductFromBucket( Bucket bucket, EntityModel model, EntityData parent, Context context, CometIdBuilder idBuilder) throws CometException; public Product createProductFromCord( Cord cord, EntityModel model, EntityData parent, Context context, CometIdBuilder idBuilder) throws CometException; // etc. }
ProductDataMapping Implementation
Usually, developers only want to override certain aspects of data mapping. To ease the implementation of custom data mapping classes, a default (abstract) implementation of the ProductDataMapping interface is provided in the SDK, which is also base for the standard data mapping delivered with the PublishingServer.
The minimal implementation of a custom data mapping would be:
@Stateless(mappedName=CustomDataMappingPlugin.MAPPED_NAME) @PubServerPlugin @LocalBean public class CustomDataMappingPlugin extends ProductDataMappingDefault implements ProductDataMapping, PluginControl { public static final String MAPPED_NAME = "com.priint.pubserver.custom.datamapping.CustomDataMappingPlugin"; // custom plugins must override the entititesToProduct method, even if this (as shown) // just delegates to the default / super class implementation, otherwise the Plugin // wont be registered properly as ProductDataMapping plugin. @Override @PubServerMethod( type=PluginMethod.MethodType.PRODUCT_DATA_MAPPING, label="Custom Data Mapping", description="Custom Description") public <T extends EntityData> List<Product> entitiesToProducts( @PubServerMethodParameter(name="entites") List<T> entities, @PubServerMethodParameter(name="parent") EntityData parent, @PubServerMethodParameter(name="model") EntityModel model, @PubServerMethodParameter(name="context") Context context, @PubServerMethodParameter(name="idBuilder") CometIdBuilder idBuilder) throws CometException { return super.entitiesToProducts(entities, parent, model, context, idBuilder); } }
Id Builder
Because setting up proper IDs is a crucial part of data mapping, an interface and some default implementations are provided in the PubServerSDK for this.
Usually
- there should be no need to implement own Id Builders
- there should be no need to override the Id Builder instance provided to product data mapping method calls (though in certain situations it may be neccessary to ignore the instance provided to the method call).
Products have 4 ID properties, though in PublishingServer environment, only the last ("StringId", alphanumerical Id) has semantic meaning.
The general pattern to set product IDs should be
CometIdBuilder idBuilder; // provided to method call EntityData entity; // from request result, e.g. Bucket, Text, ... Product product = new Product(); product.setId(1); // must be non-zero, no further semantic product.setId2(0); // usually ignored product.setId3(0); // usually ignored product.setStringId(idBuilder.createEntityId(entity)); // or, to include parent IDs: EntityData parent; product.setStringId(idBuilder.createEntityId(entity, parent));
The following IdBuilders are included in the standard distribution:
// use the Bucket resp. Content entity IDs (for planning data also): CometIdBuilder idBuilder = CometIdBuilderFactory.useBucketId(); // use Planning IDs for planning records: CometIdBuilder idBuilder = CometIdBuilderFactory.usePlanningId(); // use Bucket IDs for planning records and the Planning IDs as // parent IDs: CometIdBuilder idBuilder = CometIdBuilderFactory.useBucketAndPlanningId();
Configuration
Configuration using Panel Config Editor
Starting with
- PubServer 4.1.6 Build #745 or
- PubServer 4.1.5.1 Build #2463
In the Comet Explorer, navigate to your project (e.g. demo), open InDesign Desktop Panels and right-click on Product Pool. Choosing the Edit Panel Context Criteria entry opens the Panel Config Editor:
In the Eitor, choose the Find Statements tab.
Find statements can be disabled or enabled via drag & drop, also the order of enabled find statements can be controlled via drag & drop.
Since this editor show find statements currently registered as PubServer PlugIns only, you can also decide, whether unknown statements (not configured or deployed in the future) should be shown or not:
Configuration using XML Files
The XML configuration file responsible for storing product panel configuration can be found in the repository in
com.priint.pubserver.comet.config.CometConfiguration.CLIENT.PROJECT.panel.productpoolName of the file is config.xml. Using the Repository Explorer, the configuration can be changed by directly editing the XML file:
The panel configuration file contains a custom object of type CometProductPanelConfig:
<con:PluginConfig ...>
<con:name>config.xml</con:name>
<con:type>CometProductPanelConfig</con:type>
<con:description>0 [CometProductPanelConfig]</con:description>
<con:custom>
<comet:productPanelConfig>
<comet:id>0</comet:id>
<!-- etc ... -->
In this section, several aspects of the panel can be configured.
findStatementsVisibleByDefault
To control the default visibility of statements, use the findStatementsVisibleByDefault property:
<!-- don't show statements not explicitly set to enabled: -->
<comet:findStatementsVisibleByDefault>false</comet:findStatementsVisibleByDefault>
<!-- do show statements not explicitly set to disabled: -->
<comet:findStatementsVisibleByDefault>true</comet:findStatementsVisibleByDefault>
activeFindStatements
To enable certain find statements, use the activeFindStatements property:
<comet:activeFindStatements> <comet:findStatement> <pl:pluginMappedName> com.priint.pubserver.plugins.pubplanner.findstatements.FindStatement </pl:pluginMappedName> <pl:methodName>findRootBucketsByLabel</pl:methodName> <pl:label>Find bucket by label</pl:label> <pl:parameters name="modelId" description="" defaultValue="" type="java.lang.String"/> <pl:parameters name="context" description="" defaultValue="" type="com.priint.pubserver.plugin.entitydata.Context"/> <pl:parameters name="searchLabel" description="" defaultValue="" type="java.lang.String"/> </comet:findStatement> <comet:findStatement> <!-- more find statements ... --> </comet:activeFindStatements>The activeFindStatements element contains a list of elements of type PluginMethod. Each PluginMethod refers to one method implemented in a PubServer Plugin with PluginMethod.MethodType.FIND_STATEMENT.
To identifiy find statements, the following information is required:
- pluginMappedName: the mapped name of the PubServer Plugin, which defines the find statement method
- methodName: the name of the find statement method
- parameters: zero, one or several parameters. Number, type and order of the parameters must match the parameters of the respective method. Therefore, the type attribute must be set (either qualified or simple name of the Java class), all other attributes (name, description, defaultValue etc.) are optional.
- label: label for the entry
inactiveFindStatements
To explicitly disable find statements (regardless of the findStatementsVisibleByDefault setting), use the inactiveFindStatements property.
Type and structure of this element is exactly the same like activeFindStatements (in this example, we use the short notation for method parameters):
<comet:inactiveFindStatements> <comet:findStatement> <pl:pluginMappedName> com.priint.pubserver.plugins.pubplanner.findstatements.FindStatement </pl:pluginMappedName> <pl:methodName>findRootBucketsByLabel</pl:methodName> <pl:label>Find bucket by label</pl:label> <pl:parameters type="String"/> <pl:parameters type="Context"/> <pl:parameters type="String"/> </comet:findStatement> <comet:findStatement> <!-- more find statements ... --> </comet:inactiveFindStatements>