es之NamedXContentRegistry

1、概述

其作为ContentParser的注册器,用于统一管理 ContextParser。

2、NamedXContentRegistry

与NamedWriteableRegistry类似

其成员有

成员说明
Map<Class<?>, Map<String, Entry>> registry注册器
Map<Class<?>, Map<String, Entry>> compatibleRegistry兼容的注册器

2.1 NamedXContentRegistry.Entry

成员包含

成员说明
Class<?> categoryClass实体需要读取的类
ParseField name类型类内可以唯一标识的名称
ContextParser<Object, ?> parser内容解析器

2.2 构造函数

public NamedXContentRegistry(List<Entry> entries, List<Entry> compatibleEntries) {
        this.registry = unmodifiableMap(getRegistry(entries));
        this.compatibleRegistry = unmodifiableMap(getCompatibleRegistry(compatibleEntries));
    }

初始化registry和compatibleRegistry两个成员。

初始化registry是通过调用getRegistry实现初始化。

private  Map<Class<?>, Map<String, Entry>> getRegistry(List<Entry> entries){
        if (entries.isEmpty()) {
            return emptyMap();
        }
        entries = new ArrayList<>(entries);
        entries.sort((e1, e2) -> e1.categoryClass.getName().compareTo(e2.categoryClass.getName()));

        Map<Class<?>, Map<String, Entry>> registry = new HashMap<>();
        Map<String, Entry> parsers = null;
        Class<?> currentCategory = null;
        for (Entry entry : entries) {
            if (currentCategory != entry.categoryClass) {
                if (currentCategory != null) {
                    // we've seen the last of this category, put it into the big map
                    registry.put(currentCategory, unmodifiableMap(parsers));
                }
                parsers = new HashMap<>();
                currentCategory = entry.categoryClass;
            }

            for (String name : entry.name.getAllNamesIncludedDeprecated()) {
                Object old = parsers.put(name, entry);
                if (old != null) {
                    throw new IllegalArgumentException("NamedXContent [" + currentCategory.getName() + "][" + entry.name + "]" +
                        " is already registered for [" + old.getClass().getName() + "]," +
                        " cannot register [" + entry.parser.getClass().getName() + "]");
                }
            }
        }
        // handle the last category
        registry.put(currentCategory, unmodifiableMap(parsers));
        return registry;
    }

与NamedWriteableRegistry的初始化相似。先根据Entry中的categoryClass的名称排序,然后依次放入registry中。

初始化compatibleRegistry是通过调用getCompatibleRegistry实现初始化。

private Map<Class<?>, Map<String, Entry>> getCompatibleRegistry(List<Entry> compatibleEntries) {
        Map<Class<?>, Map<String, Entry>> compatibleRegistry = new HashMap<>(registry);
        List<Entry> unseenEntries = new ArrayList<>();
        compatibleEntries.forEach(entry -> {
                Map<String, Entry> parsers = compatibleRegistry.get(entry.categoryClass);
                if (parsers == null) {
                    unseenEntries.add(entry);
                } else {
                    Map<String, Entry> parsersCopy = new HashMap<>(parsers);
                    for (String name : entry.name.getAllNamesIncludedDeprecated()) {
                        parsersCopy.put(name, entry); //override the parser for the given name
                    }
                    compatibleRegistry.put(entry.categoryClass, parsersCopy);
                }
            }
        );
        compatibleRegistry.putAll(getRegistry(unseenEntries));
        return compatibleRegistry;
    }

其会将compatibleEntries中不在registry中的也添加上,同时会将过时的name与Entry的对应关系添加

2.3 parseNamedObject

解析内容。根据categoryClass和name从registry或者compatibleRegistry得到对应的ContextParser,然后使用parsere来解析context。

public <T, C> T parseNamedObject(Class<T> categoryClass, String name, XContentParser parser, C context) throws IOException {

        Map<String, Entry> parsers = parser.getRestApiVersion() == RestApiVersion.minimumSupported() ?
            compatibleRegistry.get(categoryClass) : registry.get(categoryClass);
        if (parsers == null) {
            if (registry.isEmpty()) {
                // The "empty" registry will never work so we throw a better exception as a hint.
                throw new XContentParseException("named objects are not supported for this parser");
            }
            throw new XContentParseException("unknown named object category [" + categoryClass.getName() + "]");
        }
        Entry entry = parsers.get(name);
        if (entry == null) {
            throw new NamedObjectNotFoundException(parser.getTokenLocation(), "unknown field [" + name + "]", parsers.keySet());
        }
        if (false == entry.name.match(name, parser.getDeprecationHandler())) {
            /* Note that this shouldn't happen because we already looked up the entry using the names but we need to call `match` anyway
             * because it is responsible for logging deprecation warnings. */
            throw new XContentParseException(parser.getTokenLocation(),
                    "unable to parse " + categoryClass.getSimpleName() + " with name [" + name + "]: parser didn't match");
        }
        return categoryClass.cast(entry.parser.parse(parser, context));
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值