Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.wgzhao.datax.common.util.Configuration Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 com.wgzhao.datax.common.util;
import com.wgzhao.datax.common.exception.CommonErrorCode;
import com.wgzhao.datax.common.exception.DataXException;
import com.wgzhao.datax.common.spi.ErrorCode;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Configuration 提供多级JSON配置信息无损存储
* 实例代码:
* 获取job的配置信息
* Configuration configuration = Configuration.from(new File("Config.json"));
* String jobContainerClass =
* configuration.getString("core.container.job.class");
* 设置多级List
* configuration.set("job.reader.parameter.jdbcUrl", Arrays.asList(new String[]
* {"jdbc", "jdbc"}));
* 合并Configuration:
* configuration.merge(another);
* Configuration 存在两种较好地实现方式
* 第一种是将JSON配置信息中所有的Key全部打平,用a.b.c的级联方式作为Map的Key,内部使用一个Map保存信息
* 第二种是将JSON的对象直接使用结构化树形结构保存
* 目前使用的第二种实现方式,使用第一种的问题在于:
* 1. 插入新对象,比较难处理,例如a.b.c="bazhen",此时如果需要插入a="bazhen",也即是根目录下第一层所有类型全部要废弃
* ,使用"bazhen"作为value,第一种方式使用字符串表示key,难以处理这类问题。
* 2. 返回树形结构,例如 a.b.c.d = "bazhen",如果返回"a"下的所有元素,实际上是一个Map,需要合并处理
* 3. 输出JSON,将上述对象转为JSON,要把上述Map的多级key转为树形结构,并输出为JSON
*/
public class Configuration
{
/**
* 对于加密的keyPath,需要记录下来
* 为的是后面分布式情况下将该值加密后抛到DataXServer中
*/
private Set secretKeyPathSet =
new HashSet<>();
private Object root;
private Configuration(String json)
{
try {
this.root = JSON.parse(json);
}
catch (Exception e) {
throw DataXException.asDataXException(CommonErrorCode.CONFIG_ERROR,
String.format("配置信息错误. 您提供的配置信息不是合法的JSON格式: %s . 请按照标准json格式提供配置信息. ", e.getMessage()));
}
}
/*
* 初始化空白的Configuration
*/
public static Configuration newDefault()
{
return Configuration.from("{}");
}
/*
* 从JSON字符串加载Configuration
*/
public static Configuration from(String json)
{
json = StrUtil.replaceVariable(json);
checkJSON(json);
try {
return new Configuration(json);
}
catch (Exception e) {
throw DataXException.asDataXException(CommonErrorCode.CONFIG_ERROR,
e);
}
}
/*
* 从包括json的File对象加载Configuration
*/
public static Configuration from(File file)
{
try {
return Configuration.from(IOUtils
.toString(new FileInputStream(file), StandardCharsets.UTF_8));
}
catch (FileNotFoundException e) {
throw DataXException.asDataXException(CommonErrorCode.CONFIG_ERROR,
String.format("配置信息错误,您提供的配置文件[%s]不存在. 请检查您的配置文件.", file.getAbsolutePath()));
}
catch (IOException e) {
throw DataXException.asDataXException(
CommonErrorCode.CONFIG_ERROR,
String.format("配置信息错误. 您提供配置文件[%s]读取失败,错误原因: %s. 请检查您的配置文件的权限设置.",
file.getAbsolutePath(), e));
}
}
/*
* 从包括json的InputStream对象加载Configuration
*/
public static Configuration from(InputStream is)
{
try {
return Configuration.from(IOUtils.toString(is, StandardCharsets.UTF_8));
}
catch (IOException e) {
throw DataXException.asDataXException(CommonErrorCode.CONFIG_ERROR,
String.format("请检查您的配置文件. 您提供的配置文件读取失败,错误原因: %s. 请检查您的配置文件的权限设置.", e));
}
}
/*
* 从Map对象加载Configuration
*/
public static Configuration from(final Map object)
{
return Configuration.from(Configuration.toJSONString(object));
}
/*
* 从List对象加载Configuration
*/
public static Configuration from(final List object)
{
return Configuration.from(Configuration.toJSONString(object));
}
private static void checkJSON(String json)
{
if (StringUtils.isBlank(json)) {
throw DataXException.asDataXException(CommonErrorCode.CONFIG_ERROR,
"配置信息错误. 因为您提供的配置信息不是合法的JSON格式, JSON不能为空白. 请按照标准json格式提供配置信息. ");
}
}
private static String toJSONString(Object object)
{
return JSON.toJSONString(object);
}
public String getNecessaryValue(String key, ErrorCode errorCode)
{
String value = this.getString(key, null);
if (StringUtils.isBlank(value)) {
throw DataXException.asDataXException(errorCode,
String.format("您提供配置文件有误,[%s]是必填参数,不允许为空或者留白 .", key));
}
return value;
}
public String getUnnecessaryValue(String key, String defaultValue)
{
String value = this.getString(key, defaultValue);
if (StringUtils.isBlank(value)) {
value = defaultValue;
}
return value;
}
/**
* 根据用户提供的json path,寻址具体的对象。
*
* NOTE: 目前仅支持Map以及List下标寻址, 例如:
*
* 对于如下JSON
*
* {"a": {"b": {"c": [0,1,2,3]}}}
*
* config.get("") 返回整个Map
* config.get("a") 返回a下属整个Map
* config.get("a.b.c") 返回c对应的数组List
* config.get("a.b.c[0]") 返回数字0
*
* @param path String 要查的json路径
* @return Java表示的JSON对象,如果path不存在或者对象不存在,均返回null。
*/
public Object get(String path)
{
this.checkPath(path);
try {
return this.findObject(path);
}
catch (Exception e) {
return null;
}
}
/**
* 用户指定部分path,获取Configuration的子集
*
* @param path String json 路径
* @return Configuration 配置对象, 如果path获取的路径或者对象不存在,返回null
*/
public Configuration getConfiguration(String path)
{
Object object = this.get(path);
if (null == object) {
return null;
}
return Configuration.from(Configuration.toJSONString(object));
}
/**
* 根据用户提供的json path,寻址String对象
*
* @param path String json 路径
*
* @return String 对象,如果path不存在或者String不存在,返回null
*/
public String getString(String path)
{
Object string = this.get(path);
if (null == string) {
return null;
}
return String.valueOf(string);
}
/**
* 根据用户提供的json path,寻址String对象,如果对象不存在,返回默认字符串
*
* @param path String json 路径
* @param defaultValue String 如果path不存在,则返回该值
*
* @return String对象,如果path不存在或者String不存在,返回默认字符串
*/
public String getString(String path, String defaultValue)
{
String result = this.getString(path);
if (null == result) {
return defaultValue;
}
return result;
}
/**
* 根据用户提供的json path,寻址Character对象
*
* @param path String json 路径
* @return Character对象,如果path不存在或者Character不存在,返回null
*/
public Character getChar(String path)
{
String result = this.getString(path);
if (null == result) {
return null;
}
try {
return CharUtils.toChar(result);
}
catch (Exception e) {
throw DataXException.asDataXException(
CommonErrorCode.CONFIG_ERROR,
String.format("任务读取配置文件出错. 因为配置文件路径[%s] 值非法,期望是字符类型: %s. 请检查您的配置并作出修改.", path,
e.getMessage()));
}
}
/**
* 根据用户提供的json path,寻址Boolean对象,如果对象不存在,返回默认Character对象
*
* @param path String json 路径
* @param defaultValue String 如果path不存在,则返回该值
*
* @return Character对象,如果path不存在或者Character不存在,返回默认Character对象
*/
public Character getChar(String path, char defaultValue)
{
Character result = this.getChar(path);
if (null == result) {
return defaultValue;
}
return result;
}
/**
* 根据用户提供的json path,寻址Boolean对象
*
* @param path String json 路径
*
* @return Boolean对象,如果path值非true,false ,将报错.特别注意:当 path 不存在时,会返回:null.
*/
public Boolean getBool(String path)
{
String result = this.getString(path);
if (null == result) {
return null; //NOSONAR
}
else if ("true".equalsIgnoreCase(result)) {
return Boolean.TRUE;
}
else if ("false".equalsIgnoreCase(result)) {
return Boolean.FALSE;
}
else {
throw DataXException.asDataXException(CommonErrorCode.CONFIG_ERROR,
String.format("您提供的配置信息有误,因为从[%s]获取的值[%s]无法转换为bool类型. 请检查源表的配置并且做出相应的修改.",
path, result));
}
}
/**
* 根据用户提供的json path,寻址Boolean对象,如果对象不存在,返回默认Boolean对象
*
*
* @param path String json 路径
* @param defaultValue String 如果path不存在,则返回该值
*
* @return Boolean对象,如果path不存在或者Boolean不存在,返回默认Boolean对象
*/
public Boolean getBool(String path, boolean defaultValue)
{
Boolean result = this.getBool(path);
if (null == result) {
return defaultValue;
}
return result;
}
/**
* 根据用户提供的json path,寻址Integer对象
*
* @param path String json 路径
*
* @return Integer对象,如果path不存在或者Integer不存在,返回null
*/
public Integer getInt(String path)
{
String result = this.getString(path);
if (null == result) {
return null;
}
try {
return Integer.valueOf(result);
}
catch (Exception e) {
throw DataXException.asDataXException(
CommonErrorCode.CONFIG_ERROR,
String.format("任务读取配置文件出错. 配置文件路径[%s] 值非法, 期望是整数类型: %s. 请检查您的配置并作出修改.", path,
e.getMessage()));
}
}
/**
* 根据用户提供的json path,寻址Integer对象,如果对象不存在,返回默认Integer对象
*
* @param path String json 路径
* @param defaultValue String 如果path不存在,则返回该值
*
* @return Integer对象,如果path不存在或者Integer不存在,返回默认Integer对象
*/
public Integer getInt(String path, int defaultValue)
{
Integer object = this.getInt(path);
if (null == object) {
return defaultValue;
}
return object;
}
/**
* 根据用户提供的json path,寻址Long对象
*
* @param path String json 路径
*
* @return Long对象,如果path不存在或者Long不存在,返回null
*/
public Long getLong(String path)
{
String result = this.getString(path);
if (StringUtils.isBlank(result)) {
return null;
}
try {
return Long.valueOf(result);
}
catch (Exception e) {
throw DataXException.asDataXException(
CommonErrorCode.CONFIG_ERROR,
String.format("任务读取配置文件出错. 配置文件路径[%s] 值非法, 期望是整数类型: %s. 请检查您的配置并作出修改.", path,
e.getMessage()));
}
}
/**
* 根据用户提供的json path,寻址Long对象,如果对象不存在,返回默认Long对象
*
* @param path String json 路径
* @param defaultValue String 如果path不存在,则返回该值
*
* @return Long对象,如果path不存在或者Integer不存在,返回默认Long对象
*/
public Long getLong(String path, long defaultValue)
{
Long result = this.getLong(path);
if (null == result) {
return defaultValue;
}
return result;
}
/**
* 根据用户提供的json path,寻址Double对象
*
* @param path String json 路径
*
* @return Double对象,如果path不存在或者Double不存在,返回null
*/
public Double getDouble(String path)
{
String result = this.getString(path);
if (StringUtils.isBlank(result)) {
return null;
}
try {
return Double.valueOf(result);
}
catch (Exception e) {
throw DataXException.asDataXException(
CommonErrorCode.CONFIG_ERROR,
String.format("任务读取配置文件出错. 配置文件路径[%s] 值非法, 期望是浮点类型: %s. 请检查您的配置并作出修改.", path,
e.getMessage()));
}
}
/**
* 根据用户提供的json path,寻址Double对象,如果对象不存在,返回默认Double对象
*
* @param path String json 路径
* @param defaultValue String 如果path不存在,则返回该值
*
* @return Double对象,如果path不存在或者Double不存在,返回默认Double对象
*/
public Double getDouble(String path, double defaultValue)
{
Double result = this.getDouble(path);
if (null == result) {
return defaultValue;
}
return result;
}
/**
* 根据用户提供的json path,寻址List对象,如果对象不存在,返回null
*
* @param path String json 路径
*
* @return 对象列表
*/
@SuppressWarnings("unchecked")
public List getList(String path)
{
return this.get(path, List.class);
}
/**
* 根据用户提供的json path,寻址List对象,如果对象不存在,返回null
*
* @param path json 路径
* @param t 要转换的类型
* @param 类型
* @return 列表
*/
@SuppressWarnings("unchecked")
public List getList(String path, Class t)
{
List object = this.get(path, List.class);
if (null == object) {
return Collections.emptyList();
}
List result = new ArrayList<>();
List origin = new ArrayList<>();
try {
origin = object;
}
catch (ClassCastException e) {
// .warn("{} 转为 List 时发生了异常,默认将此值添加到 List 中", String.valueOf(object))
origin.add(String.valueOf(object));
}
for (Object each : origin) {
result.add((T) each);
}
return result;
}
/**
* 根据用户提供的json path,寻址List对象,如果对象不存在,返回默认List
*
* @param path json 路径
* @param defaultList 默认返回的值
*
* @return 对象列表
*/
public List getList(String path, List defaultList)
{
List object = this.getList(path);
if (null == object) {
return defaultList;
}
return object;
}
/**
* 根据用户提供的json path,寻址List对象,如果对象不存在,返回默认List
*
* @param path String json 路径
* @param defaultList 默认返回的值
* @param t 要转换的类型
* @param 类型
*
* @return 列表
*/
public List getList(String path, List defaultList,
Class t)
{
List list = this.getList(path, t);
if (null == list) {
return defaultList;
}
return list;
}
/**
* 根据用户提供的json path,寻址包含Configuration的List,如果对象不存在,返回默认null
*
* @param path String json 路径
*
* @return 列表
*/
public List getListConfiguration(String path)
{
List lists = getList(path);
if (lists == null) {
return Collections.emptyList();
}
List result = new ArrayList<>();
for (Object object : lists) {
result.add(Configuration.from(Configuration.toJSONString(object)));
}
return result;
}
/**
* 根据用户提供的json path,寻址Map对象,如果对象不存在,返回null
*
* @param path String json 路径
*
* @return map 对象
*/
@SuppressWarnings("unchecked")
public Map getMap(String path)
{
return this.get(path, Map.class);
}
/**
* 根据用户提供的json path,寻址Map对象,如果对象不存在,返回默认map
*
* @param path String json 路径
* @param defaultMap 默认返回值
*
* @return map对象
*/
public Map getMap(String path,
Map defaultMap)
{
Map object = this.getMap(path);
if (null == object) {
return defaultMap;
}
return object;
}
/**
* 根据用户提供的json path,寻址具体的对象,并转为用户提供的类型
* NOTE: 目前仅支持Map以及List下标寻址, 例如:
* 对于如下JSON
*
* {"a": {"b": {"c": [0,1,2,3]}}}
*
* config.get("") 返回整个Map
* config.get("a") 返回a下属整个Map
* config.get("a.b.c") 返回c对应的数组List
* config.get("a.b.c[0]") 返回数字0
*
* @param path String json 路径
* @param clazz Class 要转换的类型
* @param 类型
*
* @return Java表示的JSON对象,如果转型失败,将抛出异常
*/
@SuppressWarnings("unchecked")
public T get(String path, Class clazz)
{
this.checkPath(path);
return (T) this.get(path);
}
/**
* 格式化Configuration输出
*
* @return string
*/
public String beautify()
{
return JSON.toJSONString(this.getInternal(),
SerializerFeature.PrettyFormat);
}
/**
* 根据用户提供的json path,插入指定对象,并返回之前存在的对象(如果存在)
*
* 目前仅支持.以及数组下标寻址, 例如:
*
* config.set("a.b.c[3]", object);
*
* 对于插入对象,Configuration 不做任何限制,但是请务必保证该对象是简单对象,不要使用自定义对象,否则后续对于JSON序列化等情况会出现未定义行为。
*
* @param path JSON path对象
* @param object 需要插入的对象
*
* @return Java表示的JSON对象
*/
public Object set(String path, Object object)
{
checkPath(path);
Object result = this.get(path);
setObject(path, extractConfiguration(object));
return result;
}
/**
* 获取Configuration下所有叶子节点的key
* 对于
*
* {"a": {"b": {"c": [0,1,2,3]}}, "x": "y"}
*
* 下属的key包括: a.b.c[0],a.b.c[1],a.b.c[2],a.b.c[3],x
*
* @return set of string
*/
public Set getKeys()
{
Set collect = new HashSet<>();
this.getKeysRecursive(this.getInternal(), "", collect);
return collect;
}
/**
* 删除path对应的值,如果path不存在,将抛出异常。
*
* @param path String json 路径
*
* @return Object 返回查到的对象,若不存在则返回为空
*/
public Object remove(String path)
{
Object result = this.get(path);
if (null == result) {
throw DataXException.asDataXException(
CommonErrorCode.RUNTIME_ERROR,
String.format("配置文件对应Key[%s]并不存在,该情况是代码编程错误. 请联系DataX团队的同学.", path));
}
this.set(path, null);
return result;
}
/**
* 合并其他Configuration,并修改两者冲突的KV配置
*
* @param another Configuration 合并加入的第三方Configuration
* @param updateWhenConflict boolean 当合并双方出现KV冲突时候,选择更新当前KV,或者忽略该KV
*
* @return Configuration
*/
public Configuration merge(Configuration another,
boolean updateWhenConflict)
{
Set keys = another.getKeys();
// 如果使用更新策略,凡是another存在的key,均需要更新
// 使用忽略策略,只有another Configuration存在但是当前Configuration不存在的key,才需要更新
keys.forEach(key -> {
if (updateWhenConflict) {
this.set(key, another.get(key));
return;
}
boolean isCurrentExists = this.get(key) != null;
if (isCurrentExists) {
return;
}
this.set(key, another.get(key));
});
return this;
}
@Override
public String toString()
{
return this.toJSON();
}
/**
* 将Configuration作为JSON输出
*
* @return String json string
*/
public String toJSON()
{
return Configuration.toJSONString(this.getInternal());
}
/**
* 拷贝当前Configuration,注意,这里使用了深拷贝,避免冲突
*/
@Override
public Configuration clone()
{
Configuration config = Configuration
.from(Configuration.toJSONString(this.getInternal()));
config.addSecretKeyPath(this.secretKeyPathSet);
return config;
}
/**
* 按照configuration要求格式的path
* 比如:
* a.b.c
* a.b[2].c
*
* @param path 路径
*
*/
public void addSecretKeyPath(String path)
{
if (StringUtils.isNotBlank(path)) {
this.secretKeyPathSet.add(path);
}
}
public void addSecretKeyPath(Set pathSet)
{
if (pathSet != null) {
this.secretKeyPathSet.addAll(pathSet);
}
}
@SuppressWarnings("unchecked")
void getKeysRecursive(Object current, String path, Set collect)
{
boolean isRegularElement = !(current instanceof Map || current instanceof List);
if (isRegularElement) {
collect.add(path);
return;
}
boolean isMap = current instanceof Map;
if (isMap) {
Map mapping = ((Map) current);
mapping.keySet().forEach(key -> {
if (StringUtils.isBlank(path)) {
getKeysRecursive(mapping.get(key), key.trim(), collect);
}
else {
getKeysRecursive(mapping.get(key), path + "." + key.trim(),
collect);
}
});
return;
}
List lists = (List) current;
for (int i = 0; i < lists.size(); i++) {
getKeysRecursive(lists.get(i), path + String.format("[%d]", i),
collect);
}
}
public Object getInternal()
{
return this.root;
}
private void setObject(String path, Object object)
{
Object newRoot = setObjectRecursive(this.root, split2List(path), 0,
object);
if (isSuitForRoot(newRoot)) {
this.root = newRoot;
return;
}
throw DataXException.asDataXException(CommonErrorCode.RUNTIME_ERROR,
String.format("值[%s]无法适配您提供[%s], 该异常代表系统编程错误, 请联系DataX开发团队!",
ToStringBuilder.reflectionToString(object), path));
}
@SuppressWarnings("unchecked")
private Object extractConfiguration(Object object)
{
if (object instanceof Configuration) {
return extractFromConfiguration(object);
}
if (object instanceof List) {
List result = new ArrayList<>();
for (Object each : (List) object) {
result.add(extractFromConfiguration(each));
}
return result;
}
if (object instanceof Map) {
Map result = new HashMap<>();
for (String key : ((Map) object).keySet()) {
result.put(key,
extractFromConfiguration(((Map) object)
.get(key)));
}
return result;
}
return object;
}
private Object extractFromConfiguration(Object object)
{
if (object instanceof Configuration) {
return ((Configuration) object).getInternal();
}
return object;
}
Object buildObject(List paths, Object object)
{
if (null == paths) {
throw DataXException.asDataXException(
CommonErrorCode.RUNTIME_ERROR,
"Path不能为null,该异常代表系统编程错误, 请联系DataX开发团队 !");
}
if (1 == paths.size() && StringUtils.isBlank(paths.get(0))) {
return object;
}
Object child = object;
for (int i = paths.size() - 1; i >= 0; i--) {
String path = paths.get(i);
if (isPathMap(path)) {
Map mapping = new HashMap<>();
mapping.put(path, child);
child = mapping;
continue;
}
if (isPathList(path)) {
List lists = new ArrayList<>(
this.getIndex(path) + 1);
expand(lists, this.getIndex(path) + 1);
lists.set(this.getIndex(path), child);
child = lists;
continue;
}
throw DataXException.asDataXException(
CommonErrorCode.RUNTIME_ERROR, String.format(
"路径[%s]出现非法值类型[%s],该异常代表系统编程错误, 请联系DataX开发团队! .",
StringUtils.join(paths, "."), path));
}
return child;
}
@SuppressWarnings("unchecked")
Object setObjectRecursive(Object current, List paths,
int index, Object value)
{
// 如果是已经超出path,我们就返回value即可,作为最底层叶子节点
boolean isLastIndex = index == paths.size();
if (isLastIndex) {
return value;
}
String path = paths.get(index).trim();
boolean isNeedMap = isPathMap(path);
if (isNeedMap) {
Map mapping;
// 当前不是map,因此全部替换为map,并返回新建的map对象
boolean isCurrentMap = current instanceof Map;
if (!isCurrentMap) {
mapping = new HashMap<>();
mapping.put(
path,
buildObject(paths.subList(index + 1, paths.size()),
value));
return mapping;
}
// 当前是map,但是没有对应的key,也就是我们需要新建对象插入该map,并返回该map
mapping = ((Map) current);
boolean hasSameKey = mapping.containsKey(path);
if (!hasSameKey) {
mapping.put(
path,
buildObject(paths.subList(index + 1, paths.size()),
value));
return mapping;
}
// 当前是map,而且还竟然存在这个值,好吧,继续递归遍历
current = mapping.get(path);
mapping.put(path,
setObjectRecursive(current, paths, index + 1, value));
return mapping;
}
boolean isNeedList = isPathList(path);
if (isNeedList) {
List lists;
int listIndexer = getIndex(path);
// 当前是list,直接新建并返回即可
boolean isCurrentList = current instanceof List;
if (!isCurrentList) {
lists = expand(new ArrayList<>(), listIndexer + 1);
lists.set(
listIndexer,
buildObject(paths.subList(index + 1, paths.size()),
value));
return lists;
}
// 当前是list,但是对应的indexer是没有具体的值,也就是我们新建对象然后插入到该list,并返回该List
lists = expand((List) current, listIndexer + 1);
boolean hasSameIndex = lists.get(listIndexer) != null;
if (!hasSameIndex) {
lists.set(
listIndexer,
buildObject(paths.subList(index + 1, paths.size()),
value));
return lists;
}
// 当前是list,并且存在对应的index,没有办法继续递归寻找
current = lists.get(listIndexer);
lists.set(listIndexer,
setObjectRecursive(current, paths, index + 1, value));
return lists;
}
throw DataXException.asDataXException(CommonErrorCode.RUNTIME_ERROR,
"该异常代表系统编程错误, 请联系DataX开发团队 !");
}
private Object findObject(String path)
{
boolean isRootQuery = StringUtils.isBlank(path);
if (isRootQuery) {
return this.root;
}
Object target = this.root;
for (String each : split2List(path)) {
if (isPathMap(each)) {
target = findObjectInMap(target, each);
}
else {
target = findObjectInList(target, each);
}
}
return target;
}
@SuppressWarnings("unchecked")
private Object findObjectInMap(Object target, String index)
{
boolean isMap = (target instanceof Map);
if (!isMap) {
throw new IllegalArgumentException(String.format(
"您提供的配置文件有误. 路径[%s]需要配置Json格式的Map对象,但该节点发现实际类型是[%s]. 请检查您的配置并作出修改.",
index, target.getClass().toString()));
}
Object result = ((Map) target).get(index);
if (null == result) {
throw new IllegalArgumentException(String.format(
"您提供的配置文件有误. 路径[%s]值为null,datax无法识别该配置. 请检查您的配置并作出修改.", index));
}
return result;
}
@SuppressWarnings({"unchecked"})
private Object findObjectInList(Object target, String each)
{
boolean isList = (target instanceof List);
if (!isList) {
throw new IllegalArgumentException(String.format(
"您提供的配置文件有误. 路径[%s]需要配置Json格式的Map对象,但该节点发现实际类型是[%s]. 请检查您的配置并作出修改.",
each, target.getClass().toString()));
}
String index = each.replace("[", "").replace("]", "");
if (!StringUtils.isNumeric(index)) {
throw new IllegalArgumentException(
String.format(
"系统编程错误,列表下标必须为数字类型,但该节点发现实际类型是[%s] ,该异常代表系统编程错误, 请联系DataX开发团队 !",
index));
}
return ((List) target).get(Integer.parseInt(index));
}
private List expand(List list, int size)
{
int expand = size - list.size();
while (expand-- > 0) {
list.add(null);
}
return list;
}
private boolean isPathList(String path)
{
return path.contains("[") && path.contains("]");
}
private boolean isPathMap(String path)
{
return StringUtils.isNotBlank(path) && !isPathList(path);
}
private int getIndex(String index)
{
return Integer.parseInt(index.replace("[", "").replace("]", ""));
}
private boolean isSuitForRoot(Object object)
{
return (object instanceof List || object instanceof Map);
}
private String split(String path)
{
return StringUtils.replace(path, "[", ".[");
}
private List split2List(String path)
{
return Arrays.asList(StringUtils.split(split(path), "."));
}
private void checkPath(String path)
{
if (null == path) {
throw new IllegalArgumentException(
"系统编程错误, 该异常代表系统编程错误, 请联系DataX开发团队!.");
}
for (String each : StringUtils.split(".")) {
if (StringUtils.isBlank(each)) {
throw new IllegalArgumentException(String.format(
"系统编程错误, 路径[%s]不合法, 路径层次之间不能出现空白字符 .", path));
}
}
}
public Set getSecretKeyPathSet()
{
return secretKeyPathSet;
}
public void setSecretKeyPathSet(Set keyPathSet)
{
if (keyPathSet != null) {
this.secretKeyPathSet = keyPathSet;
}
}
}