use of org.apache.unomi.router.api.ImportConfiguration in project unomi by apache.
the class ImportConfigByFileNameProcessor method process.
@Override
public void process(Exchange exchange) throws Exception {
String fileName = exchange.getIn().getBody(GenericFile.class).getFileName();
String importConfigId = fileName.substring(0, fileName.indexOf('.'));
ImportConfiguration importConfiguration = importConfigurationService.load(importConfigId);
if (importConfiguration != null) {
logger.debug("Set a header with import configuration found for ID : {}", importConfigId);
exchange.getIn().setHeader(RouterConstants.HEADER_IMPORT_CONFIG_ONESHOT, importConfiguration);
} else {
logger.warn("No import configuration found with ID : {}", importConfigId);
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
}
}
use of org.apache.unomi.router.api.ImportConfiguration in project unomi by apache.
the class ProfileImportFromSourceRouteBuilder method configure.
@Override
public void configure() throws Exception {
logger.info("Configure Recurrent Route 'From Source'");
if (importConfigurationList == null) {
importConfigurationList = importConfigurationService.getAll();
}
ProcessorDefinition prDefErr = onException(BadProfileDataFormatException.class).log(LoggingLevel.ERROR, "Error processing record ${exchangeProperty.CamelSplitIndex}++ !").handled(true).process(new LineSplitFailureHandler()).onException(Exception.class).log(LoggingLevel.ERROR, "Failed to process file.").handled(true);
if (RouterConstants.CONFIG_TYPE_KAFKA.equals(configType)) {
prDefErr.to((KafkaEndpoint) getEndpointURI(RouterConstants.DIRECTION_FROM, RouterConstants.DIRECT_IMPORT_DEPOSIT_BUFFER));
} else {
prDefErr.to((String) getEndpointURI(RouterConstants.DIRECTION_FROM, RouterConstants.DIRECT_IMPORT_DEPOSIT_BUFFER));
}
// Loop on multiple import configuration
for (final ImportConfiguration importConfiguration : importConfigurationList) {
if (RouterConstants.IMPORT_EXPORT_CONFIG_TYPE_RECURRENT.equals(importConfiguration.getConfigType()) && importConfiguration.getProperties() != null && importConfiguration.getProperties().size() > 0) {
// Prepare Split Processor
LineSplitProcessor lineSplitProcessor = new LineSplitProcessor();
lineSplitProcessor.setFieldsMapping((Map<String, Integer>) importConfiguration.getProperties().get("mapping"));
lineSplitProcessor.setOverwriteExistingProfiles(importConfiguration.isOverwriteExistingProfiles());
lineSplitProcessor.setPropertiesToOverwrite(importConfiguration.getPropertiesToOverwrite());
lineSplitProcessor.setMergingProperty(importConfiguration.getMergingProperty());
lineSplitProcessor.setColumnSeparator(importConfiguration.getColumnSeparator());
lineSplitProcessor.setHasHeader(importConfiguration.isHasHeader());
lineSplitProcessor.setHasDeleteColumn(importConfiguration.isHasDeleteColumn());
lineSplitProcessor.setMultiValueDelimiter(importConfiguration.getMultiValueDelimiter());
lineSplitProcessor.setMultiValueSeparator(importConfiguration.getMultiValueSeparator());
lineSplitProcessor.setProfilePropertyTypes(profileService.getTargetPropertyTypes("profiles"));
String endpoint = (String) importConfiguration.getProperties().get("source");
endpoint += "&moveFailed=.error";
if (StringUtils.isNotBlank(endpoint) && allowedEndpoints.contains(endpoint.substring(0, endpoint.indexOf(':')))) {
ProcessorDefinition prDef = from(endpoint).routeId(// This allow identification of the route for manual start/stop
importConfiguration.getItemId()).autoStartup(// Auto-start if the import configuration is set active
importConfiguration.isActive()).shutdownRunningTask(ShutdownRunningTask.CompleteAllTasks).onCompletion().log(LoggingLevel.DEBUG, "ROUTE [" + importConfiguration.getItemId() + "] is now complete [" + new Date().toString() + "]").end().process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
importConfiguration.setStatus(RouterConstants.CONFIG_STATUS_RUNNING);
importConfigurationService.save(importConfiguration, false);
}
}).split(bodyAs(String.class).tokenize(importConfiguration.getLineSeparator())).log(LoggingLevel.DEBUG, "Splitted into ${exchangeProperty.CamelSplitSize} records").setHeader(RouterConstants.HEADER_CONFIG_TYPE, constant(configType)).process(lineSplitProcessor).log(LoggingLevel.DEBUG, "Split IDX ${exchangeProperty.CamelSplitIndex} record").marshal(jacksonDataFormat).convertBodyTo(String.class);
if (RouterConstants.CONFIG_TYPE_KAFKA.equals(configType)) {
prDef.to((KafkaEndpoint) getEndpointURI(RouterConstants.DIRECTION_FROM, RouterConstants.DIRECT_IMPORT_DEPOSIT_BUFFER));
} else {
prDef.to((String) getEndpointURI(RouterConstants.DIRECTION_FROM, RouterConstants.DIRECT_IMPORT_DEPOSIT_BUFFER));
}
} else {
logger.error("Endpoint scheme {} is not allowed, route {} will be skipped.", endpoint.substring(0, endpoint.indexOf(':')), importConfiguration.getItemId());
}
}
}
}
use of org.apache.unomi.router.api.ImportConfiguration in project unomi by apache.
the class ProfileImportSurfersIT method testImportSurfers.
@Test
public void testImportSurfers() throws IOException, InterruptedException {
/**
* Create Missing Properties **
*/
PropertyType propertyType = new PropertyType(new Metadata("integration", "alive", "Alive", "Is the person alive?"));
propertyType.setValueTypeId("boolean");
propertyType.getMetadata().setSystemTags(Collections.singleton("basicProfileProperties"));
propertyType.setTarget("profiles");
profileService.setPropertyType(propertyType);
keepTrying("Failed waiting for property type 'alive'", () -> profileService.getPropertyType("alive"), Objects::nonNull, 1000, 100);
PropertyType propAlive = RouterUtils.getPropertyTypeById(profileService.getTargetPropertyTypes("profiles"), "alive");
Assert.assertNotNull("Lookup of alive property through profiles target has failed !", propAlive);
/**
* Surfers Test **
*/
ImportConfiguration importConfigSurfers = new ImportConfiguration();
String itemId1 = "2-surfers-test";
importConfigSurfers.setItemId(itemId1);
importConfigSurfers.setConfigType(RouterConstants.IMPORT_EXPORT_CONFIG_TYPE_RECURRENT);
importConfigSurfers.setMergingProperty("linkedInId");
importConfigSurfers.setOverwriteExistingProfiles(true);
importConfigSurfers.setColumnSeparator(";");
importConfigSurfers.setHasHeader(true);
importConfigSurfers.setHasDeleteColumn(true);
Map<String, Integer> mappingSurfers = new HashMap<>();
mappingSurfers.put("linkedInId", 0);
mappingSurfers.put("lastName", 1);
mappingSurfers.put("email", 2);
mappingSurfers.put("facebookId", 3);
mappingSurfers.put("gender", 4);
mappingSurfers.put("alive", 5);
mappingSurfers.put("city", 6);
importConfigSurfers.getProperties().put("mapping", mappingSurfers);
File importSurfersFile = new File("data/tmp/recurrent_import/");
importConfigSurfers.getProperties().put("source", "file://" + importSurfersFile.getAbsolutePath() + "?fileName=2-surfers-test.csv&consumer.delay=10m&move=.done");
importConfigSurfers.setActive(true);
importConfigurationService.save(importConfigSurfers, true);
logger.info("ProfileImportSurfersIT setup successfully.");
// Wait for data to be processed
keepTrying("Failed waiting for surfers initial import to complete", () -> profileService.findProfilesByPropertyValue("properties.city", "surfersCity", 0, 50, null), (p) -> p.getTotalSize() == 34, 1000, 100);
keepTrying("Failed waiting for import configurations list with 1 item", () -> importConfigurationService.getAll(), (list) -> Objects.nonNull(list) && list.size() == 1, 1000, 100);
// Profile not to delete
PartialList<Profile> jordyProfile = profileService.findProfilesByPropertyValue("properties.email", "jordy@smith.com", 0, 10, null);
Assert.assertEquals(1, jordyProfile.getList().size());
Assert.assertNotNull(jordyProfile.get(0));
Assert.assertEquals("1", jordyProfile.get(0).getProperty("linkedInId"));
Assert.assertEquals("Jordy Smith", jordyProfile.get(0).getProperty("lastName"));
Assert.assertEquals("999", jordyProfile.get(0).getProperty("facebookId"));
Assert.assertEquals("male", jordyProfile.get(0).getProperty("gender"));
Assert.assertTrue((Boolean) jordyProfile.get(0).getProperty("alive"));
// Profile to delete
PartialList<Profile> paulineProfile = profileService.findProfilesByPropertyValue("properties.lastName", "Pauline Ado", 0, 10, null);
Assert.assertEquals(0, paulineProfile.getList().size());
// Check import config status
ImportConfiguration importConfiguration = importConfigurationService.load(itemId1);
Assert.assertEquals(RouterConstants.CONFIG_STATUS_COMPLETE_SUCCESS, importConfiguration.getStatus());
Assert.assertEquals(1, importConfiguration.getExecutions().size());
importConfigurationService.delete(itemId1);
/**
* Surfers Test OVERWRITE **
*/
ImportConfiguration importConfigSurfersOverwrite = new ImportConfiguration();
String itemId2 = "3-surfers-overwrite-test";
importConfigSurfersOverwrite.setItemId(itemId2);
importConfigSurfersOverwrite.setConfigType(RouterConstants.IMPORT_EXPORT_CONFIG_TYPE_RECURRENT);
importConfigSurfersOverwrite.setMergingProperty("linkedInId");
importConfigSurfersOverwrite.setOverwriteExistingProfiles(true);
importConfigSurfersOverwrite.setColumnSeparator(";");
importConfigSurfersOverwrite.setHasHeader(true);
importConfigSurfersOverwrite.setHasDeleteColumn(true);
importConfigSurfersOverwrite.getProperties().put("mapping", mappingSurfers);
importConfigSurfersOverwrite.getProperties().put("source", "file://" + importSurfersFile.getAbsolutePath() + "?fileName=3-surfers-overwrite-test.csv&consumer.delay=10m&move=.done");
importConfigSurfersOverwrite.setActive(true);
importConfigurationService.save(importConfigSurfersOverwrite, true);
logger.info("ProfileImportSurfersOverwriteIT setup successfully.");
// Wait for data to be processed
keepTrying("Failed waiting for surfers overwrite import to complete", () -> profileService.findProfilesByPropertyValue("properties.city", "surfersCity", 0, 50, null), (p) -> p.getTotalSize() == 36, 1000, 100);
keepTrying("Failed waiting for import configurations list with 1 item", () -> importConfigurationService.getAll(), (list) -> Objects.nonNull(list) && list.size() == 1, 1000, 100);
// Profile not to delete
PartialList<Profile> aliveProfiles = profileService.findProfilesByPropertyValue("properties.alive", "true", 0, 50, null);
PartialList<Profile> deadProfiles = profileService.findProfilesByPropertyValue("properties.alive", "false", 0, 50, null);
Assert.assertEquals(0, aliveProfiles.getList().size());
Assert.assertEquals(36, deadProfiles.getList().size());
// Profile to delete = false, was to delete
PartialList<Profile> paulineProfileOverwrite = profileService.findProfilesByPropertyValue("properties.lastName", "Pauline Ado", 0, 10, null);
Assert.assertEquals(1, paulineProfileOverwrite.getList().size());
importConfigurationService.delete(itemId2);
/**
* Surfers Delete Test **
*/
ImportConfiguration importConfigSurfersDelete = new ImportConfiguration();
String itemId3 = "4-surfers-delete-test";
importConfigSurfersDelete.setItemId(itemId3);
importConfigSurfersDelete.setConfigType(RouterConstants.IMPORT_EXPORT_CONFIG_TYPE_RECURRENT);
importConfigSurfersDelete.setMergingProperty("linkedInId");
importConfigSurfersDelete.setOverwriteExistingProfiles(true);
importConfigSurfersDelete.setColumnSeparator(";");
importConfigSurfersDelete.setHasHeader(true);
importConfigSurfersDelete.setHasDeleteColumn(true);
importConfigSurfersDelete.getProperties().put("mapping", mappingSurfers);
importConfigSurfersDelete.getProperties().put("source", "file://" + importSurfersFile.getAbsolutePath() + "?fileName=4-surfers-delete-test.csv&consumer.delay=10m&move=.done");
importConfigSurfersDelete.setActive(true);
importConfigurationService.save(importConfigSurfersDelete, true);
logger.info("ProfileImportSurfersDeleteIT setup successfully.");
// Wait for data to be processed
keepTrying("Failed waiting for surfers delete import to complete", () -> profileService.findProfilesByPropertyValue("properties.city", "surfersCity", 0, 50, null), (p) -> p.getTotalSize() == 0, 1000, 100);
keepTrying("Failed waiting for import configurations list with 1 item", () -> importConfigurationService.getAll(), (list) -> Objects.nonNull(list) && list.size() == 1, 1000, 100);
PartialList<Profile> jordyProfileDelete = profileService.findProfilesByPropertyValue("properties.email", "jordy@smith.com", 0, 10, null);
Assert.assertEquals(0, jordyProfileDelete.getList().size());
importConfigurationService.delete(itemId3);
}
use of org.apache.unomi.router.api.ImportConfiguration in project unomi by apache.
the class LineSplitProcessor method process.
@Override
public void process(Exchange exchange) throws Exception {
// In case of one shot import we check the header and overwrite import config
ImportConfiguration importConfigOneShot = (ImportConfiguration) exchange.getIn().getHeader(RouterConstants.HEADER_IMPORT_CONFIG_ONESHOT);
String configType = (String) exchange.getIn().getHeader(RouterConstants.HEADER_CONFIG_TYPE);
if (importConfigOneShot != null) {
fieldsMapping = (Map<String, Integer>) importConfigOneShot.getProperties().get("mapping");
propertiesToOverwrite = importConfigOneShot.getPropertiesToOverwrite();
mergingProperty = importConfigOneShot.getMergingProperty();
overwriteExistingProfiles = importConfigOneShot.isOverwriteExistingProfiles();
columnSeparator = importConfigOneShot.getColumnSeparator();
hasHeader = importConfigOneShot.isHasHeader();
hasDeleteColumn = importConfigOneShot.isHasDeleteColumn();
multiValueSeparator = importConfigOneShot.getMultiValueSeparator();
multiValueDelimiter = importConfigOneShot.getMultiValueDelimiter();
}
if ((Integer) exchange.getProperty("CamelSplitIndex") == 0 && hasHeader) {
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
return;
}
RFC4180Parser rfc4180Parser = new RFC4180ParserBuilder().withSeparator(columnSeparator.charAt(0)).build();
logger.debug("$$$$ : LineSplitProcessor : BODY : " + (String) exchange.getIn().getBody());
String[] profileData = rfc4180Parser.parseLine(((String) exchange.getIn().getBody()));
ProfileToImport profileToImport = new ProfileToImport();
profileToImport.setItemId(UUID.randomUUID().toString());
profileToImport.setItemType("profile");
profileToImport.setScope(RouterConstants.SYSTEM_SCOPE);
if (profileData.length > 0 && StringUtils.isNotBlank(profileData[0])) {
if ((hasDeleteColumn && (fieldsMapping.size() > (profileData.length - 1))) || (!hasDeleteColumn && (fieldsMapping.size() > (profileData.length)))) {
throw new BadProfileDataFormatException("The mapping does not match the number of column : line [" + ((Integer) exchange.getProperty("CamelSplitIndex") + 1) + "]", new Throwable("MAPPING_COLUMN_MATCH"));
}
logger.debug("$$$$ : LineSplitProcessor : MAPPING : " + fieldsMapping.keySet());
Map<String, Object> properties = new HashMap<>();
for (String fieldMappingKey : fieldsMapping.keySet()) {
PropertyType propertyType = RouterUtils.getPropertyTypeById(profilePropertyTypes, fieldMappingKey);
if (fieldMappingKey != null && fieldsMapping.get(fieldMappingKey) != null && profileData != null && profileData[fieldsMapping.get(fieldMappingKey)] != null) {
logger.debug("$$$$ : LineSplitProcessor : PropType value : {}", profileData[fieldsMapping.get(fieldMappingKey)].trim());
} else {
logger.debug("$$$$ : LineSplitProcessor : no profileData found for fieldMappingKey=" + fieldMappingKey);
}
if (profileData.length > fieldsMapping.get(fieldMappingKey)) {
try {
if (propertyType == null) {
logger.error("No valid property type found for propertyTypeId=" + fieldMappingKey);
} else {
if (propertyType.getValueTypeId() == null) {
logger.error("No value type id found for property type " + propertyType.getItemId());
}
}
if (propertyType.getValueTypeId().equals("string") || propertyType.getValueTypeId().equals("email") || propertyType.getValueTypeId().equals("date")) {
if (BooleanUtils.isTrue(propertyType.isMultivalued())) {
String multivalueArray = profileData[fieldsMapping.get(fieldMappingKey)].trim();
if (StringUtils.isNotBlank(multiValueDelimiter) && multiValueDelimiter.length() == 2) {
multivalueArray = multivalueArray.replaceAll("\\" + multiValueDelimiter.charAt(0), "").replaceAll("\\" + multiValueDelimiter.charAt(1), "");
}
if (multivalueArray.contains(multiValueSeparator)) {
String[] valuesArray = multivalueArray.split("\\" + multiValueSeparator);
properties.put(fieldMappingKey, valuesArray);
} else {
if (StringUtils.isNotBlank(multivalueArray)) {
properties.put(fieldMappingKey, new String[] { multivalueArray });
} else {
properties.put(fieldMappingKey, new String[] {});
}
}
} else {
String singleValue = profileData[fieldsMapping.get(fieldMappingKey)].trim();
properties.put(fieldMappingKey, singleValue);
}
} else if (propertyType.getValueTypeId().equals("boolean")) {
properties.put(fieldMappingKey, new Boolean(profileData[fieldsMapping.get(fieldMappingKey)].trim()));
} else if (propertyType.getValueTypeId().equals("integer")) {
properties.put(fieldMappingKey, new Integer(profileData[fieldsMapping.get(fieldMappingKey)].trim()));
} else if (propertyType.getValueTypeId().equals("long")) {
properties.put(fieldMappingKey, new Long(profileData[fieldsMapping.get(fieldMappingKey)].trim()));
}
} catch (Throwable t) {
logger.error("Error converting profileData", t);
if (fieldMappingKey != null && fieldsMapping.get(fieldMappingKey) != null && profileData != null && profileData[fieldsMapping.get(fieldMappingKey)] != null) {
throw new BadProfileDataFormatException("Unable to convert '" + profileData[fieldsMapping.get(fieldMappingKey)].trim() + "' to " + propertyType != null ? propertyType.getValueTypeId() : "Null propertyType ", new Throwable("DATA_TYPE"));
} else {
throw new BadProfileDataFormatException("Unable to find profile data for key " + fieldMappingKey, new Throwable("DATA_TYPE"));
}
}
}
}
profileToImport.setProperties(properties);
profileToImport.setMergingProperty(mergingProperty);
profileToImport.setPropertiesToOverwrite(propertiesToOverwrite);
profileToImport.setOverwriteExistingProfiles(overwriteExistingProfiles);
if (hasDeleteColumn && StringUtils.isNotBlank(profileData[profileData.length - 1]) && Boolean.parseBoolean(profileData[profileData.length - 1].trim())) {
profileToImport.setProfileToDelete(true);
}
} else {
throw new BadProfileDataFormatException("Empty line : line [" + ((Integer) exchange.getProperty("CamelSplitIndex") + 1) + "]", new Throwable("EMPTY_LINE"));
}
exchange.getIn().setBody(profileToImport, ProfileToImport.class);
if (RouterConstants.CONFIG_TYPE_KAFKA.equals(configType)) {
exchange.getIn().setHeader(KafkaConstants.PARTITION_KEY, 0);
exchange.getIn().setHeader(KafkaConstants.KEY, "1");
}
}
use of org.apache.unomi.router.api.ImportConfiguration in project unomi by apache.
the class ProfileImportActorsIT method testImportActors.
@Test
public void testImportActors() throws InterruptedException {
/**
* Create Missing Properties **
*/
PropertyType propertyTypeTwitterId = new PropertyType(new Metadata("integration", "twitterId", "Twitter ID", "Twitter ID"));
propertyTypeTwitterId.setValueTypeId("integer");
propertyTypeTwitterId.getMetadata().setSystemTags(Collections.singleton("basicProfileProperties"));
propertyTypeTwitterId.setTarget("profiles");
PropertyType propertyTypeActorsGenres = new PropertyType(new Metadata("integration", "movieGenres", "Movie Genres", "Movie Genres"));
propertyTypeActorsGenres.setValueTypeId("string");
propertyTypeActorsGenres.setMultivalued(true);
propertyTypeActorsGenres.getMetadata().setSystemTags(Collections.singleton("basicProfileProperties"));
propertyTypeActorsGenres.setTarget("profiles");
profileService.setPropertyType(propertyTypeTwitterId);
profileService.setPropertyType(propertyTypeActorsGenres);
PropertyType propTwitterId = keepTrying("Failed waiting for property type 'twitterId'", () -> profileService.getPropertyType("twitterId"), Objects::nonNull, 1000, 100);
PropertyType propActorsGenre = keepTrying("Failed waiting for property type 'movieGenres'", () -> profileService.getPropertyType("movieGenres"), Objects::nonNull, 1000, 100);
/**
* Actors Test **
*/
String itemId = "6-actors-test";
ImportConfiguration importConfigActors = new ImportConfiguration();
importConfigActors.setItemId(itemId);
importConfigActors.setConfigType(RouterConstants.IMPORT_EXPORT_CONFIG_TYPE_RECURRENT);
importConfigActors.setMergingProperty("twitterId");
importConfigActors.setOverwriteExistingProfiles(true);
importConfigActors.setColumnSeparator(";");
importConfigActors.setMultiValueDelimiter("[]");
importConfigActors.setMultiValueSeparator(";");
importConfigActors.setHasHeader(true);
importConfigActors.setHasDeleteColumn(false);
Map<String, Integer> mappingActors = new HashMap<>();
mappingActors.put("twitterId", 0);
mappingActors.put("lastName", 1);
mappingActors.put("email", 2);
mappingActors.put("movieGenres", 3);
mappingActors.put("city", 4);
importConfigActors.getProperties().put("mapping", mappingActors);
File importSurfersFile = new File("data/tmp/recurrent_import/");
importConfigActors.getProperties().put("source", "file://" + importSurfersFile.getAbsolutePath() + "?fileName=6-actors-test.csv&consumer.delay=10m&move=.done");
importConfigActors.setActive(true);
importConfigurationService.save(importConfigActors, true);
// Wait for data to be processed
keepTrying("Failed waiting for actors initial import to complete", () -> profileService.findProfilesByPropertyValue("properties.city", "hollywood", 0, 10, null), (p) -> p.getTotalSize() == 6, 1000, 200);
List<ImportConfiguration> importConfigurations = importConfigurationService.getAll();
Assert.assertEquals(1, importConfigurations.size());
PartialList<Profile> jeanneProfile = profileService.findProfilesByPropertyValue("properties.twitterId", "4", 0, 10, null);
Assert.assertEquals(1, jeanneProfile.getList().size());
Assert.assertNotNull(jeanneProfile.get(0));
Assert.assertEquals("Jeanne; D'arc", jeanneProfile.get(0).getProperty("lastName"));
Assert.assertEquals("jean@darc.com", jeanneProfile.get(0).getProperty("email"));
Assert.assertArrayEquals(new String[] {}, ((List) jeanneProfile.get(0).getProperty("movieGenres")).toArray());
PartialList<Profile> rockProfile = profileService.findProfilesByPropertyValue("properties.twitterId", "6", 0, 10, null);
Assert.assertEquals(1, rockProfile.getList().size());
Assert.assertNotNull(rockProfile.get(0));
Assert.assertEquals("The Rock", rockProfile.get(0).getProperty("lastName"));
Assert.assertEquals("the.rock@gmail.com", rockProfile.get(0).getProperty("email"));
Assert.assertEquals(Arrays.asList("Adventure", "Action", "Romance", "Comedy"), rockProfile.get(0).getProperty("movieGenres"));
importConfigurationService.delete(itemId);
}
Aggregations