How to register and use a characteristic value provider with parameters
Introduction
Use the SDK to create new plugin, contribute value provider implementation and add value provider to a characteristic.
Create Plugin using SDK
Create new plug-in project similar to "com.heiler.ppm.customizing.sample.valueProvider" and add required dependencies.
Sample plugin is present under sdk→examples→customizing.
Add Extension in MANIFEST.MF
Open Extensions
add extension for "com.heiler.ppm.charateristic.core.characteristicsValueProvider"
Add valueProvider
Identifier : intgerValueProvider
Label : %valueProvider.text (Localized text)
dataType : INTEGER
providerFactory : SampleIntegerCharacteristicValueProviderFactory
Contribute the characteristic value provider
Create class with name: "SampleIntegerCharacteristicValueProviderFactory" in package: "com.heiler.ppm.customizing.sample.valueProvider.integer", implements interface: "CharacteristicValueProviderFactory".
CharacteristicValueProviderFactory: Creates new instance of CharacteristicValueProvider.
import com.heiler.ppm.characteristic.core.valueProvider.CharacteristicValueProvider;import com.heiler.ppm.characteristic.core.valueProvider.CharacteristicValueProviderFactory;import com.heiler.ppm.std.core.entity.list.EntityItemList;public class SampleIntegerCharacteristicValueProviderFactory implements CharacteristicValueProviderFactory{ @Override public CharacteristicValueProvider createValueProvider( EntityItemList itemList ) { return new SampleIntegerCharacteristicValueProvider( itemList ); }}Create class with name "SampleIntegerCharacteristicValueProvider" in package "com.heiler.ppm.customizing.sample.valueProvider.integer", implements interface: "CharacteristicValueProvider".
CharacteriticValueProvider: Provides characteristic values and check for a valid value.
Provide the implementation of interface Value inside the SampleIntegerCharacteristicValueProvider itself.
import java.util.ArrayList;import java.util.Collection;import java.util.HashSet;import java.util.List;import java.util.Locale;import java.util.Set;import com.heiler.ppm.characteristic.core.record.CharacteristicRecord;import com.heiler.ppm.characteristic.core.valueProvider.CharacteristicValueProvider;import com.heiler.ppm.lookup.core.LookupValue;import com.heiler.ppm.std.core.entity.list.EntityItemList;@SuppressWarnings( "unused" )public class SampleIntegerCharacteristicValueProvider implements CharacteristicValueProvider{ public SampleIntegerCharacteristicValueProvider( EntityItemList itemList ) { // } @Override public Collection< Value > getValues( LookupValue language, CharacteristicRecord charRecord ) { List< Value > values = createValues(); return values; } @Override public boolean containsValue( LookupValue language, CharacteristicRecord charRecord, Object value /*actual charateristic record value*/ ) { // make sure values are of datatype Long for Integer type characteristics Set< Long > values = new HashSet(); values.add( 1024L ); values.add( 2048L ); values.add( 4096L ); return values.contains( value ); } @SuppressWarnings( "nls" ) private List< Value > createValues() { List< Value > values = new ArrayList(); // make sure values are of datatype Long for Integer type characteristics Value v1 = new ValueImpl( 1024L, "1 MB" ); Value v2 = new ValueImpl( 2048L, "2 MB" ); Value v3 = new ValueImpl( 4096L, "4 MB" ); values.add( v1 ); values.add( v2 ); values.add( v3 ); return values; } public static class ValueImpl implements Value { private String label; private Object value; public ValueImpl( Object value, String label ) { this.value = value; this.label = label; } @Override public Object getValue() { return this.value; } @Override public String getLabel( Locale locale ) { return this.label; } }}Deploy the plugin and restart Product 360 server
export the plugin as deployable plug-ins and fragments.
Deploy exported jar inside server → plugins folder
We are good to start the server
Attaching value provider to a characteristic
Characteristic value provider can be attached In characteristic modeling detail view.
Characteristic UI showing the provided values
Provided values will be available to select in the dropdown.
DepedentLookup Characteristic
Introduction
Create lookups lookup values
Country
State
Setup of Lookup Value Reference
|
referencing lookup |
referenced lookup |
business case |
|
Country |
State |
A country can have multiple states |
Navigate to lookup context view
Add the referenced values for desired lookup value.
There are two ways you can add referenced values for a lookup value:
Include values table : Only selected values can be referenced.
Exclude values table : All the values can be referenced except selected values.
Refer Importing lookups and lookup value references documentation for importing lookup references.
Contribute the country to state dependent characteristics to value provider
class name: "ParentReferencingChildLookupValueProviderFactory" package: "com.heiler.ppm.customizing.sample.valueProvider.parentchild" interface: "CharacteristicValueProviderFactory".
package com.heiler.ppm.customizing.sample.valueProvider.parentchild;import com.heiler.ppm.characteristic.core.valueProvider.CharacteristicValueProvider;import com.heiler.ppm.characteristic.core.valueProvider.CharacteristicValueProviderFactory;import com.heiler.ppm.std.core.entity.list.EntityItemList;public class ParentReferencingChildLookupValueProviderFactory implements CharacteristicValueProviderFactory{ @Override public CharacteristicValueProvider createValueProvider( EntityItemList itemList ) { return new ParentReferencingChildLookupValueProvider( itemList ); }} class name: "ParentReferencingChildLookupValueProvider" package: "com.heiler.ppm.customizing.sample.valueProvider.parentchild" interface: "CharacteristicValueProvider".
package com.heiler.ppm.customizing.sample.valueProvider.parentchild;import java.util.Collection;import java.util.HashSet;import java.util.Locale;import java.util.Set;import java.util.stream.Collectors;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.eclipse.core.runtime.CoreException;import com.google.gson.JsonElement;import com.google.gson.JsonObject;import com.google.gson.JsonParser;import com.heiler.ppm.characteristic.core.record.CharacteristicRecord;import com.heiler.ppm.characteristic.core.valueProvider.CharacteristicValueProvider;import com.heiler.ppm.commons.RuntimeCoreException;import com.heiler.ppm.lookup.core.Lookup;import com.heiler.ppm.lookup.core.LookupValue;import com.heiler.ppm.security.core.SecurityComponent;import com.heiler.ppm.std.core.entity.list.EntityItemList;public class ParentReferencingChildLookupValueProvider implements CharacteristicValueProvider{ private Locale locale; private static final String PARENT_CHARACTERISTIC = "parentCharacteristic"; //$NON-NLS-1$ private static final Log LOG = LogFactory.getLog( ParentReferencingChildLookupValueProvider.class ); public ParentReferencingChildLookupValueProvider( @SuppressWarnings( "unused" ) EntityItemList itemList ) { this.locale = SecurityComponent.getImpersonator() .getLoginToken() .getLocale(); } @Override public Collection getValues( LookupValue language, CharacteristicRecord characteristicRecord ) { Set< LookupValue > dependentLookupValues = fetchDependentLookupValues( language, characteristicRecord ); return dependentLookupValues.stream() .map( lookupValue -> new ValueImpl( lookupValue, lookupValue.getName( this.locale ) ) ) .collect( Collectors.toList() ); } @Override public boolean containsValue( LookupValue language, CharacteristicRecord characteristicRecord, Object value ) { Set< LookupValue > dependentLookupValues = fetchDependentLookupValues( language, characteristicRecord ); return dependentLookupValues.contains( value ); } private Set< LookupValue > fetchDependentLookupValues( LookupValue language, CharacteristicRecord characteristicRecord ) { Lookup lookup = characteristicRecord.getCharacteristic() .getLookup(); CharacteristicRecord parent = getParentCharacteristicRecord( characteristicRecord ); Set< LookupValue > values = new HashSet(); if ( parent != null ) { parent.getValues( language ) .forEach( lookupValue -> { addLookupValueReferences( lookup, values, lookupValue ); } ); } //In case parent is null then by default all the values present in the characteristic lookup should be returned else if ( lookup != null ) { Collection< LookupValue > lookUpValues = lookup.getValues(); values.addAll( lookUpValues ); } return values.stream() .filter( v -> v.isActive() ) .collect( Collectors.toSet() ); } private void addLookupValueReferences( Lookup lookup, Set< LookupValue > values, Object lookupValue ) { LookupValue parentLookupValue = ( LookupValue ) lookupValue; try { Collection< LookupValue > lookupValueReference = parentLookupValue.getReferences( lookup ); values.addAll( lookupValueReference ); } catch ( CoreException e ) { throw new RuntimeCoreException( e ); } } private CharacteristicRecord getParentCharacteristicRecord( CharacteristicRecord characteristicRecord ) { CharacteristicRecord parent; if ( characteristicRecord.getCharacteristic() .getValueProviderParameter() != null ) { parent = getRequiredCharacteristicRecord( characteristicRecord, characteristicRecord.getCharacteristic() .getValueProviderParameter() ); } else { parent = characteristicRecord.getParent(); } return parent; } private CharacteristicRecord getRequiredCharacteristicRecord( CharacteristicRecord characteristicRecord, String parameter ) { CharacteristicRecord parent = characteristicRecord.getParent(); JsonObject charParameter = parseStringtoJson( parameter ); String parentRefParam = ( charParameter != null && charParameter.get( PARENT_CHARACTERISTIC ) != null ) ? charParameter.get( PARENT_CHARACTERISTIC ) .getAsString() : null; return getParent( parent, parentRefParam ); } private CharacteristicRecord getParent( CharacteristicRecord parent, String parentRefParam ) { if ( parent == null ) { return parent; } if ( parentRefParam != null && parent.getCharacteristic() .getIdentifier() .equals( parentRefParam ) ) { return parent; } return getParent( parent.getParent(), parentRefParam ); } private JsonObject parseStringtoJson( String input ) { JsonObject jsonObject = null; JsonParser parser = new JsonParser(); try { JsonElement element = parser.parse( input ); if ( element.isJsonObject() ) { jsonObject = element.getAsJsonObject(); } } catch ( Exception e ) { LOG.error( e.getMessage() ); } return jsonObject; } public static class ValueImpl implements Value { private String label; private Object value; public ValueImpl( Object value, String label ) { this.value = value; this.label = label; } @Override public Object getValue() { return this.value; } @Override public String getLabel( Locale locale ) { return this.label; } }}class name: "ParentReferencingChildLookupValueProviderParameter" package: "com.heiler.ppm.customizing.sample.valueProvider.parentchild" interface: "ValueProviderParameter".
package com.heiler.ppm.customizing.sample.valueProvider.parentchild;import java.util.ArrayList;import java.util.Collection;import java.util.Locale;import com.heiler.ppm.characteristic.core.model.Characteristic;import com.heiler.ppm.characteristic.core.record.CharacteristicRecord;import com.heiler.ppm.characteristic.core.valueProvider.ValueProviderParameter;import com.heiler.ppm.lookup.core.LookupValue;/** * @author rkumhar */public class ParentReferencingChildLookupValueProviderParameter implements ValueProviderParameter{ @Override public Collection getParameters( LookupValue language, CharacteristicRecord characteristicRecord ) { Collection< ParameterValue > paramList = new ArrayList< ParameterValue >(); Collection< Characteristic > parentList = new ArrayList<>(); Characteristic characteristic = characteristicRecord.getCharacteristic(); checkForParent( characteristic.getParent(), parentList ); parentList.forEach( parentCharacteristic -> paramList.add( new ParameterValueImpl( parentCharacteristic.getIdentifier(), parentCharacteristic.getName( Locale.ENGLISH ) ) ) ); return paramList; } Collection< CharacteristicRecord > checkForParent( CharacteristicRecord characteristicRecord, Collection< CharacteristicRecord > parentCharRecordSetList ) { if ( characteristicRecord != null ) { parentCharRecordSetList.add( characteristicRecord ); if ( characteristicRecord.getParent() != null ) { checkForParent( characteristicRecord.getParent(), parentCharRecordSetList ); } } return parentCharRecordSetList; } Collection< Characteristic > checkForParent( Characteristic parentCharacteristic, Collection< Characteristic > parentCharList ) { if ( parentCharacteristic != null ) { parentCharList.add( parentCharacteristic ); if ( parentCharacteristic.getParent() != null ) { checkForParent( parentCharacteristic.getParent(), parentCharList ); } } return parentCharList; } public static class ParameterValueImpl implements ParameterValue { private String label; private Object value; public ParameterValueImpl( Object value, String label ) { this.value = value; this.label = label; } @Override public Object getValue() { return this.value; } @Override public String getLabel( Locale locale ) { return this.label; } }}Characteristic modeling:
Create characteristics like the following:
|
Characteristic |
Name |
Identifier |
Data type |
Lookup |
|
Parent characteristic |
Country -> state |
Country_to_State |
Lookup value |
Country |
|
Child characteristic |
Parent referencing child lookup |
parent_referencing_child_lookup |
Lookup value |
State |
Assigning value provider to characteristics in modelling UI
Value provider dropdown lists all the contributed value providers.
Parameter dropdown list appropriate values for corresponding value provider
Characteristic UI showing the provided values
Characteristic showing filtered values of state lookup.