org.geoserver.wfs.GetPropertyValue#run
public ValueCollectionType run(GetPropertyValueType request) throws WFSException {
// 检查请求中的valueReference是否为空
if (request.getValueReference() == null) {
throw new WFSException(request, "No valueReference specified", "MissingParameterValue")
.locator("valueReference");
} else if ("".equals(request.getValueReference().trim())) {
// 检查请求中的valueReference是否为空字符串
throw new WFSException(
request,
"ValueReference cannot be empty",
ServiceException.INVALID_PARAMETER_VALUE)
.locator("valueReference");
}
// 执行getFeature请求
GetFeatureType getFeature = Wfs20Factory.eINSTANCE.createGetFeatureType();
getFeature.setBaseUrl(request.getBaseUrl());
getFeature.getAbstractQueryExpression().add(request.getAbstractQueryExpression());
getFeature.setResolve(request.getResolve());
getFeature.setResolveDepth(request.getResolveDepth());
getFeature.setResolveTimeout(request.getResolveTimeout());
getFeature.setCount(request.getCount());
// 获取特征集合
FeatureCollectionType fc =
(FeatureCollectionType)
delegate.run(GetFeatureRequest.adapt(getFeature)).getAdaptee();
// 获取查询类型和特征类型信息
QueryType query = (QueryType) request.getAbstractQueryExpression();
QName typeName = (QName) query.getTypeNames().iterator().next();
FeatureTypeInfo featureType =
catalog.getFeatureTypeByName(typeName.getNamespaceURI(), typeName.getLocalPart());
try {
// 创建属性名称对象,包括去除索引后的属性名称对象
PropertyName propertyName =
filterFactory.property(request.getValueReference(), getNamespaceSupport());
PropertyName propertyNameNoIndexes =
filterFactory.property(
request.getValueReference().replaceAll("\\\\[.*\\\\]", ""),
getNamespaceSupport());
// 获取属性描述符
// !!!!!
AttributeDescriptor descriptor =
(AttributeDescriptor)
propertyNameNoIndexes.evaluate(featureType.getFeatureType());
// 检查请求的属性是否为特征ID
boolean featureIdRequest =
FEATURE_ID_PATTERN.matcher(request.getValueReference()).matches();
if (descriptor == null && !featureIdRequest) {
// 如果属性描述符为空且请求的不是特征ID,则抛出异常
throw new WFSException(
request, "No such attribute: " + request.getValueReference());
}
// 从特征集合创建值集合类型
ValueCollectionType vc = Wfs20Factory.eINSTANCE.createValueCollectionType();
vc.setTimeStamp(fc.getTimeStamp());
vc.setNumberMatched(fc.getNumberMatched());
vc.setNumberReturned(fc.getNumberReturned());
vc.getMember()
.add(
new PropertyValueCollection(
fc.getMember().iterator().next(), descriptor, propertyName));
return vc;
} catch (IOException e) {
// 处理IO异常并抛出WFS异常
throw new WFSException(request, e);
}
}
该方法处理请求,获取指定属性值的特征集合,并返回包含这些值的集合类型。
org.geotools.filter.AttributeExpressionImpl#evaluate(java.lang.Object, java.lang.Class)
public <T> T evaluate(Object obj, Class<T> target) {
// 初始化上次使用的属性访问器
PropertyAccessor accessor = this.lastAccessor;
// 初始化默认属性值为 false
Object value = false;
// 标记访问是否成功
boolean success = false;
// 尝试使用上次的属性访问器获取属性值
if (accessor != null && accessor.canHandle(obj, this.attPath, target)) {
try {
// 获取属性值
value = accessor.get(obj, this.attPath, target);
success = true;
} catch (Exception var11) {
// 忽略异常
}
}
// 如果上次的访问器无法处理,尝试其他访问器
if (!success) {
// 如果存在命名空间支持但没有提示信息,则创建提示信息
if (this.namespaceSupport != null && this.hints == null) {
this.hints = new Hints(PropertyAccessorFactory.NAMESPACE_CONTEXT, this.namespaceSupport);
}
// 查找可用的属性访问器
List<PropertyAccessor> accessors = PropertyAccessors.findPropertyAccessors(obj, this.attPath, target, this.hints);
List<Exception> exceptions = null;
// 遍历所有找到的访问器
if (accessors != null) {
Iterator var8 = accessors.iterator();
while(var8.hasNext()) {
PropertyAccessor propertyAccessor = (PropertyAccessor)var8.next();
accessor = propertyAccessor;
try {
// 尝试获取属性值
// !!!!!
value = accessor.get(obj, this.attPath, target);
success = true;
break;
} catch (Exception var12) {
// 捕获异常,记录到异常列表
if (exceptions == null) {
exceptions = new ArrayList();
}
exceptions.add(var12);
}
}
}
// 如果所有访问器都失败,处理异常
if (!success) {
// 如果启用了宽松模式,返回 null
if (this.lenient) {
return null;
}
// 构造包含所有异常信息的 IllegalArgumentException
IllegalArgumentException exception = new IllegalArgumentException("Could not find working property accessor for attribute (" + this.attPath + ") in object (" + obj + ")");
if (exceptions != null) {
exceptions.forEach((e) -> {
exception.addSuppressed(exception);
});
}
// 抛出异常
throw exception;
}
// 缓存成功的访问器
this.lastAccessor = accessor;
}
// 返回转换后的值,如果 target 为空则直接返回值
return target == null ? value : Converters.convert(value, target);
}
这个方法用于在给定对象中查找并获取指定属性的值,并根据目标类型进行转换。
主要逻辑如下:
- 初始化:
- 初始化上次使用的属性访问器
accessor
。 - 初始化默认属性值
value
为false
,并标记访问是否成功success
为false
。
- 初始化上次使用的属性访问器
- 尝试使用上次的属性访问器:
- 如果上次的属性访问器存在且可以处理当前对象和目标类型,则尝试使用它获取属性值。
- 如果获取成功,则标记
success
为true
。
- 尝试其他访问器:
- 如果上次的访问器无法处理,检查是否存在命名空间支持且没有提示信息,如果是则创建提示信息。
- 查找所有可以处理当前对象和目标类型的属性访问器。
- 遍历所有找到的访问器,尝试使用它们获取属性值。
- 如果获取成功,则标记
success
为true
并退出循环。 - 如果获取失败,则捕获异常并记录到异常列表。
- 处理失败情况:
- 如果所有访问器都失败且启用了宽松模式,则返回
null
。 - 如果未启用宽松模式,则构造包含所有异常信息的
IllegalArgumentException
并抛出。
- 如果所有访问器都失败且启用了宽松模式,则返回
- 缓存成功的访问器:
- 缓存成功的访问器
accessor
以便下次使用。
- 缓存成功的访问器
- 返回结果:
- 根据目标类型
target
进行类型转换并返回结果。如果目标类型为空,则直接返回值。
- 根据目标类型
这段代码体现了以下设计思想:
- 缓存机制:
- 通过缓存
lastAccessor
属性访问器,避免每次调用evaluate
方法时都需要重新查找合适的访问器,从而提升性能。
- 通过缓存
- 责任链模式:
- 使用多个
PropertyAccessor
实现属性访问的责任链模式。如果一个访问器无法处理请求,则尝试下一个访问器,直到找到合适的为止。
- 使用多个
- 宽松模式(Lenient Mode):
- 提供宽松模式(
lenient
)的支持。如果所有访问器都失败且启用了宽松模式,则返回null
,而不是抛出异常。这在某些情况下可以提高系统的容错性。
- 提供宽松模式(
- 异常处理:
- 在访问器失败时,捕获并记录异常,最后统一处理并抛出包含所有失败信息的异常。这种方式提供了详细的错误信息,便于调试和问题定位。
- 类型转换:
- 在返回结果前,根据目标类型进行类型转换(
Converters.convert
),确保返回值符合预期的类型。
- 在返回结果前,根据目标类型进行类型转换(
- 灵活性和扩展性:
- 通过
PropertyAccessor
和Hints
的使用,使得代码具备较高的灵活性和扩展性。新的访问器和提示可以很容易地添加和配置,以适应不同的需求和场景。
- 通过