package gw.rating.rtm.valueprovider
uses gw.api.domain.covterm.CovTerm
uses gw.api.locale.DisplayKey
uses gw.api.productmodel.CovTermPattern
uses gw.api.productmodel.PolicyLinePattern
uses gw.api.upgrade.PCCoercions
uses gw.lang.reflect.IType
uses gw.rating.flow.util.CovTermValueVisitor
uses gw.rating.flow.util.InScopeUsage
uses gw.rating.flow.util.RatingEntityGraphTraverser
uses gw.rating.flow.util.TypeMaps
uses gw.rating.rtm.domain.PersistenceAdapter
uses gw.rating.rtm.matchop.CoverageParam
uses gw.rating.rtm.util.AvailableAttributePresenter
/**
*
* Value provider implementation for coverage term options of a specific coverage term
* of a specific policy line coverage configured in PC product model.
*
* This value provider should be used for rate table columns satisfying one of
* the following conditions:
*
* - A rate table column depends on another rate table column that contains coverage term code.
* - Two arguments are specified for this value provider: 1) coverage code, 2) coverage term code
*
* In both cases value provider will retrieve coverage term options of a specific coverage term,
* either from another column or the second argument.
*
* Example 1: When a value provider is configured with arguments -
* gw.rating.rtm.valueprovider.CovTermOptionValueProvider(PACollisionCov,PACollDeductible),
* rate table column does not need to depend on any other column in the rate table and
* will return all coverage term options under the coverage term identified by PACollDeductible
* code under coverage identified by PACollisionCov code.
*
* Example 2: When a value provider is configured without arguments -
* gw.rating.rtm.valueprovider.CovTermOptionValueProvider,
* rate table column must depend on another column in the rate table that defines
* coverage term code which in turn must depend on the column defining coverage code.
*
* This value provider should be usually used together with
* {@link gw.rating.rtm.valueprovider.CovTermValueProvider CovTermValueProvider} and
* {@link gw.rating.rtm.valueprovider.CoverageValueProvider CoverageValueProvider} value providers.
* In that case, a column that uses CovTermOptionValueProvider should depend
* on a column that uses CovTermValueProvider which in turn should depend on
* a column that uses CoverageValueProvider.
*
*/
class CovTermOptionValueProvider extends AbstractCovTermOptionValueProvider {
private var _covTermColumn : RateTableColumn as readonly CovTermColumn
private var _covColumn : RateTableColumn as readonly CovColumn
construct(column : RateTableColumn) {
super(column)
_covTermColumn = ColumnDefinition.DependsOn
_covColumn = _covTermColumn.DependsOn
}
/**
* Returns coverage term code.
*
* - When value provider agruments are specified, returns the second argument.
* - Otherwise, returns the parameter value according to the dependency chain (see Example 2 above).
*
*
* @see gw.rating.rtm.valueprovider.AbstractCovTermOptionValueProvider#getCovTermCode(KeyableBean)
*/
override function getCovTermCode(adapter : PersistenceAdapter) : String {
if (Arguments != null and Arguments.length > 1) {
return Arguments[1]
}
if (adapter == null) {
return null
}
return getDependsOnValue(_covTermColumn, adapter)
}
/**
* Returns coverage code.
*
* - When value provider agruments are specified, returns the first argument.
* - Otherwise, returns the parameter value according to the dependency chain (see Example 2 above).
*
*
* @see gw.rating.rtm.valueprovider.AbstractCovTermOptionValueProvider#getCovTermCode(KeyableBean)
*/
override function getCovCode(adapter : PersistenceAdapter) : String {
if (Arguments != null and Arguments.length > 0) return Arguments[0]
return getDependsOnValue(_covColumn, adapter)
}
protected function createDefaultAttributePresenter(cov : entity.CalcRoutineParameter) : AvailableAttributePresenter {
return new AvailableAttributePresenter(cov.Code, "CovTermOption", false, DisplayKey.get("Web.Rating.CovTermOptionValueProvider.CovTermOption"))
}
protected function covtermOptionIsAssignable(featureType : IType) : boolean {
// If the underlying column is a string, RTM permits all cov term options. So should we...BUT
// we don't want to return the CovTerms, only the option values.
var restriction = TypeRestrictionForAvailableAttributes
if (restriction.Count == 1 and restriction.single() == String) {
return not CalcStepValueDelegate.isCovTermType(featureType) // don't accept the CovTerm itself
and not CalcStepValueDelegate.isCoverageType(featureType) // don't include the Coverage either!
} else {
return TypeMaps.isAssignable(TypeRestrictionForAvailableAttributes, featureType)
}
}
override function availableAttributes(line : PolicyLinePattern, paramSet : CalcRoutineParameterSet) : List {
if (paramSet == null) {
return {}
}
var results = new RatingEntityGraphTraverser(paramSet).getImmutableTargetableElementsForParameterSet(paramSet)
if (Arguments == null or Arguments.IsEmpty) {
var covParams = paramSet.Parameters.where(\ p -> p.ParamType == "entity.Coverage")
var ret : List = {}
covParams.each(\ cov -> {
if (cov.CoveragePattern == null) {
ret.add(createDefaultAttributePresenter(cov))
} else {
var usages : List = {}
results.asMap().eachKeyAndValue(\ k, l -> usages.addAll(l.where(\ v -> v.Root == cov.Code.Code)))
usages = usages.where(\ v -> covtermOptionIsAssignable(v.FeatureType))
ret.addAll(usages.toTypedArray().map(\ u -> new AvailableAttributePresenter(u)).toList())
}
})
return ret
} else {
var coverages = paramSet.Parameters.where(\ p -> coveragePatternMatchesCoverageArgument(p)).map(\ c -> c.Code)
if (coverages.HasElements) {
// If we got here, we have an explicitly-typed Coverage whose code matches the one that was given
// as Argument[0]. In this case we want to allow corresponding CovTerm values to be inserted.
var usages : List = {}
results.asMap().eachKeyAndValue(\ k, l -> usages.addAll(l.where(\ v -> v.CovTermPattern != null)))
usages = usages.where(\ v -> covtermOptionIsAssignable(v.FeatureType))
if (Arguments != null and Arguments.length > 1 and Arguments[1] != null) {
// When we know argument 1, we should be able to restrict this completely.
var ret = usages.where(\ v -> v.CovTermPattern == PCCoercions.makeProductModel(Arguments[1])).toTypedArray().map(\ u -> new AvailableAttributePresenter(u)).toList()
return ret
} else {
// We can't fully restrict if we don't know Arguments[1]
return usages.toTypedArray().map(\ u -> new AvailableAttributePresenter(u)).toList()
}
} else {
// we have a specified Coverage, but nothing matches it.
// Should we be returning anything at all here???
var covParams = paramSet.Parameters.where(\ p -> p.ParamType == "entity.Coverage")
return covParams.map(\ cov -> createDefaultAttributePresenter(cov)).toList()
}
}
}
private function getDependsOnValue(column : RateTableColumn, adapter : PersistenceAdapter) : String {
if (column == null) return null
var value = adapter.getFieldValue(column.PhysicalColumnName)
if (value == null) return null
return value as String
}
override function getQueryParamValue(cov : Coverage) : String {
if (cov.CovTerms.IsEmpty) return null
return getCovTermValue(cov.CovTerms.first())
}
override function getQueryParam(cov : Coverage) : CoverageParam {
var value = getQueryParamValue(cov) // this gets the optionCode which is what we need to query the rate tables
if (value == null) return null; // don't make a wrapper if the value is null
return new CoverageParam(:codeIdentifier = value,
:patternCode = value)
}
private function getCovTermValue(covTerm : CovTerm) : String {
var visitor = new CovTermValueVisitor()
covTerm.Pattern.acceptVisitor(visitor)
return visitor.getValueAsString(covTerm)
}
override property get ArgumentsHelpText(): String {
return DisplayKey.get("Web.Rating.RateTableDefinition.ValueProvider.HelpText.CovTermOptionValueProvider")
}
}