OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 132 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 132 Rev 156
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
3
 * 
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 * 
5
 * 
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
9
 * language governing permissions and limitations under the License.
10
 * 
10
 * 
11
 * When distributing the software, include this License Header Notice in each file.
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
12
 */
13
 
13
 
14
 package org.openconcerto.sql.element;
14
 package org.openconcerto.sql.element;
15
 
15
 
16
import org.openconcerto.sql.Log;
16
import org.openconcerto.sql.Log;
17
import org.openconcerto.utils.i18n.Grammar;
17
import org.openconcerto.utils.i18n.Grammar;
18
import org.openconcerto.utils.i18n.NounClass;
18
import org.openconcerto.utils.i18n.NounClass;
19
import org.openconcerto.utils.i18n.Phrase;
19
import org.openconcerto.utils.i18n.Phrase;
20
import org.openconcerto.utils.i18n.VariantKey;
20
import org.openconcerto.utils.i18n.VariantKey;
21
import org.openconcerto.xml.JDOM2Utils;
21
import org.openconcerto.xml.JDOM2Utils;
22
 
22
 
23
import java.io.IOException;
23
import java.io.IOException;
24
import java.io.InputStream;
24
import java.io.InputStream;
25
import java.util.AbstractMap.SimpleEntry;
25
import java.util.AbstractMap.SimpleEntry;
-
 
26
import java.util.Collections;
-
 
27
import java.util.HashMap;
26
import java.util.Locale;
28
import java.util.Locale;
-
 
29
import java.util.Map;
27
import java.util.Map.Entry;
30
import java.util.Map.Entry;
-
 
31
import java.util.Set;
-
 
32
import java.util.logging.Level;
28
import java.util.regex.Pattern;
33
import java.util.regex.Pattern;
29
 
34
 
30
import org.jdom2.Document;
35
import org.jdom2.Document;
31
import org.jdom2.Element;
36
import org.jdom2.Element;
32
import org.jdom2.JDOMException;
37
import org.jdom2.JDOMException;
33
import org.jdom2.input.SAXBuilder;
38
import org.jdom2.input.SAXBuilder;
34
 
39
 
35
import net.jcip.annotations.ThreadSafe;
40
import net.jcip.annotations.ThreadSafe;
36
 
41
 
37
/**
42
/**
38
 * Parses XML to create phrases.
43
 * Parses XML to create phrases.
39
 * 
44
 * 
40
 * <pre>
45
 * <pre>
41
 *     &lt;element refid="elementCode">
46
 *     &lt;element refid="elementCode">
42
 *         &lt;name base="elemName" nounClass="masculine">
47
 *         &lt;name base="elemName" nounClass="masculine">
43
 *             &lt;variant refids="singular,plural" value="elemNameBothSingularAndPlural" />
48
 *             &lt;variant refids="singular,plural" value="elemNameBothSingularAndPlural" />
44
 *             &lt;variant idPattern="(singular|plural)" value="elemNameBothSingularAndPlural" />
49
 *             &lt;variant idPattern="(singular|plural)" value="elemNameBothSingularAndPlural" />
45
 *         &lt;/name>
50
 *         &lt;/name>
46
 *     &lt;/element>
51
 *     &lt;/element>
47
 * </pre>
52
 * </pre>
48
 * 
53
 * 
49
 * @author Sylvain
54
 * @author Sylvain
50
 * 
55
 * 
51
 */
56
 */
52
@ThreadSafe
57
@ThreadSafe
53
public class SQLElementNamesFromXML extends SQLElementNamesMap.ByCode {
58
public class SQLElementNamesFromXML {
54
 
59
 
55
    static public final Pattern SPLIT_PATTERN = Pattern.compile("\\s*,\\s*");
60
    static public final Pattern SPLIT_PATTERN = Pattern.compile("\\s*,\\s*");
-
 
61
    static private final Set<Object> SHORT_VARIANTS = Collections.singleton(Grammar.PLURAL);
-
 
62
 
-
 
63
    private static final String ELEMENT_ELEM_NAME = "element";
-
 
64
    private static final String NAME_ID_ATTR = "refid";
-
 
65
    private static final String VARIANT_ATTR = "variant";
-
 
66
    private static final String VARIANT_REFIDS_ATTR = "refids";
-
 
67
    private static final String VARIANT_VALUE_ATTR = "value";
-
 
68
    private static final String NAME_PLURAL_ATTR = "namePlural";
-
 
69
 
-
 
70
    static private final String getNounClassAttrName(final boolean shortForm) {
-
 
71
        return shortForm ? "nameClass" : "nounClass";
-
 
72
    }
-
 
73
 
-
 
74
    // <element nameClass="masculine" name="contact fournisseur">
-
 
75
    // <name nounClass="masculine" base="droit utilisateur">
-
 
76
    static final private void setNounClassAndBase(final Element elem, final Phrase phrase, final boolean shortForm) {
-
 
77
        elem.setAttribute(getNounClassAttrName(shortForm), phrase.getNounClass().getName());
-
 
78
        elem.setAttribute(shortForm ? "name" : "base", phrase.getBase());
-
 
79
    }
-
 
80
 
-
 
81
    private final Locale locale;
56
 
82
 
57
    public SQLElementNamesFromXML(Locale locale) {
83
    public SQLElementNamesFromXML(Locale locale) {
58
        super(locale);
84
        this.locale = locale;
59
    }
85
    }
60
 
86
 
-
 
87
    public final Locale getLocale() {
-
 
88
        return this.locale;
-
 
89
    }
-
 
90
 
61
    public final void load(final InputStream ins) throws JDOMException, IOException {
91
    public final Map<String, Phrase> load(final InputStream ins) throws JDOMException, IOException {
62
        final Grammar gr = Grammar.getInstance(getLocale());
-
 
63
        final Document doc = new SAXBuilder().build(ins);
92
        final Document doc = new SAXBuilder().build(ins);
-
 
93
        return load(doc.getRootElement());
-
 
94
    }
-
 
95
 
-
 
96
    public final Map<String, Phrase> load(final Element root) throws IOException {
-
 
97
        final Grammar gr = Grammar.getInstance(getLocale());
-
 
98
        final Map<String, Phrase> res = new HashMap<>();
64
        for (final Element elem : doc.getRootElement().getChildren("element"))
99
        for (final Element elem : root.getChildren(ELEMENT_ELEM_NAME)) {
-
 
100
            final Entry<String, Phrase> e = this.createPhrase(gr, elem);
65
            this.load(gr, elem);
101
            if (e != null)
-
 
102
                res.put(e.getKey(), e.getValue());
-
 
103
        }
-
 
104
        return res;
66
    }
105
    }
67
 
106
 
68
    public final Entry<String, Phrase> createPhrase(final Element elem) throws IOException {
107
    public final Entry<String, Phrase> createPhrase(final Element elem) throws IOException {
69
        return this.createPhrase(Grammar.getInstance(getLocale()), elem);
108
        return this.createPhrase(Grammar.getInstance(getLocale()), elem);
70
    }
109
    }
71
 
110
 
72
    private Entry<String, Phrase> createPhrase(final Grammar gr, final Element elem) throws IOException {
111
    private Entry<String, Phrase> createPhrase(final Grammar gr, final Element elem) throws IOException {
73
        final String refid = elem.getAttributeValue("refid");
112
        final String refid = elem.getAttributeValue(NAME_ID_ATTR);
74
        if (refid == null)
113
        if (refid == null)
75
            throw new IOException("No refid attribute");
114
            throw new IOException("No refid attribute");
76
 
115
 
77
        final Element nameElem = elem.getChild("name");
116
        final Element nameElem = elem.getChild("name");
78
        final boolean hasChild = nameElem != null;
117
        final boolean hasChild = nameElem != null;
79
        final String nameAttr = elem.getAttributeValue("name");
118
        final String nameAttr = elem.getAttributeValue("name");
80
        if (!hasChild && nameAttr == null) {
119
        if (!hasChild && nameAttr == null) {
-
 
120
            // perhaps elem is just used to change item names
81
            Log.get().warning("No name for code : " + refid);
121
            Log.get().log(Level.FINER, "No name for code : {0}", refid);
82
            return null;
122
            return null;
83
        }
123
        }
84
        if (hasChild && nameAttr != null) {
124
        if (hasChild && nameAttr != null) {
85
            Log.get().warning("Ignoring attribute : " + nameAttr);
125
            Log.get().warning("Ignoring attribute : " + nameAttr);
86
        }
126
        }
87
 
127
 
88
        final String base = hasChild ? nameElem.getAttributeValue("base") : nameAttr;
128
        final String base = hasChild ? nameElem.getAttributeValue("base") : nameAttr;
89
        if (base == null)
129
        if (base == null)
90
            throw new IOException("No base for the name of " + refid);
130
            throw new IOException("No base for the name of " + refid);
91
        final String nounClassName = hasChild ? nameElem.getAttributeValue("nounClass") : elem.getAttributeValue("nameClass");
131
        final String nounClassName = (hasChild ? nameElem : elem).getAttributeValue(getNounClassAttrName(!hasChild));
92
        final NounClass nounClass = nounClassName == null ? null : gr.getNounClass(nounClassName);
132
        final NounClass nounClass = nounClassName == null ? null : gr.getNounClass(nounClassName);
93
 
133
 
94
        final Phrase res = new Phrase(gr, base, nounClass);
134
        final Phrase res = new Phrase(gr, base, nounClass);
95
        if (!hasChild) {
135
        if (!hasChild) {
96
            // most languages have at most 2 grammatical number
136
            // most languages have at most 2 grammatical number
97
            final String plural = elem.getAttributeValue("namePlural");
137
            final String plural = elem.getAttributeValue(NAME_PLURAL_ATTR);
98
            if (plural != null)
138
            if (plural != null)
99
                res.putVariant(Grammar.PLURAL, plural);
139
                res.putVariant(Grammar.PLURAL, plural);
100
        } else {
140
        } else {
101
            for (final Element variantElem : nameElem.getChildren("variant")) {
141
            for (final Element variantElem : nameElem.getChildren(VARIANT_ATTR)) {
102
                final String value = variantElem.getAttributeValue("value");
142
                final String value = variantElem.getAttributeValue(VARIANT_VALUE_ATTR);
103
                if (value == null) {
143
                if (value == null) {
104
                    warning(refid, variantElem, "No value");
144
                    warning(refid, variantElem, "No value");
105
                    continue;
145
                    continue;
106
                }
146
                }
107
                final String variantIDs = variantElem.getAttributeValue("refids");
147
                final String variantIDs = variantElem.getAttributeValue(VARIANT_REFIDS_ATTR);
108
                final String variantPattern = variantElem.getAttributeValue("idPattern");
148
                final String variantPattern = variantElem.getAttributeValue("idPattern");
109
                if (variantIDs == null && variantPattern == null) {
149
                if (variantIDs == null && variantPattern == null) {
110
                    warning(refid, variantElem, "No ID");
150
                    warning(refid, variantElem, "No ID");
111
                } else if (variantIDs != null) {
151
                } else if (variantIDs != null) {
112
                    if (variantPattern != null) {
152
                    if (variantPattern != null) {
113
                        warning(refid, variantElem, "Ignorig pattern " + variantPattern);
153
                        warning(refid, variantElem, "Ignorig pattern " + variantPattern);
114
                    }
154
                    }
115
                    for (final String variantID : SPLIT_PATTERN.split(variantIDs)) {
155
                    for (final String variantID : SPLIT_PATTERN.split(variantIDs)) {
116
                        final VariantKey variantKey = gr.getVariantKey(variantID);
156
                        final VariantKey variantKey = gr.getVariantKey(variantID);
117
                        if (variantKey == null) {
157
                        if (variantKey == null) {
118
                            warning(refid, variantElem, "Ignorig " + variantID);
158
                            warning(refid, variantElem, "Ignorig " + variantID);
119
                        } else {
159
                        } else {
120
                            res.putVariant(variantKey, value);
160
                            res.putVariant(variantKey, value);
121
                        }
161
                        }
122
                    }
162
                    }
123
                } else {
163
                } else {
124
                    assert variantIDs == null && variantPattern != null;
164
                    assert variantIDs == null && variantPattern != null;
125
                    final Pattern p = Pattern.compile(variantPattern);
165
                    final Pattern p = Pattern.compile(variantPattern);
126
                    for (final VariantKey vk : gr.getVariantKeys()) {
166
                    for (final VariantKey vk : gr.getVariantKeys()) {
127
                        if (p.matcher(vk.getID()).matches()) {
167
                        if (p.matcher(vk.getID()).matches()) {
128
                            res.putVariant(vk, value);
168
                            res.putVariant(vk, value);
129
                        }
169
                        }
130
                    }
170
                    }
131
                }
171
                }
132
            }
172
            }
133
        }
173
        }
134
        return new SimpleEntry<String, Phrase>(refid, res);
174
        return new SimpleEntry<String, Phrase>(refid, res);
135
    }
175
    }
136
 
176
 
137
    private void load(final Grammar gr, final Element elem) throws IOException {
-
 
138
        final Entry<String, Phrase> entry = this.createPhrase(gr, elem);
-
 
139
        if (entry != null)
-
 
140
            this.put(entry.getKey(), entry.getValue());
-
 
141
    }
-
 
142
 
-
 
143
    private void warning(final String refid, final Element variantElem, final String msg) {
177
    private void warning(final String refid, final Element variantElem, final String msg) {
144
        Log.get().warning(msg + " for variant of " + refid + " : " + JDOM2Utils.output(variantElem));
178
        Log.get().warning(msg + " for variant of " + refid + " : " + JDOM2Utils.output(variantElem));
145
    }
179
    }
-
 
180
 
-
 
181
    public final Element createElement(final String refID, final Phrase phrase) {
-
 
182
        final Element elem = new Element(ELEMENT_ELEM_NAME);
-
 
183
        elem.setAttribute(NAME_ID_ATTR, refID);
-
 
184
        final Set<VariantKey> explicitVariants = phrase.getExplicitVariants();
-
 
185
        final boolean shortForm = SHORT_VARIANTS.containsAll(explicitVariants);
-
 
186
        final Element nameElem;
-
 
187
        if (shortForm) {
-
 
188
            nameElem = elem;
-
 
189
        } else {
-
 
190
            nameElem = new Element("name");
-
 
191
            elem.addContent(nameElem);
-
 
192
        }
-
 
193
        setNounClassAndBase(nameElem, phrase, shortForm);
-
 
194
        if (!shortForm) {
-
 
195
            // <variant refids="plural" value="droits utilisateurs"
-
 
196
            for (final VariantKey explicitVariant : explicitVariants) {
-
 
197
                final Element variantElem = new Element(VARIANT_ATTR);
-
 
198
                variantElem.setAttribute(VARIANT_REFIDS_ATTR, explicitVariant.getID());
-
 
199
                variantElem.setAttribute(VARIANT_VALUE_ATTR, phrase.getVariant(explicitVariant));
-
 
200
                nameElem.addContent(variantElem);
-
 
201
            }
-
 
202
        } else if (explicitVariants.contains(Grammar.PLURAL)) {
-
 
203
            elem.setAttribute(NAME_PLURAL_ATTR, phrase.getVariant(Grammar.PLURAL));
-
 
204
        }
-
 
205
        return elem;
-
 
206
    }
-
 
207
 
146
}
208
}