Skip to contentMethod: set(String)
1: package cz.cvut.kbss.jopa.model;
2:
3: import java.io.Serializable;
4: import java.util.*;
5:
6: /**
7: * Represents a string with translations to (possibly) multiple languages.
8: * <p>
9: * This allows an application to naturally work in an internationalized environment leveraging the <a
10: * href="https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string">language-tagged strings</a> of the Semantic
11: * Web.
12: * <p>
13: * Instances of this class basically represent all available translations of the string, allowing to read (and write)
14: * particular versions by specifying the corresponding language tag. A special case supported by this class are <a
15: * href="https://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal">simple literals</a> (language-less strings with
16: * type {@code xsd:string}), for which the language tag is {@code null}.
17: * <p>
18: * Note that this class is not thread-safe.
19: */
20: public class MultilingualString implements Serializable {
21:
22: private final Map<String, String> value;
23:
24: public MultilingualString() {
25: this.value = new HashMap<>(8);
26: }
27:
28: /**
29: * Creates a new {@code MultilingualString} instance based on the specified value.
30: * <p>
31: * Convenience constructor for simple initialization with existing data.
32: *
33: * @param value Map of language to translation values
34: */
35: public MultilingualString(Map<String, String> value) {
36: this.value = new HashMap<>(Objects.requireNonNull(value));
37: }
38:
39: /**
40: * Sets value in the specified language.
41: * <p>
42: * This overrides any previous value in the specified language, if it existed.
43: *
44: * @param language Language to use with the specified value. Passing {@code null} has the same effect as {@link
45: * #set(String)}
46: * @param value String value in the specified language
47: * @return This instance
48: * @see #set(String)
49: */
50: public MultilingualString set(String language, String value) {
51: Objects.requireNonNull(value);
52: this.value.put(language, value);
53: return this;
54: }
55:
56: /**
57: * Sets value without language.
58: * <p>
59: * That is, the specified value will be stored as a simple literal (type xsd:string).
60: *
61: * @param value Value to set
62: * @return This instance
63: * @see #set(String, String)
64: */
65: public MultilingualString set(String value) {
66: Objects.requireNonNull(value);
67: this.value.put(null, value);
68: return this;
69: }
70:
71: /**
72: * Gets value for the specified language.
73: * <p>
74: * If no language is specified, either the simple literal value is returned (if present), or any other existing
75: * value is returned. However, note that, in case of missing simple literal, repeated calls may return values in
76: * different languages. If there are no translations, {@code null} is returned.
77: *
78: * @param language Requested language (language tag). Can be {@code null}
79: * @return Value of this string for the specified language (or {@code null} if not available)
80: */
81: public String get(String language) {
82: return language != null ? value.get(language) : get();
83: }
84:
85: /**
86: * Gets the value of a simple literal represented by this instance.
87: * <p>
88: * If this instances does not represent a simple literal, any other existing value is returned. However, note that
89: * in that case repeated calls may return values in different languages.
90: * <p>
91: * If this object is empty (i.e., neither simple literal nor any translations are available), {@code null} is
92: * returned.
93: *
94: * @return Value of simple literal represented by this string
95: */
96: public String get() {
97: return value.getOrDefault(null, value.isEmpty() ? null : value.get(value.keySet().iterator().next()));
98: }
99:
100: /**
101: * Checks whether this string contains value in the specified language.
102: * <p>
103: * If no language is specified (argument is {@code null}), this method will return {@code true} if there is value
104: * without language tag (simple literal) or in any other language.
105: *
106: * @param language Requested language (language tag)
107: * @return {@code true} if this string exists in the specified language
108: */
109: public boolean contains(String language) {
110: return value.containsKey(language) || (language == null && !value.isEmpty());
111: }
112:
113: /**
114: * Checks whether this string contains a simple literal value.
115: * <p>
116: * That is, whether this instance contains a value without a language tag.
117: *
118: * @return {@code true} if and only if this string exists as a simple literal
119: */
120: public boolean containsSimple() {
121: return value.containsKey(null);
122: }
123:
124: /**
125: * Checks whether this instance does not contain any language representations (including a simple literal).
126: *
127: * @return {@code true} if no translations exist in this instance
128: */
129: public boolean isEmpty() {
130: return value.isEmpty();
131: }
132:
133: /**
134: * Removes translation in the specified language.
135: * <p>
136: * Passing in {@code null} will remove the simple literal contained in this instance.
137: *
138: * @param language Language for which translation should be removed
139: */
140: public void remove(String language) {
141: value.remove(language);
142: }
143:
144: /**
145: * Gets the set of languages for which translations exist in the instance.
146: * <p>
147: * Note that the result may contain {@code null}, indicating a simple literal.
148: *
149: * @return Set of languages available in this multilingual string
150: */
151: public Set<String> getLanguages() {
152: return Collections.unmodifiableSet(value.keySet());
153: }
154:
155: /**
156: * Gets the translations contained in this instance as an unmodifiable map backed by this instance.
157: * <p>
158: * Convenience method for accessing all values at once.
159: *
160: * @return Map of language to translation values
161: */
162: public Map<String, String> getValue() {
163: return Collections.unmodifiableMap(value);
164: }
165:
166: @Override
167: public boolean equals(Object o) {
168: if (this == o) {
169: return true;
170: }
171: if (!(o instanceof MultilingualString)) {
172: return false;
173: }
174: MultilingualString that = (MultilingualString) o;
175: return value.equals(that.value);
176: }
177:
178: @Override
179: public int hashCode() {
180: return Objects.hash(value);
181: }
182:
183: @Override
184: public String toString() {
185: return value.toString();
186: }
187:
188: /**
189: * Creates a new instance of {@link MultilingualString} and sets the specified value in the specified language.
190: * <p>
191: * Convenience method for creating strings with one (initial) translation.
192: *
193: * @param value String value
194: * @param language Language of the value (language tag)
195: * @return New instance of {@code MultiLangString}
196: */
197: public static MultilingualString create(String value, String language) {
198: final MultilingualString instance = new MultilingualString();
199: instance.set(language, value);
200: return instance;
201: }
202: }