Skip to content

Commit

Permalink
Data Substitutor (#160)
Browse files Browse the repository at this point in the history
* [DataBind] Added Substitutor support

* [DataBind] Updated Test

* [DataBind] Substitutor for ExcelData

* [DataBind] Cleanup

* [DataBind] updated test
  • Loading branch information
RameshBabuPrudhvi authored Jul 9, 2022
1 parent 77ff0bb commit 4fa96d9
Show file tree
Hide file tree
Showing 13 changed files with 202 additions and 30 deletions.
2 changes: 1 addition & 1 deletion selcukes-databind/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<artifactId>selcukes-databind</artifactId>
<name>selcukes-databind</name>
<description>Selcukes Databind helps to parser JSON, YML, XML and Excel files.</description>
<description>Selcukes Databind helps to parser JSON, YML, XML, Properties and Excel files.</description>

<properties>
<maven.compiler.source>11</maven.compiler.source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@

package io.github.selcukes.databind;

import io.github.selcukes.databind.annotation.Interpolate;
import io.github.selcukes.databind.annotation.Key;
import io.github.selcukes.databind.converters.Converter;
import io.github.selcukes.databind.substitute.DefaultSubstitutor;
import io.github.selcukes.databind.substitute.Substitutor;
import io.github.selcukes.databind.utils.Reflections;
import lombok.Getter;
import lombok.Setter;

Expand Down Expand Up @@ -66,6 +70,20 @@ public Optional<Key> getColumn() {
return ofNullable(field.getDeclaredAnnotation(Key.class));
}

@SuppressWarnings("unchecked")
private Optional<Interpolate> getInterpolate() {
Class<T> entityClass = (Class<T>) field.getDeclaringClass();
return ofNullable(entityClass.getDeclaredAnnotation(Interpolate.class));
}

public Substitutor getSubstitutor() {
return getInterpolate()
.map(Interpolate::substitutor)
.map(Reflections::newInstance)
.map(Substitutor.class::cast)
.orElseGet(DefaultSubstitutor::new);
}

@SuppressWarnings("unchecked")
private Converter<T> findMatchingConverter() {
return getColumn()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) Ramesh Babu Prudhvi.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.github.selcukes.databind.annotation;

import io.github.selcukes.databind.substitute.DefaultSubstitutor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Interpolate {
Class<?> substitutor() default DefaultSubstitutor.class;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,17 @@

package io.github.selcukes.databind.excel;

import io.github.selcukes.databind.DataField;
import io.github.selcukes.databind.annotation.Key;
import io.github.selcukes.databind.converters.Converter;
import io.github.selcukes.databind.DataField;
import io.github.selcukes.databind.utils.Maps;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static io.github.selcukes.databind.utils.StringHelper.toFieldName;
import static java.lang.String.CASE_INSENSITIVE_ORDER;
import static java.lang.String.format;
import static java.util.Optional.ofNullable;
import static org.apache.poi.ss.usermodel.Row.MissingCellPolicy.RETURN_BLANK_AS_NULL;
Expand All @@ -52,17 +50,18 @@ public ExcelCell<T> parse(final Row row) {
var cellValue = ofNullable(row.getCell(index, RETURN_BLANK_AS_NULL))
.map(cell -> formatter.formatCellValue(cell).trim())
.orElse("");
setConvertedValue(getConverter().convert(cellValue, getColumn().map(Key::format).orElse("")));
var substituted = getSubstitutor().replace(cellValue);
var format = getColumn().map(Key::format).orElse("");
var converted = getConverter().convert(substituted, format);
setConvertedValue(converted);
return this;
}

private int getIndex(Map<String, Integer> headers) {
String header = getColumn()
.map(Key::name)
.orElse(toFieldName(getFieldName()));
Map<String, Integer> headersMap = new TreeMap<>(CASE_INSENSITIVE_ORDER);
headersMap.putAll(headers);
return ofNullable(headersMap.get(header))
.orElse(getFieldName());
return ofNullable(Maps.caseInsensitive(headers).get(header))
.orElseThrow(() -> new IllegalArgumentException(format("Column %s not found", getFieldName())));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,24 @@
import java.util.List;
import java.util.Properties;

import static io.github.selcukes.databind.utils.StringHelper.toFieldName;

class PropertyField<T> extends DataField<T> {
private final Properties properties;

public PropertyField(final Field field, final Properties properties, final List<Converter<T>> defaultConverters) {
public PropertyField(
final Field field,
final Properties properties,
final List<Converter<T>> defaultConverters
) {
super(field, defaultConverters);
this.properties = properties;
}

public PropertyField<T> parse() {
String fieldName = getColumn()
String keyName = getColumn()
.map(Key::name)
.orElse(toFieldName(getFieldName()));
setConvertedValue(getConverter().convert(properties.getProperty(fieldName)));
.orElse(getFieldName());
var substituted = getSubstitutor().replace(properties, keyName);
setConvertedValue(getConverter().convert(substituted));
return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) Ramesh Babu Prudhvi.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.github.selcukes.databind.substitute;

import java.util.Properties;

public class DefaultSubstitutor implements Substitutor {
public String replace(Properties variables, String key) {
return variables.getProperty(key);
}

@Override
public String replace(String strToReplace) {
return strToReplace;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) Ramesh Babu Prudhvi.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.github.selcukes.databind.substitute;


import java.util.Properties;

public interface Substitutor {
String replace(Properties variables, String key);
String replace(String strToReplace);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@

import lombok.experimental.UtilityClass;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static java.lang.String.CASE_INSENSITIVE_ORDER;

@UtilityClass
public class Maps {
public static Map<String, String> of(Properties properties) {
Expand All @@ -40,4 +39,10 @@ public static Map<String, String> of(List<String> keys, List<String> values) {
return IntStream.range(0, keys.size()).boxed()
.filter(i -> !StringHelper.isNullOrEmpty(keys.get(i))).collect(Collectors.toMap(keys::get, values::get));
}

public static <V> Map<String, V> caseInsensitive(Map<String, V> map) {
var newMap = new TreeMap<String,V>(CASE_INSENSITIVE_ORDER);
newMap.putAll(map);
return newMap;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) Ramesh Babu Prudhvi.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.github.selcukes.databind.tests;

import io.github.selcukes.databind.substitute.DefaultSubstitutor;
import io.github.selcukes.databind.utils.StringHelper;

import java.time.LocalDate;
import java.util.Properties;

public class EnvPropSubstitutor extends DefaultSubstitutor {
@Override
public String replace(Properties variables, String key) {
String value = variables.getProperty(key);
return StringHelper.interpolate(value,
matcher -> matcher.group(1).equals("DATE") ?
LocalDate.now().toString() : System.getProperty(matcher.group(1))
);
}

@Override
public String replace(String strToReplace) {
return StringHelper.interpolate(strToReplace,
matcher -> matcher.group(1).equals("DATE") ?
LocalDate.now().toString() : System.getenv(matcher.group(1)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

package io.github.selcukes.databind.tests;

import io.github.selcukes.databind.excel.ExcelMapper;
import io.github.selcukes.databind.annotation.Key;
import io.github.selcukes.databind.annotation.DataFile;
import io.github.selcukes.databind.annotation.Interpolate;
import io.github.selcukes.databind.annotation.Key;
import io.github.selcukes.databind.excel.ExcelMapper;
import io.github.selcukes.databind.exception.DataMapperException;
import lombok.Data;
import org.testng.annotations.Test;
Expand All @@ -29,27 +30,42 @@ public class ExcelMapperTest {

@Data
@DataFile(fileName = "TestData.xlsx", sheetName = "Smoke")
static class Pojo {
static class SampleExcel {
@Key(name = "Screen")
private String screen;
@Key(name = "Feature")
private String feature;
@Key(name = "Test")
private String test;
// @Column(name = "Run")
private String run;
}

@Test
public void excelMapperTest() {
Stream<Pojo> pojoStream = ExcelMapper.parse(Pojo.class);
Stream<SampleExcel> pojoStream = ExcelMapper.parse(SampleExcel.class);
pojoStream.forEach(System.out::println);
}

@Interpolate(substitutor = EnvPropSubstitutor.class)
@Data
@DataFile(fileName = "TestData.xlsx", sheetName = "Yahoo")
static class SampleExcel1 {
@Key(name = "First Name")
String firstName;
@Key(name = "Last Name")
String lastName;
String date;
}

@Test
public void interpolateExcelMapperTest() {
Stream<SampleExcel1> excelStream = ExcelMapper.parse(SampleExcel1.class);
excelStream.forEach(System.out::println);
}

@Test(expectedExceptions = DataMapperException.class)
public void excelMapperNegativeTest() {
ExcelMapper.parse(Selcukes.class);

}

@Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.github.selcukes.databind.tests;

import io.github.selcukes.databind.annotation.DataFile;
import io.github.selcukes.databind.annotation.Interpolate;
import io.github.selcukes.databind.annotation.Key;
import io.github.selcukes.databind.properties.PropertiesMapper;
import lombok.Data;
Expand All @@ -33,21 +34,24 @@ public void testProperties() {
System.out.println(testConfig.getUserName());
if (testConfig.isTest())
System.out.println(testConfig.getDate());

System.out.println(testConfig.getOsName());
System.out.println(testConfig.getJim());
System.out.println(testConfig.getMass());
}

@Interpolate(substitutor = EnvPropSubstitutor.class)
@DataFile
@Data
static class TestConfig {
String userName;
boolean isTest;
String password;
boolean isTest;
String osName;
LocalDate date;
@Key(name = "selcukes.jim")
int jim;
@Key(name = "mass", converter = ListStringConverter.class)
List<String> mass;
}

}
Binary file modified selcukes-databind/src/test/resources/TestData.xlsx
Binary file not shown.
5 changes: 3 additions & 2 deletions selcukes-databind/src/test/resources/test_config.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
userName=QA
userName=Ramesh
password=make
isTest=true
date=2022-07-08
osName= ${os.name}
date=${DATE}
selcukes.jim=50
mass=jim,jil

0 comments on commit 4fa96d9

Please sign in to comment.