geoserver GetPropertyValue run

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);
}

这个方法用于在给定对象中查找并获取指定属性的值,并根据目标类型进行转换。

主要逻辑如下:

  1. 初始化
    • 初始化上次使用的属性访问器 accessor
    • 初始化默认属性值 valuefalse,并标记访问是否成功 successfalse
  2. 尝试使用上次的属性访问器
    • 如果上次的属性访问器存在且可以处理当前对象和目标类型,则尝试使用它获取属性值。
    • 如果获取成功,则标记 successtrue
  3. 尝试其他访问器
    • 如果上次的访问器无法处理,检查是否存在命名空间支持且没有提示信息,如果是则创建提示信息。
    • 查找所有可以处理当前对象和目标类型的属性访问器。
    • 遍历所有找到的访问器,尝试使用它们获取属性值。
    • 如果获取成功,则标记 successtrue 并退出循环。
    • 如果获取失败,则捕获异常并记录到异常列表。
  4. 处理失败情况
    • 如果所有访问器都失败且启用了宽松模式,则返回 null
    • 如果未启用宽松模式,则构造包含所有异常信息的 IllegalArgumentException 并抛出。
  5. 缓存成功的访问器
    • 缓存成功的访问器 accessor 以便下次使用。
  6. 返回结果
    • 根据目标类型 target 进行类型转换并返回结果。如果目标类型为空,则直接返回值。

这段代码体现了以下设计思想:

  1. 缓存机制
    • 通过缓存 lastAccessor 属性访问器,避免每次调用 evaluate 方法时都需要重新查找合适的访问器,从而提升性能。
  2. 责任链模式
    • 使用多个 PropertyAccessor 实现属性访问的责任链模式。如果一个访问器无法处理请求,则尝试下一个访问器,直到找到合适的为止。
  3. 宽松模式(Lenient Mode)
    • 提供宽松模式(lenient)的支持。如果所有访问器都失败且启用了宽松模式,则返回 null,而不是抛出异常。这在某些情况下可以提高系统的容错性。
  4. 异常处理
    • 在访问器失败时,捕获并记录异常,最后统一处理并抛出包含所有失败信息的异常。这种方式提供了详细的错误信息,便于调试和问题定位。
  5. 类型转换
    • 在返回结果前,根据目标类型进行类型转换(Converters.convert),确保返回值符合预期的类型。
  6. 灵活性和扩展性
    • 通过 PropertyAccessorHints 的使用,使得代码具备较高的灵活性和扩展性。新的访问器和提示可以很容易地添加和配置,以适应不同的需求和场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值