diff --git a/src/main/java/io/cdap/plugin/successfactors/common/util/ExceptionParser.java b/src/main/java/io/cdap/plugin/successfactors/common/util/ExceptionParser.java index 36b5f55..710af5a 100644 --- a/src/main/java/io/cdap/plugin/successfactors/common/util/ExceptionParser.java +++ b/src/main/java/io/cdap/plugin/successfactors/common/util/ExceptionParser.java @@ -45,6 +45,7 @@ public class ExceptionParser { public static final int NO_VERSION_FOUND = 1; public static final int INVALID_VERSION_FOUND = 2; + public static final int INVALID_ASSOCIATED_ENTITY_NAME = 4; private static final String BROKEN_HYPERLINK = "Refer to https"; private static final String HTML_TAG = ""; diff --git a/src/main/java/io/cdap/plugin/successfactors/common/util/ResourceConstants.java b/src/main/java/io/cdap/plugin/successfactors/common/util/ResourceConstants.java index 20f9951..debbe80 100644 --- a/src/main/java/io/cdap/plugin/successfactors/common/util/ResourceConstants.java +++ b/src/main/java/io/cdap/plugin/successfactors/common/util/ResourceConstants.java @@ -26,6 +26,7 @@ public enum ResourceConstants { ERR_MISSING_PARAM_OR_MACRO_ACTION(null, "err.missing.param.or.macro.action"), ERR_INVALID_BASE_URL(null, "err.invalid.base.url"), ERR_FEATURE_NOT_SUPPORTED("CDF_SAP_ODATA_01500", "err.feature.not.supported"), + ERR_INVALID_ENTITY_CALL(null, "err.invalid.entityCall"), ROOT_CAUSE_LOG(null, "root.cause.log"), ERR_ODATA_SERVICE_CALL("CDF_SAP_ODATA_01532", "err.odata.service.call"), ERR_ODATA_ENTITY_FAILURE("CDF_SAP_ODATA_01534", "err.odata.entity.failure"), @@ -38,6 +39,7 @@ public enum ResourceConstants { ERR_CHECK_ADVANCED_PARAM(null, "err.check.advanced.parameter"), ERR_NOT_FOUND(null, "err.resource.not.found"), ERR_NO_COLUMN_FOUND(null, "err.no.column.found"), + ERR_UNSUPPORTED_ASSOCIATED_ENTITY(null, "err.unsupported.associated.entity"), ERR_BUILDING_COLUMNS(null, "err.building.columns"), DEBUG_NAVIGATION_NOT_FOUND(null, "debug.navigation.not.found"), DEBUG_NAV_PROP_NOT_FOUND(null, "debug.nav.prop.not.found"), diff --git a/src/main/java/io/cdap/plugin/successfactors/source/SuccessFactorsSource.java b/src/main/java/io/cdap/plugin/successfactors/source/SuccessFactorsSource.java index 8efe95b..ec8087e 100644 --- a/src/main/java/io/cdap/plugin/successfactors/source/SuccessFactorsSource.java +++ b/src/main/java/io/cdap/plugin/successfactors/source/SuccessFactorsSource.java @@ -171,7 +171,7 @@ private void attachFieldWithError(SuccessFactorsServiceException ose, FailureCol case HttpURLConnection.HTTP_BAD_REQUEST: failureCollector.addFailure(errMsg, ResourceConstants.ERR_CHECK_ADVANCED_PARAM.getMsgForKey()); break; - + case ExceptionParser.INVALID_ASSOCIATED_ENTITY_NAME: default: failureCollector.addFailure(errMsg, null); } diff --git a/src/main/java/io/cdap/plugin/successfactors/source/config/SuccessFactorsPluginConfig.java b/src/main/java/io/cdap/plugin/successfactors/source/config/SuccessFactorsPluginConfig.java index bab6de6..108a368 100644 --- a/src/main/java/io/cdap/plugin/successfactors/source/config/SuccessFactorsPluginConfig.java +++ b/src/main/java/io/cdap/plugin/successfactors/source/config/SuccessFactorsPluginConfig.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.util.regex.Pattern; + import javax.annotation.Nullable; /** @@ -45,9 +46,10 @@ public class SuccessFactorsPluginConfig extends PluginConfig { private static final String REFERENCE_NAME = "referenceName"; private static final String REFERENCE_NAME_DESCRIPTION = "This will be used to uniquely identify this source/sink " + "for lineage, annotating metadata, etc."; - private static final String ASSOCIATED_ENTITY_NAME = "associatedEntityName"; + public static final String ASSOCIATED_ENTITY_NAME = "associatedEntityName"; private static final String NAME_SCHEMA = "schema"; private static final String PAGINATION_TYPE = "paginationType"; + public static final String EXPAND_OPTION = "expandOption"; private static final String COMMON_ACTION = ResourceConstants.ERR_MISSING_PARAM_OR_MACRO_ACTION.getMsgForKey(); private static final Pattern PATTERN = Pattern.compile("\\(.*\\)"); private static final String SAP_SUCCESSFACTORS_ENTITY_NAME = "Entity Name"; @@ -78,6 +80,7 @@ public class SuccessFactorsPluginConfig extends PluginConfig { "All the fields must be comma (,) separated.\n") private final String selectOption; + @Name(EXPAND_OPTION) @Nullable @Macro @Description("List of navigation fields to be expanded in the extracted output data. For example: customManager. " + @@ -259,6 +262,12 @@ private void validateEntityParameter(FailureCollector failureCollector) { .withConfigProperty(ENTITY_NAME); } } + if (SuccessFactorsUtil.isNotNullOrEmpty(associateEntityName)) { + if (SuccessFactorsUtil.isNullOrEmpty(getExpandOption()) && !containsMacro(EXPAND_OPTION)) { + failureCollector.addFailure(ResourceConstants.ERR_INVALID_ENTITY_CALL.getMsgForKey(), null) + .withConfigProperty(ASSOCIATED_ENTITY_NAME); + } + } } /** diff --git a/src/main/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGenerator.java b/src/main/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGenerator.java index 45bea64..64b2979 100644 --- a/src/main/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGenerator.java +++ b/src/main/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGenerator.java @@ -23,6 +23,8 @@ import io.cdap.plugin.successfactors.common.util.SapAttributes; import io.cdap.plugin.successfactors.common.util.SuccessFactorsDataTypes; import io.cdap.plugin.successfactors.common.util.SuccessFactorsUtil; +import io.cdap.plugin.successfactors.source.config.SuccessFactorsPluginConfig; + import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute; import org.apache.olingo.odata2.api.edm.EdmComplexType; import org.apache.olingo.odata2.api.edm.EdmEntityType; @@ -297,25 +299,34 @@ private SuccessFactorsColumnMetadata buildSuccessFactorsColumnMetadata(String na * * @param entityName service entity name * @param expandOption all the selective expanded property names + * @param pluginConfig * @return {@code Schema} * @throws SuccessFactorsServiceException throws in following two cases * 1. if neither default nor expanded property were found in the given entity * name, * 2. if fails at apache olingo processing. */ - public Schema buildExpandOutputSchema(String entityName, String expandOption) throws SuccessFactorsServiceException { + public Schema buildExpandOutputSchema(String entityName, String expandOption, String associatedEntity, + SuccessFactorsPluginConfig pluginConfig) throws + SuccessFactorsServiceException { try { List columnDetailList = buildDefaultColumns(entityName); if (columnDetailList.isEmpty()) { throw new SuccessFactorsServiceException(ResourceConstants.ERR_NO_COLUMN_FOUND.getMsgForKey(DEFAULT_PROPERTY, - entityName)); + entityName, 4)); } List expandColumnDetailList = buildExpandedEntity(entityName, expandOption); if (expandColumnDetailList.isEmpty()) { - throw new SuccessFactorsServiceException(ResourceConstants.ERR_NO_COLUMN_FOUND.getMsgForKey(expandOption, + if (associatedEntity == null && !pluginConfig.containsMacro + (SuccessFactorsPluginConfig.ASSOCIATED_ENTITY_NAME)) { + throw new SuccessFactorsServiceException(ResourceConstants.ERR_NO_COLUMN_FOUND.getMsgForKey(expandOption, + entityName), 4); + } else if (!pluginConfig.containsMacro(SuccessFactorsPluginConfig.ASSOCIATED_ENTITY_NAME)) { + throw new SuccessFactorsServiceException(ResourceConstants.ERR_UNSUPPORTED_ASSOCIATED_ENTITY. + getMsgForKey(associatedEntity, entityName), 4); + } - entityName)); } columnDetailList.addAll(expandColumnDetailList); diff --git a/src/main/java/io/cdap/plugin/successfactors/source/service/SuccessFactorsService.java b/src/main/java/io/cdap/plugin/successfactors/source/service/SuccessFactorsService.java index cea6a1f..0780dc6 100644 --- a/src/main/java/io/cdap/plugin/successfactors/source/service/SuccessFactorsService.java +++ b/src/main/java/io/cdap/plugin/successfactors/source/service/SuccessFactorsService.java @@ -132,7 +132,7 @@ public Schema buildOutputSchema() throws SuccessFactorsServiceException, Transpo } } else if (SuccessFactorsUtil.isNotNullOrEmpty(pluginConfig.getExpandOption())) { return successFactorsSchemaGenerator.buildExpandOutputSchema(pluginConfig.getEntityName(), pluginConfig. - getExpandOption()); + getExpandOption(), pluginConfig.getAssociatedEntityName(), pluginConfig); } else { return successFactorsSchemaGenerator.buildDefaultOutputSchema(pluginConfig.getEntityName()); } @@ -282,8 +282,15 @@ public ODataFeed readServiceEntityData(Edm edm, Long skip, Long top) } } catch (EdmException | EntityProviderException | IOException ex) { - String errMsg = ResourceConstants.ERR_RECORD_PROCESSING.getMsgForKeyWithCode(pluginConfig.getEntityName()); - throw new SuccessFactorsServiceException(errMsg, ex); + if (pluginConfig.getAssociatedEntityName() != null) { + String errMsg = + ResourceConstants.ERR_UNSUPPORTED_ASSOCIATED_ENTITY. + getMsgForKey(pluginConfig.getAssociatedEntityName(), pluginConfig.getEntityName()); + throw new SuccessFactorsServiceException(errMsg, ex); + } else { + String errMsg = ResourceConstants.ERR_RECORD_PROCESSING.getMsgForKeyWithCode(pluginConfig.getEntityName()); + throw new SuccessFactorsServiceException(errMsg, ex); + } } catch (TransportException te) { String errMsg = ResourceConstants.ERR_RECORD_PULL.getMsgForKeyWithCode(pluginConfig.getEntityName()); errMsg += ExceptionParser.buildTransportError(te); diff --git a/src/main/resources/i10n/SuccessFactorsBatchSourceBundle.properties b/src/main/resources/i10n/SuccessFactorsBatchSourceBundle.properties index a8d2e69..9e432c5 100644 --- a/src/main/resources/i10n/SuccessFactorsBatchSourceBundle.properties +++ b/src/main/resources/i10n/SuccessFactorsBatchSourceBundle.properties @@ -12,6 +12,7 @@ root.cause.log=Root Cause: err.feature.not.supported=Entity 'Key' property based extraction is not supported. err.invalid.base.url=Please verify the provided base url is correct. Please contact the SAP administrator. err.invalid.credential=Please verify the connection parameters. Username or password is incorrect. +err.invalid.entityCall=Associated Entity must be used with the expand field. Please provide the Expand fields. ## SAP SuccessFactors - Design Time generic error err.odata.service.call={0} - {1} @@ -30,6 +31,9 @@ err.missing.dataservice.version=No data service version number found. Please ens ## SAP SuccessFactors - metadata processing related messages err.no.column.found=''{0}'' not found in the ''{1}'' entity. +err.unsupported.associated.entity=''{0}'' not found in the ''{1}'' entity. Please ensure that associated entity is \ +correct. Please check the property name in Admin Center > OData API Data Dictionary or entity metadata. + err.building.columns=Error while building ''{0}'' from service metadata for the given ''{1}'' entity. debug.navigation.not.found=''{0}'' navigation property not found from the ''{1}''. debug.nav.prop.not.found=''{0}'' navigation path not found in given entity ''{1}''. diff --git a/src/test/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGeneratorTest.java b/src/test/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGeneratorTest.java index e7b6f22..c40cc84 100644 --- a/src/test/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGeneratorTest.java +++ b/src/test/java/io/cdap/plugin/successfactors/source/metadata/SuccessFactorsSchemaGeneratorTest.java @@ -17,6 +17,8 @@ import io.cdap.cdap.api.data.schema.Schema; import io.cdap.plugin.successfactors.common.exception.SuccessFactorsServiceException; +import io.cdap.plugin.successfactors.source.config.SuccessFactorsPluginConfig; + import org.apache.olingo.odata2.api.edm.Edm; import org.apache.olingo.odata2.api.ep.EntityProvider; import org.apache.olingo.odata2.api.ep.EntityProviderException; @@ -28,6 +30,8 @@ import java.util.List; +import javax.annotation.Nullable; + public class SuccessFactorsSchemaGeneratorTest { private static Edm edm; @@ -74,8 +78,12 @@ public void testSelectWithExpandNames() throws SuccessFactorsServiceException { @Test public void testBuildExpandOutputSchema() throws SuccessFactorsServiceException { + SuccessFactorsPluginConfig pluginConfig = new SuccessFactorsPluginConfig("referenceName", + "baseUR", "entityName", "associateEntityName", "username", + "password", "filterOption", "selectOption", "expandOption", + "paginationType"); Schema outputSchema = generator.buildExpandOutputSchema("Benefit", - "eligibleBenefits"); + "eligibleBenefits", "associatedEntity", pluginConfig); int lastIndex = outputSchema.getFields().size() - 1; Assert.assertEquals("Schema field size is same.", 96, @@ -144,8 +152,13 @@ public void testInvalidEntityName() throws SuccessFactorsServiceException { @Test public void testInvalidExpandName() throws SuccessFactorsServiceException { - exception.expectMessage("'INVALID-NAVIGATION-NAME' not found in the 'Benefit' entity."); - generator.buildExpandOutputSchema("Benefit", "INVALID-NAVIGATION-NAME"); + SuccessFactorsPluginConfig pluginConfig = new SuccessFactorsPluginConfig("referenceName", + "baseUR", "entityName", "associateEntityName", "username", + "password", "filterOption", "selectOption", "expandOption", + "paginationType"); + exception.expectMessage("'assEntity' not found in the 'Benefit' entity."); + generator.buildExpandOutputSchema("Benefit", "INVALID-NAVIGATION-NAME", + "assEntity", pluginConfig); } private Schema getFieldSchema(List fieldList, String fieldName) {