Auto Assignment - Catalog data not including digital asset references
When importing the catalog data to the PIM Server(HPM) no digital asset reference is provided. The PIM objects do not have any information on digital assets assigned. Completely independent on the provision of the catalog data the digital assets are provided. The information to which catalog these digital assets belong to has to be provided anyway. In this case the naming of the digital asset files has to follow a predefined naming convention. The messages provided through MQ are handled on side the PIM Server by gathering information on the provided digital asset following the given naming convention.
Example: The file name contains the information that the asset has to be assigned to an item and the item number is given. In that case the PIM Server MQ handler would look for an item with the given item number in the given catalog (provided with the message). If the desired item is found, it will be assigned with the asset. (Of course, the configuration in hmm.properties for the corresponding catalog(master or supplier) should be be set with Auto Assignment.)
Since the message exists only on the MQ and will be removed after being processed without exception, therefore at the moment it is processed, the corresponding catalog data needs to be already in place. This means if you upload the digital assets first and upload the catalog data later, the assets will be assigned only if the post import mode is actived.
Naming convention
Desired components for assignment
Generally 5 components are relevant for asset assignment. These components of information help to identify the PIM object the digital asset should be assigned to and specify the type of assignment, where the PIM side media asset differ in type, quality and language.
Component |
Description |
Allowed values |
Must be provided for auto assignment |
Object type (OT) |
The type of repository object the identifier (see below) refers to. In the standard PIM Server this could |
"Product", "Article", "Variant" |
Yes |
Object indentifier (ID) |
The alphanumeric, unique identifier of the PIM object to which the asset should be assigned. |
Any alphanumeric string matching the rules defined |
Yes |
Media asset type (TY) |
Media asset type to be used to qualify the Media Asset assigned to the object specified (see above). |
e.g. "normal", "thumbnail", "data_sheet", "logo" |
Yes |
Media asset quality (QU) |
Media asset quality to be used to qualify the Media Asset assigned to the object specified (see above). |
e.g. "originalimage", "others" |
No |
Media asset language (LG) |
Language to be used to qualify the Media Asset assigned to the object specified (see above). |
e.g. "de", "deu", "ger" or "7" in case of German, |
Yes |
The value used for Media asset type and language have to correspond with the specification of the enumerations in the PIM Server repository. The enum entries are uniquely qualified through their "key", "label"(language dependent), "external-code", or one of the "keySynonyms"(language independent).
Information about Media Asset Quality needs not to be provided, because the Auto Assignment will assign the asset to the corresponding PIM object always with default quality("originalimage" or also called "master image") and all at the moment existing derivatives, and if an new derivative of such asset is created laterly in Media Manager, then another JMS(with topic "NewDerivative") will complete the further derivative assignment for the corresponding PIM object.
Encode components in asset file name
The file name (excluding the "." and the file's suffix) of the digital asset is used to encode these components of information. The components are separated by a predefined separator which is configurable. For the separator a character should be chosen not used in the values of the components.
That means a file might consist of the following information: "OT_ID_TY_LG.jpg" and looks like this: "Article_A123456_thumbnail_de.jpg". In that case a simple "Split" using "_" as a separator would lead to an array with 4 elements. The indexes 1 = OT; 2 = ID; 3 = TY; 4= LG.
In many cases the whole qualification shown here is not neccessary and possibly too complex. Therefore the rules of the file names' encoding will be configurable. It is possible to specify a default value for one or more of the components (all except the identifier are possible to use a default value for).
For the remaining components, an one-based index indicates the position of the component in the name after splitting it using the separator.
See the configuration section for more examples.
Change in 7.0.05.00
Since the PIM 7.0.05.00 the filename is allowed to contain irrelevant parameter which will be ignored by component check for auto assignment. And such information should not be arranged with the indices which are predefined for the above mentioned components. For example, if the settings for auto assignment are predefined in hmm.properties like following:
MasterCatalog.autoAssignment.index.objectType=1
MasterCatalog.autoAssignment.index.objectIdentifier=2
MasterCatalog.autoAssignment.index.mediaAssetType=3
MasterCatalog.autoAssignment.index.mediaAssetLanguage=4
Then the auto assginment can perform correctly by the asset wtih filename "Article_A123456_thumbnail_de.jpg" or "Article_A123456_thumbnail_de_irrelevantParameter.jpg", but can not be performed by "Article_A123456_thumbnail_irrelevantParameter_de.jpg", because the index 4 is predefined for media asset language, and the "irrelevantParameter" can not be parsed to a defined language, therefore it leads to an exception.
Catalog data first
In this scenario the catalog data is imported in the PIM Server first, then the digital assets are uploaded in the Media Manager in following ways:
For master catalog: directly via the PIM desktop or Media Manager application(nativ medias or web application).
For supplier catalog: in a ZIP file (through Supplier Portal (HSX)).
The asset upload action triggers a workflow in Media Manager which places messages with the topic "AssignDocument" on the message queue. These messages are then received and processed by the PIM Server. The source filename is taken from the message and combinated with the other configurations in hmm.properties to find the corresponding PIM object which will be then assigned with the asset, whose identifier(PKOM_PNR) is also contained in the message.
Digital assets first(Post Import mode) - only for supplier catalog
In this scenario the digital assets are uploaded to the Media Manager firstly, the JMS messages are received by the PIM Server but there is no catalog data yet to which the uploaded digital assets can be assinged. Nothing happens (from an user's point of view) and the message is removed from queue.
Then after the catalog data is imported in PIM Server, a post import step is executed which calls connector API method to fetch from Media Manager datebase for relevant associations between following information to perform auto assignment.
the identifier(PKOM_PNR) of digital asset.
the file name of digital asset: file name of the digital asset
the catalogID to which the digital asset belongs to.
This post import mode is only avaialbe for supplier catalog and has to happen via Supplier Portal (HSX), which uses the Media Manager hot folder to upload the assets, because only thus the above mentioned association can be stored in Media Manager datebase.
If you are sure never to upload the catalog data after the digital assets you can turn off the post import step.
Customization
Since PIM 7.0.04.00 there are two extension points ObjectFinder and Assigner which allows that customer can add contributions (extensions) to perform the auto assignment with desired implement.
Standard Process
Configuration
The ID of the corresponding contributions should be used in hmm.properties to identify the active extention contributions. For more information please read: Configuration for Auto Assignment.
Extention points
ObjectFinder
ObjectFinder is responsible for detecting all assginment informations which contain each object to assign, the corresponding media asset identifier and all parameters during assignment. There are two available standard ObjectFinider implements which can be set as actived in hmm.properties to switch auto assignment between case sensitive and case insensitive by finding the corresponding PIM object to assign:
standardCaseInsensitiveObjectFinder
standardCaseSensitiveObjectFinder
As default the standardCaseInsensitiveObjectFinder(case insensitive) is actived to search the corresponding PIM object by object identifier(e.g. item number) with case insensitive, and like the previous version, all other search field(objectType, MediaAssetType and languageType) work always with case insensitive. The API method ObjectFinder.isCaseSensitive() indicates whether case is sensitive and is used also in auto assignment by Post-Import mode to find assets by file name from media manager.
The default ObjectFinider can be replaced by a custom one, for that the extension point com.heiler.ppm.mediaasset.server.opasg.objectFinder is provided. The extension point expects an identifier and a java class which implements the interface ObjectFinder. The identifier has to be unique and will be used in the configuration file(hmm.properties) to identify the actived objectFinder. If you create your own objectFinder, you can
extend your class from the default implementation ObjectFinderBaseImpl. This class implements the corresponding interface and uses all standard configuration and JMS setting for auto assignment, but the abstract method resolveObjectsToAssign(CatalogProxy, String, String) should be implemented to get all objects to assign.
or implement your class from the interface ObjectFinder only if you have special Logic concernig configuration and name convention.
Noteworthy things
If you write your own ObjectFinder by extending ObjectFinderBaseImpl, you should find the corresponding entityProxy(ies) with given object information which is stored as the parameter objectIdentfier. Use case example: all standard configuration(hmm.properties and name convention) will be used, and the asset file name contains no object number(e.g. item number) from PIM Core, but the corresponding EAN(GTIN) value as object identifier.
If you write your own ObjectFinder by implementing the interface ObjectFinder, you should implement the interface method find(...) to return a list of the AssetAssignment which contains each assignment mapping information. And this method is called in AutoAssignmentTask which provides all JMS message information as its parameters:
mediaAssetIdentifier: id of the media asset from Media Manager
fileName: file name of the uploaded asset which contains corresponding useful information according to the name convertion
catalogID: id of the catalog to which the to assigned PIM object belongs
additionalProperties: all addtional properties of JMS message.
A code example from the default StandardCaseSensitiveObjectFinder is shown below:
/**
* Standard implement of {@link ObjectFinder} to find the corresponding object(s) for auto assignment
* @author jyu
* @since 7.0.04
*/
public
class
StandardCaseSensitiveObjectFinder
extends
ObjectFinderBaseImpl
{
@Override
public
boolean
isCaseSensitive()
{
return
true
;
}
@Override
protected
List< EntityProxy > resolveObjectsToAssign( CatalogProxy catalogProxy, String objectType,
String objectIdentifier )
throws
CoreException
{
List< EntityProxy > entityProxies =
new
ArrayList< EntityProxy >();
//currently it can only be an articleproxy
Short entityId = getEntityId( objectType );
EntityProxy entityProxy =
new
ArticleProxy( entityId, catalogProxy, objectIdentifier );
String entityTypeIdentifier = entityProxy.getEntityType()
.getIdentifier();
EntityManager manager = EntityManagementComponent.getManagerRegistry()
.getEntityManager( entityTypeIdentifier );
ResolveItemsParam param = ResolveItemsParam.createFromProxy( entityProxy );
entityProxy = manager.resolveItem( param );
if
( entityProxy !=
null
)
{
entityProxies.add( entityProxy );
}
return
entityProxies;
}
}
As a comparison the following code shows the implementation for StandardCaseInsensitiveObjectFinder which uses the search framework to find the desired object. Customer can implement a similar solution for his own extension in the way that should build a searchExpression for the corresponding FieldPathExpression to the "objectIdentifier" value.
public
class
StandardCaseInsensitiveObjectFinder
extends
ObjectFinderBaseImpl
{
private
static
String ARTICLE_TYPE_CATALOG_PROXY =
"ArticleType.CatalogProxy"
;
//$NON-NLS-1$
@Override
public
boolean
isCaseSensitive()
{
return
false
;
}
@Override
protected
List< EntityProxy > resolveObjectsToAssign( CatalogProxy catalogProxy, String objectType,
String objectIdentifier )
throws
CoreException
{
Expression expression = createEqualExpression( catalogProxy, objectType, objectIdentifier );
return
executeSearch( catalogProxy, expression );
}
private
Expression createEqualExpression( CatalogProxy catalogProxy, String objectType, String objectIdentifier )
{
//search expression
FieldPath catalogFieldPath =
new
FieldPath( ARTICLE_TYPE_CATALOG_PROXY );
EqualExpression equalCatalogExpression =
new
EqualExpression(
new
FieldPathExpression( catalogFieldPath ),
new
ValueExpression( catalogProxy ) );
//get EqualExpression for article entity id
FieldPath entityIdFieldPath =
new
FieldPath( ArticleCoreConst.FIELD_TYPE_ARTICLE_ENTITYID );
Short entityId = getEntityId( objectType );
Expression equalEntityIdExpression =
new
EqualExpression(
new
FieldPathExpression( entityIdFieldPath ),
new
ValueExpression( entityId ) );
//get EqualExpression for article identifier
FieldPath identifierFieldPath =
new
FieldPath( ArticleCoreConst.FTI_ARTICLE_SUPPLIERAID );
Expression equalIdentifierExpression =
new
EqualStringExpression(
new
FieldPathExpression( identifierFieldPath ),
new
ValueExpression( objectIdentifier ),
false
);
//combinate the above both expression
Expression rootExpression = equalCatalogExpression.and( equalEntityIdExpression )
.and( equalIdentifierExpression );
return
rootExpression;
}
private
List< EntityProxy > executeSearch( CatalogProxy catalogProxy, Expression expression )
throws
CoreException
{
List< EntityProxy > entityProxyList =
null
;
String articleDataSource = catalogProxy.getDataSourceOfElements()
.getIdentifier();
SearchParameters parameters =
new
SearchParameters( articleDataSource, ArticleCoreConst.ENTITY_TYPE_ARTICLE,
expression );
// create and execute the search
SearchService searchService = EntitySearchComponent.getSearchService();
try
{
EntityProxy[] proxies = searchService.searchAsEntityProxies(
new
NullProgressMonitor(), parameters,
null
);
entityProxyList = Arrays.asList( proxies );
return
entityProxyList;
}
catch
( InterruptedException ie )
{
if
( log.isErrorEnabled() )
{
String errorMessage =
"InterruptedException while searching target objects to assign: "
+ ie;
//$NON-NLS-1$
logProblem( Categories.SUMMARY, IStatus.ERROR,
0
, errorMessage );
}
}
return
entityProxyList;
}
}
Assigner
Assigner is responsible for performing the auto assignment according to the information which the find method of the active ObjectFinder contribution returns. There is a StandardAssigner which performs the auto assignment with default logic and can be replaced by a custom assigner. To replace the assigner, the extension point com.heiler.ppm.mediaasset.server.opasg.assigner is provided. The extension point expects an identifier and a java class which implements the interface Assigner. The identifier has to be unique and will be used in the configuration file(hmm.properties) to identify the actived assigner. And you should implement the interface, if you create your own assigner to perform assignment with a special Logic. E.g. you have addtional primary key to identify an media asset document which is assigned to object.
A code example from the default StandardAssigner is shown below:
/**
* Standard implement of {@link Assigner} to perform auto assignment
* @author jyu
* @since 7.0.04
*/
public
class
StandardAssigner
implements
Assigner
{
@Override
public
void
performAssignment( IProgressMonitor progressMonitor, ProblemLog problemLog, List< AssetAssignment > assignments )
throws
CoreException
{
FeedbackProcessor feedbackProcessor =
new
ProblemLogFeedbackProcessor( problemLog );
AssetAssignment[] assertAssignmentArray = assignments.toArray(
new
AssetAssignment[assignments.size()] );
MediaAssetComponent.getMediaAssetAssignmentService()
.performAutoAssignment( progressMonitor, feedbackProcessor, assertAssignmentArray );
}
}