summaryrefslogtreecommitdiffstats
path: root/docproc/src/main/java/com/yahoo/docproc/proxy/SchemaMap.java
blob: b27c8b725f2065c3b715eb8613bd56efab7001ab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.docproc.proxy;

import com.yahoo.collections.Pair;
import com.yahoo.config.subscription.ConfigSubscriber;
import com.yahoo.config.docproc.SchemamappingConfig;
import com.yahoo.config.docproc.SchemamappingConfig.Fieldmapping;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;

/**
 * Can be used to map field names from input doc into names used in a docproc that was
 * written with generic field names.
 * @author vegardh
 *
 */
public class SchemaMap implements ConfigSubscriber.SingleSubscriber<SchemamappingConfig> {
    /**
     * Map key. Doctype can be null, not the others.
     * @author vegardh
     *
     */
    class SchemaMapKey {

        private final String chain;
        private final String docproc;
        private final String doctype;
        private final String inDocument;

        public SchemaMapKey(String chain, String docproc, String doctype, String from) {
            this.chain = chain;
            this.docproc = docproc;
            this.doctype = doctype;
            this.inDocument = from;
            if (chain==null) throw new IllegalArgumentException("'chain' cannot be null in schema map.");
            if (docproc==null) throw new IllegalArgumentException("'docproc' cannot be null in schema map.");
            if (from==null) throw new IllegalArgumentException("'from' cannot be null in schema map.");
        }
        public String getChain() {
            return chain;
        }
        public String getDocproc() {
            return docproc;
        }
        public String getDoctype() {
            return doctype;
        }
        public String getInDocument() {
            return inDocument;
        }

        private boolean equalType(SchemaMapKey other) {
            if (doctype==null) return other.getDoctype()==null;
            return doctype.equals(other.getDoctype());
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof SchemaMapKey)) return false;
            SchemaMapKey other = (SchemaMapKey)obj;
            return other.getChain().equals(chain) &&
              other.getDocproc().equals(docproc) &&
              other.getInDocument().equals(inDocument) &&
              equalType(other);
        }
        @Override
        public int hashCode() {
            return chain.hashCode()+docproc.hashCode()+(doctype!=null?doctype.hashCode():0)+inDocument.hashCode();
        }

    }

    // (key->inProcessor),...
    private final ConfigSubscriber subscriber;
    private Map<SchemaMapKey, String> fields = new HashMap<>();

    void addMapping(String chain, String docproc, String doctype, String inDocument, String inProcessor) {
        fields.put(new SchemaMapKey(chain, docproc, doctype, inDocument), inProcessor);
    }

    /**
     * New map from the docproc cluster's config id
     * @param configid can be null. Will not get anything from config in that case.
     */
    public SchemaMap(String configid) {
        subscriber = new ConfigSubscriber();
        if (configid!=null) {
            subscriber.subscribe(this, SchemamappingConfig.class, configid);
        }
    }

    public SchemaMap() {
        this(null);
    }

    @Override
    public void configure(SchemamappingConfig config) {
        if (config == null) {
            return;
        }
        fields.clear();
        for (Fieldmapping m: config.fieldmapping()) {
            SchemaMapKey key = new SchemaMapKey(m.chain(), m.docproc(), ("".equals(m.doctype())?null:m.doctype()), m.indocument());
            fields.put(key, m.inprocessor());
        }
    }

    /**
     * The map for a given chain,docproc:
     * "Reverses" the direction, this is the mapping a docproc should do when a
     * doc comes in. The doctype is null if not given in map.
     *
     * @return (doctype,inProcessor)→inDocument
     */
    public Map<Pair<String,String>, String> chainMap(String chain, String docproc) {
        Map<Pair<String, String>, String> ret = new HashMap<>();
        for (Entry<SchemaMapKey, String> e : fields.entrySet()) {
            SchemaMapKey key = e.getKey();
            if (key.getChain().equals(chain) && key.getDocproc().equals(docproc)) {
                // Reverse direction here
                ret.put(new Pair<>(key.getDoctype(),e.getValue()), key.getInDocument());
            }
        }
        return ret;
    }


}