2021SC@SDUSC
/*
* 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 org.apache.lucene.util;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.UndeclaredThrowableException;
/**
* AttributeFactory 创建 {@link AttributeImpl} 的实例。
*/
public abstract class AttributeFactory {
/**
* 为提供的 {@link Attribute} 接口类返回一个 {@link AttributeImpl}。
*
* @throws UndeclaredThrowableException 一个包装运行时异常抛出,如果
* 属性类的构造函数抛出一个检查异常。
* 请注意,属性不应抛出或声明
* 检查异常; 这可能会在未来早期得到验证并失败。
*/
public abstract AttributeImpl createAttributeInstance(Class<? extends Attribute> attClass)
throws UndeclaredThrowableException;
/**
* 为给定类的无参数构造函数返回正确类型的 {@link MethodHandle}。
*/
static final MethodHandle findAttributeImplCtor(Class<? extends AttributeImpl> clazz) {
try {
return lookup.findConstructor(clazz, NO_ARG_CTOR).asType(NO_ARG_RETURNING_ATTRIBUTEIMPL);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new IllegalArgumentException("Cannot lookup accessible no-arg constructor for: " + clazz.getName(), e);
}
}
private static final MethodHandles.Lookup lookup = MethodHandles.publicLookup();
private static final MethodType NO_ARG_CTOR = MethodType.methodType(void.class);
private static final MethodType NO_ARG_RETURNING_ATTRIBUTEIMPL = MethodType.methodType(AttributeImpl.class);
/**
* 这是使用 {@link AttributeImpl} 创建的
* 提供的 {@link Attribute} 接口类的类名,通过附加 <code>Impl</code> 到它。
*/
public static final AttributeFactory DEFAULT_ATTRIBUTE_FACTORY = new DefaultAttributeFactory();
private static final class DefaultAttributeFactory extends AttributeFactory {
private final ClassValue<MethodHandle> constructors = new ClassValue<MethodHandle>() {
@Override
protected MethodHandle computeValue(Class<?> attClass) {
return findAttributeImplCtor(findImplClass(attClass.asSubclass(Attribute.class)));
}
};
DefaultAttributeFactory() {}
@Override
public AttributeImpl createAttributeInstance(Class<? extends Attribute> attClass) {
try {
return (AttributeImpl) constructors.get(attClass).invokeExact();
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
private Class<? extends AttributeImpl> findImplClass(Class<? extends Attribute> attClass) {
try {
return Class.forName(attClass.getName() + "Impl", true, attClass.getClassLoader()).asSubclass(AttributeImpl.class);
} catch (ClassNotFoundException cnfe) {
throw new IllegalArgumentException("Cannot find implementing class for: " + attClass.getName());
}
}
}
/** <b>Expert</b>: AttributeFactory 返回给定 {@code clazz} 的实例,用于
* 它实现的属性。 对于所有其他属性,它调用给定的委托工厂
* 作为后备。 此类可用于首选特定的 {@code AttributeImpl}
* 在不同的类上组合多个属性。
* @lucene.internal
*/
public abstract static class StaticImplementationAttributeFactory<A extends AttributeImpl> extends AttributeFactory {
private final AttributeFactory delegate;
private final Class<A> clazz;
/** <b>Expert</b>:创建一个返回 {@code clazz} 作为实例的 AttributeFactory
* 它实现的属性和所有其他属性调用给定的委托工厂。 */
public StaticImplementationAttributeFactory(AttributeFactory delegate, Class<A> clazz) {
this.delegate = delegate;
this.clazz = clazz;
}
@Override
public final AttributeImpl createAttributeInstance(Class<? extends Attribute> attClass) {
return attClass.isAssignableFrom(clazz) ? createInstance() : delegate.createAttributeInstance(attClass);
}
/** Creates an instance of {@code A}. */
protected abstract A createInstance();
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || other.getClass() != this.getClass())
return false;
@SuppressWarnings("rawtypes")
final StaticImplementationAttributeFactory af = (StaticImplementationAttributeFactory) other;
return this.delegate.equals(af.delegate) && this.clazz == af.clazz;
}
@Override
public int hashCode() {
return 31 * delegate.hashCode() + clazz.hashCode();
}
}
/** 返回一个 AttributeFactory 返回给定 {@code clazz} 的实例
* 它实现的属性。 给定的 {@code clazz} 必须有一个公共的无参数构造函数。
* 对于所有其他属性,它调用给定的委托工厂作为回退。
* 此方法可用于偏好特定的 {@code AttributeImpl},它结合了
* 不同类的多个属性。
* <p>请将此方法创建的实例保存在静态final字段中,因为
* 在每次调用时,这都会反射以创建 {@link MethodHandle}。
*/
public static <A extends AttributeImpl> AttributeFactory getStaticImplementation(AttributeFactory delegate, Class<A> clazz) {
final MethodHandle constr = findAttributeImplCtor(clazz);
return new StaticImplementationAttributeFactory<A>(delegate, clazz) {
@Override
protected A createInstance() {
try {
return (A) constr.invokeExact();
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
};
}
}