com.github.datalking.beans.factory.config.ConstructorArgumentValues Maven / Gradle / Ivy
package com.github.datalking.beans.factory.config;
import com.github.datalking.beans.Mergeable;
import com.github.datalking.util.Assert;
import com.github.datalking.util.ClassUtils;
import com.github.datalking.util.ObjectUtils;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 构造函数参数值,常作为BeanDefinition的一部分
*
* Holder for constructor argument values, typically as part of a bean definition.
* Supports values for a specific index in the constructor argument list as well as for generic argument matches by type.
*/
public class ConstructorArgumentValues {
private final Map indexedArgumentValues = new LinkedHashMap<>(0);
private final List genericArgumentValues = new LinkedList<>();
public ConstructorArgumentValues() {
}
public ConstructorArgumentValues(ConstructorArgumentValues original) {
// 深拷贝
addArgumentValues(original);
}
public void addArgumentValues(ConstructorArgumentValues other) {
if (other != null) {
for (Map.Entry entry : other.indexedArgumentValues.entrySet()) {
addOrMergeIndexedArgumentValue(entry.getKey(), entry.getValue().copy());
}
for (ValueHolder valueHolder : other.genericArgumentValues) {
if (!this.genericArgumentValues.contains(valueHolder)) {
addOrMergeGenericArgumentValue(valueHolder.copy());
}
}
}
}
public void addIndexedArgumentValue(int index, Object value) {
addIndexedArgumentValue(index, new ValueHolder(value));
}
public void addIndexedArgumentValue(int index, Object value, String type) {
addIndexedArgumentValue(index, new ValueHolder(value, type));
}
public void addIndexedArgumentValue(int index, ValueHolder newValue) {
Assert.isTrue(index >= 0, "Index must not be negative");
Assert.notNull(newValue, "ValueHolder must not be null");
addOrMergeIndexedArgumentValue(index, newValue);
}
private void addOrMergeIndexedArgumentValue(Integer key, ValueHolder newValue) {
ValueHolder currentValue = this.indexedArgumentValues.get(key);
if (currentValue != null && newValue.getValue() instanceof Mergeable) {
Mergeable mergeable = (Mergeable) newValue.getValue();
if (mergeable.isMergeEnabled()) {
newValue.setValue(mergeable.merge(currentValue.getValue()));
}
}
this.indexedArgumentValues.put(key, newValue);
}
public boolean hasIndexedArgumentValue(int index) {
return this.indexedArgumentValues.containsKey(index);
}
public ValueHolder getIndexedArgumentValue(int index, Class> requiredType) {
return getIndexedArgumentValue(index, requiredType, null);
}
public ValueHolder getIndexedArgumentValue(int index, Class> requiredType, String requiredName) {
Assert.isTrue(index >= 0, "Index must not be negative");
ValueHolder valueHolder = this.indexedArgumentValues.get(index);
if (valueHolder != null &&
(valueHolder.getType() == null ||
(requiredType != null && ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) &&
(valueHolder.getName() == null ||
(requiredName != null && requiredName.equals(valueHolder.getName())))) {
return valueHolder;
}
return null;
}
public Map getIndexedArgumentValues() {
return Collections.unmodifiableMap(this.indexedArgumentValues);
}
public void addGenericArgumentValue(Object value) {
this.genericArgumentValues.add(new ValueHolder(value));
}
public void addGenericArgumentValue(Object value, String type) {
this.genericArgumentValues.add(new ValueHolder(value, type));
}
public void addGenericArgumentValue(ValueHolder newValue) {
Assert.notNull(newValue, "ValueHolder must not be null");
if (!this.genericArgumentValues.contains(newValue)) {
addOrMergeGenericArgumentValue(newValue);
}
}
private void addOrMergeGenericArgumentValue(ValueHolder newValue) {
if (newValue.getName() != null) {
for (Iterator it = this.genericArgumentValues.iterator(); it.hasNext(); ) {
ValueHolder currentValue = it.next();
if (newValue.getName().equals(currentValue.getName())) {
if (newValue.getValue() instanceof Mergeable) {
Mergeable mergeable = (Mergeable) newValue.getValue();
if (mergeable.isMergeEnabled()) {
newValue.setValue(mergeable.merge(currentValue.getValue()));
}
}
it.remove();
}
}
}
this.genericArgumentValues.add(newValue);
}
public ValueHolder getGenericArgumentValue(Class> requiredType) {
return getGenericArgumentValue(requiredType, null, null);
}
public ValueHolder getGenericArgumentValue(Class> requiredType, String requiredName) {
return getGenericArgumentValue(requiredType, requiredName, null);
}
public ValueHolder getGenericArgumentValue(Class> requiredType, String requiredName, Set usedValueHolders) {
for (ValueHolder valueHolder : this.genericArgumentValues) {
if (usedValueHolders != null && usedValueHolders.contains(valueHolder)) {
continue;
}
if (valueHolder.getName() != null &&
(requiredName == null || !valueHolder.getName().equals(requiredName))) {
continue;
}
if (valueHolder.getType() != null &&
(requiredType == null || !ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) {
continue;
}
if (requiredType != null && valueHolder.getType() == null && valueHolder.getName() == null &&
!ClassUtils.isAssignableValue(requiredType, valueHolder.getValue())) {
continue;
}
return valueHolder;
}
return null;
}
public List getGenericArgumentValues() {
return Collections.unmodifiableList(this.genericArgumentValues);
}
public ValueHolder getArgumentValue(int index, Class> requiredType) {
return getArgumentValue(index, requiredType, null, null);
}
public ValueHolder getArgumentValue(int index, Class> requiredType, String requiredName) {
return getArgumentValue(index, requiredType, requiredName, null);
}
public ValueHolder getArgumentValue(int index, Class> requiredType, String requiredName, Set usedValueHolders) {
Assert.isTrue(index >= 0, "Index must not be negative");
ValueHolder valueHolder = getIndexedArgumentValue(index, requiredType, requiredName);
if (valueHolder == null) {
valueHolder = getGenericArgumentValue(requiredType, requiredName, usedValueHolders);
}
return valueHolder;
}
public int getArgumentCount() {
return (this.indexedArgumentValues.size() + this.genericArgumentValues.size());
}
public boolean isEmpty() {
return (this.indexedArgumentValues.isEmpty() && this.genericArgumentValues.isEmpty());
}
public void clear() {
this.indexedArgumentValues.clear();
this.genericArgumentValues.clear();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ConstructorArgumentValues)) {
return false;
}
ConstructorArgumentValues that = (ConstructorArgumentValues) other;
if (this.genericArgumentValues.size() != that.genericArgumentValues.size() ||
this.indexedArgumentValues.size() != that.indexedArgumentValues.size()) {
return false;
}
Iterator it1 = this.genericArgumentValues.iterator();
Iterator it2 = that.genericArgumentValues.iterator();
while (it1.hasNext() && it2.hasNext()) {
ValueHolder vh1 = it1.next();
ValueHolder vh2 = it2.next();
if (!vh1.contentEquals(vh2)) {
return false;
}
}
for (Map.Entry entry : this.indexedArgumentValues.entrySet()) {
ValueHolder vh1 = entry.getValue();
ValueHolder vh2 = that.indexedArgumentValues.get(entry.getKey());
if (!vh1.contentEquals(vh2)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
int hashCode = 7;
for (ValueHolder valueHolder : this.genericArgumentValues) {
hashCode = 31 * hashCode + valueHolder.contentHashCode();
}
hashCode = 29 * hashCode;
for (Map.Entry entry : this.indexedArgumentValues.entrySet()) {
hashCode = 31 * hashCode + (entry.getValue().contentHashCode() ^ entry.getKey().hashCode());
}
return hashCode;
}
@Override
public String toString() {
return "{" +
"indexedArgVals=" + indexedArgumentValues.size() +
", genericArgVals=" + genericArgumentValues.size() +
'}';
}
/**
* Holder for a constructor argument value, with an optional type attribute indicating the target type of the actual constructor argument.
*/
// public static class ValueHolder implements BeanMetadataElement {
public static class ValueHolder {
// 构造方法xxx
private Object value;
// 构造方法xxx
private String type;
// 构造方法xxx
private String name;
private Object source;
private boolean converted = false;
private Object convertedValue;
public ValueHolder(Object value) {
this.value = value;
}
public ValueHolder(Object value, String type) {
this.value = value;
this.type = type;
}
public ValueHolder(Object value, String type, String name) {
this.value = value;
this.type = type;
this.name = name;
}
public void setValue(Object value) {
this.value = value;
}
public Object getValue() {
return this.value;
}
public void setType(String type) {
this.type = type;
}
public String getType() {
return this.type;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setSource(Object source) {
this.source = source;
}
public Object getSource() {
return this.source;
}
public synchronized boolean isConverted() {
return this.converted;
}
public synchronized void setConvertedValue(Object value) {
this.converted = true;
this.convertedValue = value;
}
public synchronized Object getConvertedValue() {
return this.convertedValue;
}
private boolean contentEquals(ValueHolder other) {
return (this == other ||
(ObjectUtils.nullSafeEquals(this.value, other.value) && ObjectUtils.nullSafeEquals(this.type, other.type)));
}
private int contentHashCode() {
return ObjectUtils.nullSafeHashCode(this.value) * 29 + ObjectUtils.nullSafeHashCode(this.type);
}
public ValueHolder copy() {
ValueHolder copy = new ValueHolder(this.value, this.type, this.name);
copy.setSource(this.source);
return copy;
}
}
}