Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BitSail][Features] Support list and map in current FileMappingTypeInfoConverter #345

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,25 @@ public class BitSailTypeParser {
private static final String SPLIT_TOKEN = ",";

public static String fromTypeInfo(TypeInfo<?> typeInfo) {
return TypeInfoBridge.bridgeTypes(typeInfo);
Preconditions.checkNotNull(typeInfo, "typeInfo can not be null.");

if (typeInfo instanceof ListTypeInfo || typeInfo instanceof MapTypeInfo) {

if (typeInfo instanceof MapTypeInfo) {
MapTypeInfo mapTypeInfo = (MapTypeInfo) typeInfo;
return String.format("%s<%s, %s>", Types.MAP.name(), fromTypeInfo(mapTypeInfo.getKeyTypeInfo()), fromTypeInfo(mapTypeInfo.getValueTypeInfo()));
} else {

ListTypeInfo listTypeInfo = (ListTypeInfo) typeInfo;
return String.format("%s<%s>", Types.LIST.name(), fromTypeInfo(listTypeInfo.getElementTypeInfo()));
}
}
String typeString = TypeInfoBridge.bridgeTypes(typeInfo);
if (StringUtils.isEmpty(typeString)) {
throw BitSailException.asBitSailException(CommonErrorCode.INTERNAL_ERROR,
String.format("Not support type typeInfo %s.", typeInfo));
}
return typeString;
}

public static List<TypeProperty> fromTypePropertyString(String typePropertyString) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@

package com.bytedance.bitsail.common.type.filemapping;

import com.bytedance.bitsail.common.BitSailException;
import com.bytedance.bitsail.common.exception.CommonErrorCode;
import com.bytedance.bitsail.common.type.BitSailTypeParser;
import com.bytedance.bitsail.common.type.TypeInfoConverter;
import com.bytedance.bitsail.common.typeinfo.ListTypeInfo;
import com.bytedance.bitsail.common.typeinfo.MapTypeInfo;
import com.bytedance.bitsail.common.typeinfo.TypeInfo;
import com.bytedance.bitsail.common.typeinfo.Types;

import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;

public class FileMappingTypeInfoConverter implements TypeInfoConverter {
@Getter
protected FileMappingTypeInfoReader reader;
Expand Down Expand Up @@ -52,11 +60,53 @@ protected static String trim(String typeName) {

@Override
public TypeInfo<?> fromTypeString(String typeString) {
return reader.getToTypeInformation().get(typeString);
TypeInfo<?> typeInfo = reader.getToTypeInformation().get(typeString);

if (!Objects.isNull(typeInfo)) {
return typeInfo;
}

String engineMapStr = reader.customToEngineTypeStringMap.get(Types.MAP.name().toLowerCase());
String engineListStr = reader.customToEngineTypeStringMap.get(Types.LIST.name().toLowerCase());
if (StringUtils.isNotBlank(engineMapStr) && typeString.contains(engineMapStr)
|| StringUtils.isNotBlank(engineListStr) && typeString.contains(engineListStr)) {
String customTypeString = this.toCustomTypeString(typeString);
return BitSailTypeParser.fromTypeString(customTypeString);
}

throw BitSailException.asBitSailException(CommonErrorCode.INTERNAL_ERROR,
String.format("Not support type string %s.", typeString));
}

@Override
public String fromTypeInfo(TypeInfo<?> typeInfo) {
return reader.getFromTypeInformation().get(typeInfo);
String typeStr = reader.getFromTypeInformation().get(typeInfo);

if (StringUtils.isNotBlank(typeStr)) {
return typeStr;
}

if (typeInfo instanceof ListTypeInfo || typeInfo instanceof MapTypeInfo) {
String customTypeString = BitSailTypeParser.fromTypeInfo(typeInfo);
return this.toEngineTypeString(customTypeString);
}

throw BitSailException.asBitSailException(CommonErrorCode.INTERNAL_ERROR,
String.format("Not support typeInfo %s.", typeInfo));
}

private String toEngineTypeString(String customTypeString) {
customTypeString = customTypeString.toLowerCase();
for (String key : reader.customToEngineTypeStringMap.keySet()) {
customTypeString = customTypeString.replace(key, reader.customToEngineTypeStringMap.get(key));
}
return customTypeString;
}

private String toCustomTypeString(String engineTypeString) {
for (String key : reader.engineToCustomTypeStringMap.keySet()) {
engineTypeString = engineTypeString.replace(key, reader.engineToCustomTypeStringMap.get(key));
}
return engineTypeString.toLowerCase();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.bytedance.bitsail.common.type.filemapping;

import com.bytedance.bitsail.common.BitSailException;
import com.bytedance.bitsail.common.exception.CommonErrorCode;
import com.bytedance.bitsail.common.type.BitSailTypeParser;
import com.bytedance.bitsail.common.typeinfo.TypeInfo;

Expand All @@ -31,6 +33,7 @@
import java.io.Serializable;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -45,12 +48,19 @@ public class FileMappingTypeInfoReader implements Serializable {
private static final String ENGINE_TO_CUSTOM_KEY = "engine.type.to.bitsail.type.converter";
private static final String CUSTOM_TO_ENGINE_KEY = "bitsail.type.to.engine.type.converter";

private static final String ENGINE_TO_CUSTOM_COMPLEX_KEY = "engine.type.to.bitsail.complex.converter";
private static final String CUSTOM_TO_ENGINE_COMPLEX_KEY = "bitsail.type.to.engine.complex.converter";

private final String converterFileName;

@Getter
protected Map<String, TypeInfo<?>> toTypeInformation = Maps.newHashMap();
@Getter
protected Map<TypeInfo<?>, String> fromTypeInformation = Maps.newHashMap();
@Getter
protected Map<String, String> engineToCustomTypeStringMap = Maps.newHashMap();
@Getter
protected Map<String, String> customToEngineTypeStringMap = Maps.newHashMap();

public FileMappingTypeInfoReader(String engine) {
LOG.info("File mapping reader from engine = {}.", engine);
Expand Down Expand Up @@ -99,6 +109,13 @@ private void read() throws IOException {
readerOption(converterConf, ENGINE_TO_CUSTOM_KEY, tmpToTypeInformation);
readerOption(converterConf, CUSTOM_TO_ENGINE_KEY, tmpFromTypeInformation);

readerOption(converterConf, ENGINE_TO_CUSTOM_COMPLEX_KEY, engineToCustomTypeStringMap);
readerOption(converterConf, CUSTOM_TO_ENGINE_COMPLEX_KEY, customToEngineTypeStringMap);
this.customTypeStringCaseCheck(engineToCustomTypeStringMap.values());
this.customTypeStringCaseCheck(customToEngineTypeStringMap.keySet());
engineToCustomTypeStringMap.putAll(tmpToTypeInformation);
customToEngineTypeStringMap.putAll(tmpFromTypeInformation);

handleEngineTypeToCustom(tmpToTypeInformation);
handleCustomToEngineType(tmpFromTypeInformation);
}
Expand Down Expand Up @@ -128,4 +145,14 @@ protected void handleCustomToEngineType(Map<String, String> tmpFromTypeInformati
fromTypeInformation.put(typeInfo, entry.getValue());
}
}

private void customTypeStringCaseCheck(Collection<String> customTypeStrings) {
for (String typeStr : customTypeStrings) {
if (!typeStr.equals(typeStr.toLowerCase())) {
throw BitSailException.asBitSailException(CommonErrorCode.INTERNAL_ERROR,
String.format("custom type string must be lowercase:%s", typeStr));
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,67 @@
import com.bytedance.bitsail.common.typeinfo.TypeInfo;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Map;

/**
* Created 2022/8/23
*/
public class SimpleTypeInfoConverterTest {

@Test
public void testSimpleTypeInfoConverter() {
FileMappingTypeInfoConverter fileMappingTypeInfoConverter = new FileMappingTypeInfoConverter("fake");
private FileMappingTypeInfoConverter fileMappingTypeInfoConverter;
private Map<String, TypeInfo<?>> toTypeInformation;
private Map<TypeInfo<?>, String> fromTypeInformation;

@Before
public void before() {
fileMappingTypeInfoConverter = new FileMappingTypeInfoConverter("fake");
FileMappingTypeInfoReader reader = fileMappingTypeInfoConverter.getReader();
Map<String, TypeInfo<?>> toTypeInformation = reader.getToTypeInformation();
Map<TypeInfo<?>, String> fromTypeInformation = reader.getFromTypeInformation();
toTypeInformation = reader.getToTypeInformation();
fromTypeInformation = reader.getFromTypeInformation();
}

@Test
public void testSimpleTypeInfoConverter() {
Assert.assertEquals(toTypeInformation.size(), 8);
Assert.assertEquals(fromTypeInformation.size(), 6);
Assert.assertEquals(fromTypeInformation.size(), 7);
}

@Test
public void testFromTypeString_ListType() {
TypeInfo<?> typeInfo01 = fileMappingTypeInfoConverter.fromTypeString("Array(double)");
Assert.assertEquals(typeInfo01.getTypeClass(), List.class);

TypeInfo<?> typeInfo02 = fileMappingTypeInfoConverter.fromTypeString("Array(Array(double))");
Assert.assertEquals(typeInfo02.getTypeClass(), List.class);
}

@Test
public void testFromTypeString_MapType() {
TypeInfo<?> typeInfo01 = fileMappingTypeInfoConverter.fromTypeString("Map(string,double)");
Assert.assertEquals(typeInfo01.getTypeClass(), Map.class);

TypeInfo<?> typeInfo02 = fileMappingTypeInfoConverter.fromTypeString("Map(string, Map(string, double))");
Assert.assertEquals(typeInfo02.getTypeClass(), Map.class);
}

@Test
public void testFromTypeInfo_ListType() {
TypeInfo<?> typeInfo = fileMappingTypeInfoConverter.fromTypeString("Array(Array(Int32))");
Assert.assertEquals(typeInfo.getTypeClass(), List.class);

String typeString = fileMappingTypeInfoConverter.fromTypeInfo(typeInfo);
Assert.assertEquals(typeString, "Array(Array(Int32))");
}

@Test
public void testFromTypeInfo_MapType() {
TypeInfo<?> typeInfo = fileMappingTypeInfoConverter.fromTypeString("Map(string, Map(string, double))");

String typeString = fileMappingTypeInfoConverter.fromTypeInfo(typeInfo);
Assert.assertEquals(typeString, "Map(string, Map(string, double))");
}
}
37 changes: 34 additions & 3 deletions bitsail-common/src/test/resources/fake-type-converter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ engine.type.to.bitsail.type.converter:
- source.type: double
target.type: double

- source.type: int
target.type: long
- source.type: Int32
target.type: int

- source.type: bigint
target.type: long


bitsail.type.to.engine.type.converter:
- source.type: long
target.type: long
target.type: bigint

- source.type: double
target.type: double
Expand All @@ -42,3 +42,34 @@ bitsail.type.to.engine.type.converter:

- source.type: bytes
target.type: bytes

- source.type: int
target.type: Int32


engine.type.to.bitsail.complex.converter:
- source.type: Array
target.type: list

- source.type: Map
target.type: map

- source.type: (
target.type: <
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we didn't need this part, we can consider it as default


- source.type: )
target.type: '>'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we didn't need this part, we can consider it as default

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do this because I want to leave an entry for connector developers so that they can make the engine type string as close as possible to the type description of the engine itself. I think this has two advantages:

  1. It can constrain the field types configured by users ;
  2. Users have a clearer principle to know how to configure the engine type—consistent with the original type of the engine. Type configurations such as int32 and double64 will make users doubtful

@hk-lrzy look forwards ur further advice


bitsail.type.to.engine.complex.converter:
- source.type: list
target.type: Array

- source.type: map
target.type: Map

- source.type: <
target.type: (

- source.type: '>'
target.type: )