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.
jexx.bean.AbstractBeanPropertyAccessor Maven / Gradle / Ivy
package jexx.bean;
import jexx.convert.Convert;
import jexx.exception.UtilException;
import jexx.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;
public abstract class AbstractBeanPropertyAccessor implements PropertyAccessor {
private static final Logger LOG = LoggerFactory.getLogger(AbstractBeanPropertyAccessor.class);
/** 内嵌路径 */
private String nestedPath = "";
/** 包装对象 */
private Object wrappedObject;
/** 父对象 */
private Object rootObject;
/** 允许array,list,set自动增长 */
protected boolean allowCollectionAutoGrow = true;
/**
* 当持有对象为null时, 是否允许创建对象
*
* a.b 持有对象为 a
* a[1][2] 持有对象为 a[1]
* a[1][2].b 持有对象为 a[1][2]
*
*/
protected boolean allowCreateHoldValueIfNull = true;
/**
* 设置包装对象
* @param object 待包装对象
* @param nestedPath 包装对象在父对象中路径
* @param rootObject 父对象
*/
public void setWrappedInstance(Object object, String nestedPath, Object rootObject){
this.wrappedObject = ObjectUtil.unwrapOptional(object);
Assert.notNull(this.wrappedObject, "Target object must not be null");
this.nestedPath = (nestedPath != null ? nestedPath : "");
this.rootObject = (!this.nestedPath.isEmpty() ? rootObject : this.wrappedObject);
}
/**
* 设置包装对象
* @param object 待包装对象
*/
public void setWrappedInstance(Object object){
setWrappedInstance(object, "", null);
}
/**
* 返回包装对象
*/
public final Object getWrappedInstance() {
Assert.isTrue(this.wrappedObject != null, "No wrapped object");
return this.wrappedObject;
}
/**
* 返回包装对象的Class
*/
public final Class getWrappedClass() {
return getWrappedInstance().getClass();
}
/**
* 对象路径
*/
public final String getNestedPath() {
return this.nestedPath;
}
/**
* 根对象
* @return 根对象
*/
public final Object getRootInstance() {
Assert.isTrue(this.rootObject != null, "No root object");
return this.rootObject;
}
/**
* 根对象的class
*/
public final Class getRootClass() {
return getRootInstance().getClass();
}
public void setAllowCollectionAutoGrow(boolean allowCollectionAutoGrow) {
this.allowCollectionAutoGrow = allowCollectionAutoGrow;
}
public void setAllowCreateHoldValueIfNull(boolean allowCreateHoldValueIfNull) {
this.allowCreateHoldValueIfNull = allowCreateHoldValueIfNull;
}
/**
* 根据属性名称获取值
* @param propertyName 属性名称
* @return 值
*/
public Object getPropertyValue(String propertyName){
int index = propertyName.indexOf(NESTED_PROPERTY_SEPARATOR);
if(index > -1){
String nestedProperty = propertyName.substring(0, index);
AbstractBeanPropertyAccessor accessor = getNestedPropertyAccessor(nestedProperty);
return accessor.getPropertyValue(propertyName.substring(index+1));
}
PropertyToken token = getPropertyNameToken(propertyName);
return getPropertyValue(token);
}
protected Object getPropertyValue(PropertyToken token){
String propertyName = token.canonicalName;
String actual = token.actualName;
PropertyHandle handle = getPropertyHandle(actual);
if(handle == null || !handle.isRead()){
throw new BeanException(StringUtil.format("Class[{}] cannot read property {}", getRootClass(), actual));
}
try {
Object value = handle.getValue();
if(token.keys != null){
StringBuilder indexedPropertyName = new StringBuilder(token.actualName);
// apply indexes and map keys
for (int i = 0; i < token.keys.length; i++) {
String key = token.keys[i];
if (value == null) {
throw new BeanException("Cannot read index property \"{}\" because key \"{}\" is null ", propertyName, indexedPropertyName.toString());
}
else if (value.getClass().isArray()) {
int index = Integer.parseInt(key);
value = growArrayIfNecessary(value, index, indexedPropertyName.toString());
value = Array.get(value, index);
}
else if (value instanceof List) {
List list = (List)value;
int index = Integer.parseInt(key);
growCollectionIfNecessary(list, index, indexedPropertyName.toString(), handle, i+1);
value = list.get(index);
}
else if (value instanceof Set) {
// Apply index to Iterator in case of a Set.
Set set = (Set) value;
int index = Integer.parseInt(key);
growCollectionIfNecessary(set, index, indexedPropertyName.toString(), handle, i+1);
if (index < 0 || index >= set.size()) {
throw new BeanException("Cannot get element {} from set because the set's size is {}, path={}", index, set.size(), indexedPropertyName);
}
Iterator it = set.iterator();
for (int j = 0; it.hasNext(); j++) {
Object elem = it.next();
if (j == index) {
value = elem;
break;
}
}
}
else if (value instanceof Map) {
Map map = (Map) value;
Class paramType = handle.getMapKeyType(i+1);
Object convertedMapKey = convertIfNecessary(key, paramType);
value = map.get(convertedMapKey);
}
else {
throw new IllegalArgumentException(StringUtil.format("key {} is not illegal"));
}
indexedPropertyName.append(PROPERTY_KEY_PREFIX).append(key).append(PROPERTY_KEY_SUFFIX);
}
}
return value;
}
catch (Exception e){
throw new BeanException(e);
}
}
/**
* 获取索引属性名称的路径与对应的值;
*
* 如获取a[].b[] :
*
* a[0]b[0]=1
* a[0]b[1]=2
*
*
* @param propertyName 索引属性名称
* @return 路径与对应的值, map有序
*/
public List getIndexPropertyValues(String propertyName){
List indexProperties = new ArrayList<>();
indexProperties.add(new IndexProperty(this.nestedPath, this.wrappedObject));
return getIndexPropertyValues(propertyName, indexProperties);
}
/**
* 获取索引属性名称的路径与对应的值; null值会丢失
*/
public Map getMapIndexPropertyValues(String propertyName){
List indexProperties = getIndexPropertyValues(propertyName);
return indexProperties.stream().collect(Collectors.toMap(IndexProperty::getPath, IndexProperty::getValue));
}
protected List getIndexPropertyValues(String propertyName, List indexProperties){
int index = propertyName.indexOf(NESTED_PROPERTY_SEPARATOR);
if(index > -1){
String nestedProperty = propertyName.substring(0, index);
try {
List newList = new ArrayList<>();
for(IndexProperty property : indexProperties){
AbstractBeanPropertyAccessor accessor = newNestedPropertyAccessor(property.getValue(), property.getPath());
List m1 = accessor.getIndexPropertyValues(nestedProperty);
newList.addAll(m1);
}
return getIndexPropertyValues(propertyName.substring(index+1), newList);
} catch (Exception e) {
throw new BeanException(e);
}
}
PropertyToken token = getPropertyNameToken(propertyName);
List newList = new ArrayList<>();
for(IndexProperty property : indexProperties){
scanPropertyMapValue(newList, property.getPath(), property.getValue(), token, 0);
}
return newList;
}
protected List scanPropertyMapValue(List all, String rootPath, Object holdingObject, PropertyToken token, int keyLocation){
if(holdingObject == null){
if(ArrayUtil.isEmpty(token.keys) || token.keys.length == keyLocation - 1){
String path = StringUtil.isEmpty(rootPath) ? "" : rootPath.concat(".");
all.add(new IndexProperty(path.concat(token.getPath()), null));
return all;
}
return all;
}
if(keyLocation == 0){
AbstractBeanPropertyAccessor accessor = newNestedPropertyAccessor(holdingObject, rootPath);
Object value = accessor.getPropertyValue(token.actualName);
return scanPropertyMapValue(all, rootPath, value, token, keyLocation+1);
}
if(ArrayUtil.isEmpty(token.keys) || token.keys.length == keyLocation - 1){
String path = StringUtil.isEmpty(rootPath) ? "" : rootPath.concat(".");
all.add(new IndexProperty(path.concat(token.getPath()), holdingObject));
return all;
}
int keyIndex = keyLocation - 1;
String key = token.keys[keyIndex];
if (holdingObject.getClass().isArray()){
int length = Array.getLength(holdingObject);
if("".equals(key)){
for(int i = 0; i < length; i++){
Array.get(holdingObject, i);
PropertyToken newToken = token.clone();
newToken.keys[keyIndex] = Integer.toString(i);
scanPropertyMapValue(all, rootPath, Array.get(holdingObject, i), newToken, keyLocation+1);
}
}
else{
int index = Integer.parseInt(key);
if(index < 0 || index >= length){
throw new BeanException("key {} is illegal", key);
}
PropertyToken newToken = token.clone();
scanPropertyMapValue(all, rootPath, Array.get(holdingObject, index), newToken, keyLocation+1);
}
}
else if (holdingObject instanceof List) {
int length = ((List) holdingObject).size();
if("".equals(key)){
for(int i = 0; i < length; i++){
PropertyToken newToken = token.clone();
newToken.keys[keyIndex] = Integer.toString(i);
scanPropertyMapValue(all, rootPath, ((List) holdingObject).get(i), newToken, keyLocation+1);
}
}
else{
int index = Integer.parseInt(key);
if(index < 0 || index >= length){
throw new BeanException("key {} is illegal", key);
}
PropertyToken newToken = token.clone();
scanPropertyMapValue(all, rootPath, Array.get(holdingObject, index), newToken, keyLocation+1);
}
}
else if (holdingObject instanceof Set) {
Set set = (Set) holdingObject;
int length = set.size();
if("".equals(key)){
Iterator it = set.iterator();
for (int i = 0; it.hasNext(); i++) {
Object elem = it.next();
PropertyToken newToken = token.clone();
newToken.keys[keyIndex] = Integer.toString(i);
scanPropertyMapValue(all, rootPath, elem, newToken, keyLocation+1);
}
}
else{
int index = Integer.parseInt(key);
if(index < 0 || index >= length){
throw new BeanException("key {} is illegal", key);
}
Iterator it = set.iterator();
for (int i = 0; it.hasNext(); i++) {
if(i == index){
Object elem = it.next();
PropertyToken newToken = token.clone();
newToken.keys[keyIndex] = Integer.toString(i);
scanPropertyMapValue(all, rootPath, elem, newToken, keyLocation+1);
break;
}
}
}
}
else if (holdingObject instanceof Map) {
Map mValue = (Map) holdingObject;
if("".equals(key)){
for(Map.Entry entry : mValue.entrySet()){
PropertyToken newToken = token.clone();
newToken.keys[keyIndex] = entry.getKey().toString();
scanPropertyMapValue(all, rootPath, entry.getValue(), newToken, keyLocation+1);
}
}
else{
PropertyToken newToken = token.clone();
scanPropertyMapValue(all, rootPath, mValue.get(key), newToken, keyLocation+1);
}
}
return all;
}
/**
* 获取索引属性名称上一级的值; 如 属性名称为 a[a1][a2] 即 上一级为 a[a1]
* @param token 索引属性token
*/
protected Object getPropertyHoldingValue(PropertyToken token){
PropertyToken holdingToken = getPropertyHoldingToken(token);
return getPropertyValue(holdingToken);
}
/**
* 获取token的上一级token
* @param token token
* @return 上一级属性的token
*/
protected PropertyToken getPropertyHoldingToken(PropertyToken token){
Assert.isTrue(token.keys != null, "No token keys");
String canonicalName = token.canonicalName;
int lastIndex = canonicalName.lastIndexOf(PROPERTY_KEY_PREFIX);
canonicalName = canonicalName.substring(0, lastIndex);
String[] keys = new String[token.keys.length - 1];
System.arraycopy(token.keys, 0, keys, 0, token.keys.length - 1);
PropertyToken holdingToken = new PropertyToken(token.actualName);
holdingToken.canonicalName = canonicalName;
holdingToken.keys = keys;
return holdingToken;
}
/**
* 确保属性持有者不为null
*/
private void ensurePropertyHoldingValueNotNull(PropertyToken token){
if(this.allowCreateHoldValueIfNull && token.keys != null){
try {
PropertyHandle ph = getPropertyHandle(token.actualName);
Object value = ph.getValue();
if(value == null){
value = newValue(ph.getPropertyType(), null, token.actualName);
ph.setValue(value);
}
StringBuilder indexedPropertyName = new StringBuilder(token.actualName);
for (int i = 0; i < token.keys.length-1; i++) {
String key = token.keys[i];
if (value.getClass().isArray()) {
int index = Integer.parseInt(key);
value = growArrayIfNecessary(value, index, indexedPropertyName.toString());
Object v = Array.get(value, index);
if(v == null){
v = newValue(ph.getNestedType(i+1), null, key);
Array.set(value, index, v);
}
value = v;
}
else if (value instanceof List) {
List list = (List)value;
int index = Integer.parseInt(key);
growCollectionIfNecessary(list, index, indexedPropertyName.toString(), ph, i+1);
Object v = list.get(index);
if(v == null){
v = newValue(ph.getNestedType(i+1), null, key);
Array.set(value, index, v);
}
value = v;
}
else if (value instanceof Set) {
Set set = (Set)value;
int index = Integer.parseInt(key);
if (index < 0 || index >= set.size()) {
throw new BeanException(StringUtil.format("property name {} key[{}] is big!", indexedPropertyName, key));
}
Object v = null;
Iterator it = set.iterator();
for (int j = 0; it.hasNext(); j++) {
Object elem = it.next();
if (j == index) {
v = elem;
break;
}
}
if(v == null){
v = newValue(ph.getNestedType(i+1), null, key);
Array.set(value, index, v);
}
value = v;
}
else if (value instanceof Map) {
Map map = (Map) value;
Class paramType = ph.getMapKeyType(i+1);
Object convertedMapKey = convertIfNecessary(key, paramType);
Object v = map.get(convertedMapKey);
if(v == null){
v = newValue(ph.getMapValueType(i+1), null, key);
map.put(convertedMapKey, v);
}
value = v;
}
else {
throw new IllegalArgumentException(StringUtil.format("key {} is not illegal"));
}
indexedPropertyName.append(PROPERTY_KEY_PREFIX).append(key).append(PROPERTY_KEY_SUFFIX);
}
}
catch (Exception e){
LOG.error("", e);
}
}
}
public void setPropertyValue(String propertyName, Object value){
int index = propertyName.indexOf(NESTED_PROPERTY_SEPARATOR);
if(index > -1){
String nestedProperty = propertyName.substring(0, index);
AbstractBeanPropertyAccessor accessor = getNestedPropertyAccessor(nestedProperty);
accessor.setPropertyValue(propertyName.substring(index+1), value);
}
else{
PropertyToken token = getPropertyNameToken(propertyName);
setPropertyValue(token, value);
}
}
protected void setPropertyValue(PropertyToken token, Object newValue){
PropertyHandle ph = getPropertyHandle(token.actualName);
if(ph == null || !ph.isWrite()){
throw new BeanException("Class[{}] cannot write property {}", getWrappedClass(), token.actualName);
}
try {
ensurePropertyHoldingValueNotNull(token);
if(token.keys != null){
String lastKey = token.keys[token.keys.length - 1];
PropertyToken holdingToken = getPropertyHoldingToken(token);
Object holdingValue = getPropertyValue(holdingToken);
if(holdingValue == null){
throw new BeanException("Class[{}] cannot write index property {} because holding key {} is null ", getWrappedClass(), token.canonicalName, holdingToken.canonicalName);
}
else if(holdingValue.getClass().isArray()){
Class requiredType = holdingValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(lastKey);
int length = Array.getLength(holdingValue);
if(this.allowCollectionAutoGrow && arrayIndex >= length){
holdingValue = growArrayIfNecessary(holdingValue, arrayIndex, holdingToken.canonicalName);
}
Object convertValue = convertIfNecessary(newValue, requiredType);
Array.set(holdingValue, arrayIndex, convertValue);
}
else if(holdingValue instanceof List){
List list = (List)holdingValue;
Class requiredType = ph.getNestedType(token.keys.length);
int arrayIndex = Integer.parseInt(lastKey);
if(this.allowCollectionAutoGrow && arrayIndex >= list.size()){
for (int i = list.size(); i <= arrayIndex; i++) {
if(i == arrayIndex){
list.add(Convert.convert(requiredType, newValue));
}
else{
list.add(newValue(requiredType, null, holdingToken.canonicalName));
}
}
}
else{
list.set(arrayIndex, Convert.convert(requiredType, newValue));
}
}
else if(holdingValue instanceof Set){
Set set = (Set)holdingValue;
int arrayIndex = Integer.parseInt(lastKey);
//只能添加元素
if(arrayIndex != set.size()){
throw new BeanException("only add element for set of size {}, path={}", arrayIndex, set.size(), holdingToken.canonicalName);
}
Class requiredType = ph.getNestedType(token.keys.length);
set.add(Convert.convert(requiredType, newValue));
}
else if (holdingValue instanceof Map){
Map map = (Map)holdingValue;
Class keyType = ph.getMapKeyType(token.keys.length);
Object key = Convert.convert(keyType, lastKey);
Class valueType = ph.getMapValueType(token.keys.length);
Object value = Convert.convert(valueType, newValue);
map.put(key, value);
}
else{
throw new IllegalArgumentException(StringUtil.format("Class[{}] property {} is neither an array or a list or a map"
,getWrappedClass(), holdingToken.canonicalName));
}
}
else{
ph.setValue(newValue);
}
}
catch (Exception e){
throw new BeanException(e);
}
}
protected PropertyToken getPropertyNameToken(String propertyName){
String actualName = null;
List keys = new ArrayList<>(2);
int searchIndex = 0;
while (searchIndex != -1) {
int keyStart = propertyName.indexOf(PROPERTY_KEY_PREFIX, searchIndex);
searchIndex = -1;
if (keyStart != -1) {
int keyEnd = propertyName.indexOf(PROPERTY_KEY_SUFFIX, keyStart + PROPERTY_KEY_PREFIX.length());
if (keyEnd != -1) {
if (actualName == null) {
actualName = propertyName.substring(0, keyStart);
}
String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd);
if (key.length() > 1 && (key.startsWith("'") && key.endsWith("'")) ||
(key.startsWith("\"") && key.endsWith("\""))) {
key = key.substring(1, key.length() - 1);
}
keys.add(key);
searchIndex = keyEnd + PROPERTY_KEY_SUFFIX.length();
}
}
}
PropertyToken tokens = new PropertyToken(actualName != null ? actualName : propertyName);
if (!keys.isEmpty()) {
tokens.canonicalName += PROPERTY_KEY_PREFIX.concat(StringUtil.join(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX)).concat(PROPERTY_KEY_SUFFIX);
tokens.keys = ArrayUtil.toStringArray(keys);
}
return tokens;
}
/**
* 获取属性处理类
*/
protected abstract PropertyHandle getPropertyHandle(String propertyName);
/**
* 根据类型转换为对应的属性
* @param value 值
* @param type 值对应属性
* @return 转换后的值
*/
private Object convertIfNecessary(Object value, Type type){
return Convert.convert(type, value);
}
/**
* 自动增长数组
* @param array 数组对象
* @param index 索引
* @param name 属性名称
* @return 数组索引值
*/
private Object growArrayIfNecessary(Object array, int index, String name){
int length = Array.getLength(array);
if(this.allowCollectionAutoGrow && index >= length){
Class componentType = array.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, index+1);
System.arraycopy(array, 0, newArray, 0, length);
setPropertyValue(name, newArray);
return newArray;
}
return array;
}
private Collection growCollectionIfNecessary(Collection collection, int index, String name, PropertyHandle pd, int nestingLevel){
int size = collection.size();
if(this.allowCollectionAutoGrow && index >= size){
Class elementType = pd.getNestedType(nestingLevel);
if(elementType != null){
for(int i = size; i <= index; i++){
collection.add(newValue(elementType, null, name));
}
}
}
return collection;
}
/**
* 根据类型创建value
* @param type 对象类型
* @param elementType 对象为集合时的元素类型
* @param name 属性名称
* @return value
*/
private Object newValue(Class type, Class elementType, String name) {
try {
if (type.isArray()) {
Class componentType = type.getComponentType();
// TODO - only handles 2-dimensional arrays
if (componentType.isArray()) {
Object array = Array.newInstance(componentType, 1);
Array.set(array, 0, Array.newInstance(componentType.getComponentType(), 0));
return array;
}
else {
return Array.newInstance(componentType, 0);
}
}
else if (Collection.class.isAssignableFrom(type)) {
return CollectionUtil.createCollection(type, elementType, 16);
}
else if (Map.class.isAssignableFrom(type)) {
return MapUtil.createMap(type, elementType, 16);
}
else {
Constructor ctor = type.getDeclaredConstructor();
if (Modifier.isPrivate(ctor.getModifiers())) {
if(this.allowCollectionAutoGrow){
}
throw new IllegalAccessException("Auto-growing not allowed with private constructor: " + ctor);
}
return ReflectUtil.newInstance(ctor);
}
}
catch (Throwable ex) {
throw new UtilException(ex, "Could not instantiate property type \"{}\" to auto-grow nested property path {}", type.getName(), name);
}
}
/**
* 构造属性寄存对象
* @param object 当前对象
* @param nestedPath 当前内嵌路径
* @return 属性寄存对象
*/
protected abstract AbstractBeanPropertyAccessor newNestedPropertyAccessor(Object object, String nestedPath);
/**
* 根据内嵌属性名称获取属性寄存器对象
* @param nestedProperty 含有内嵌变量的属性,如a[1], a["b"]
* @return 属性寄存对象器
*/
private AbstractBeanPropertyAccessor getNestedPropertyAccessor(String nestedProperty) {
PropertyToken tokens = getPropertyNameToken(nestedProperty);
String canonicalName = tokens.canonicalName;
//确保持有属性不为空
ensurePropertyHoldingValueNotNull(tokens);
Object value = getPropertyValue(tokens);
if(this.allowCreateHoldValueIfNull && value == null){
PropertyHandle ph = getPropertyHandle(tokens.actualName);
Class clazz = tokens.keys != null ?ph.getNestedType(tokens.keys.length): ph.getPropertyType();
value = newValue(clazz, null, tokens.actualName);
setPropertyValue(tokens, value);
}
if(value == null){
throw new BeanException("property \"{}\" is null", nestedProperty);
}
AbstractBeanPropertyAccessor propertyAccessor = newNestedPropertyAccessor(value, this.nestedPath+canonicalName+NESTED_PROPERTY_SEPARATOR);
return propertyAccessor;
}
protected abstract static class PropertyHandle{
private String propertyName;
private boolean read;
private boolean write;
public PropertyHandle(String propertyName, boolean read, boolean write) {
this.propertyName = propertyName;
this.read = read;
this.write = write;
}
public boolean isRead(){
return this.read;
}
public boolean isWrite(){
return this.write;
}
public abstract Object getValue() throws Exception;
public abstract void setValue(Object value) throws Exception;
/** 获取属性类型 */
public abstract Class getPropertyType();
public abstract Class getCollectionType(int nestingLevel);
public abstract Class getMapKeyType(int nestingLevel);
public abstract Class getMapValueType(int nestingLevel);
/**
* 获取集合类内嵌内省
* @param nestingLevel 内嵌层次
* @param typeIndexesPerLevel 每个层次对应索引类型, 如Map有两个类型
* @return 指定层次的内嵌类型
*/
protected abstract Class getNestedType(int nestingLevel, Map typeIndexesPerLevel);
public Class getNestedType(int nestingLevel){
return getNestedType(nestingLevel, null);
}
/**
* type解析成对应的class
*/
protected Class resolveClass(Type type){
if(type == null){
return null;
}
if(type instanceof Class){
return (Class)type;
}
if(type instanceof GenericArrayType){
return ((GenericArrayType) type).getGenericComponentType().getClass();
}
if(type instanceof ParameterizedType){
Type newType = ((ParameterizedType) type).getRawType();
return resolveClass(newType);
}
return null;
}
}
protected static class PropertyToken{
/** 属性名, 如 a[1]为a */
protected String actualName;
/** 标准属性名(全路径), 如 a */
protected String canonicalName;
/** 属性key, 1 */
protected String[] keys;
public PropertyToken(String propertyName) {
this.actualName = propertyName;
this.canonicalName = propertyName;
}
public PropertyToken clone(){
PropertyToken token = new PropertyToken(this.actualName);
token.canonicalName = canonicalName;
token.keys = ObjectUtil.clone(keys);
return token;
}
public String getPath(){
String canonicalName = actualName;
if(ArrayUtil.isNotEmpty(keys)){
String str = PROPERTY_KEY_PREFIX.concat(StringUtil.join(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX)).concat(PROPERTY_KEY_SUFFIX);
canonicalName = actualName.concat(str);
}
return canonicalName;
}
}
}