21
21
*/
22
22
package com .github ._1c_syntax .bsl .mdo .support ;
23
23
24
+ import com .github ._1c_syntax .utils .GenericInterner ;
24
25
import com .github ._1c_syntax .utils .StringInterner ;
26
+ import edu .umd .cs .findbugs .annotations .Nullable ;
27
+ import lombok .EqualsAndHashCode ;
28
+ import lombok .Getter ;
25
29
import lombok .NonNull ;
26
30
import lombok .Value ;
27
31
28
32
import java .util .Collections ;
29
- import java .util .HashMap ;
33
+ import java .util .HashSet ;
30
34
import java .util .List ;
31
35
import java .util .Map ;
36
+ import java .util .Set ;
32
37
33
38
/**
34
39
* Используется для хранения текстовой строки на разных языках
35
40
*/
36
41
@ Value
37
- public class MultiLanguageString {
42
+ @ EqualsAndHashCode
43
+ public class MultiLanguageString implements Comparable <MultiLanguageString > {
38
44
39
45
/**
40
46
* Ссылка на пустой элемент
41
47
*/
42
48
public static final MultiLanguageString EMPTY = new MultiLanguageString (Collections .emptyMap ());
43
-
44
- private static final StringInterner stringInterner = new StringInterner ();
49
+ private static final GenericInterner <MultiLanguageString > interner = new GenericInterner <>();
45
50
46
51
/**
47
52
* Содержимое описания для каждого языка
48
53
*/
49
- Map < String , String > content ;
54
+ Set < Entry > content ;
50
55
51
- public MultiLanguageString (Map <String , String > source ) {
52
- Map < String , String > newContent = new HashMap <>();
56
+ private MultiLanguageString (@ NonNull Map <String , String > source ) {
57
+ Set < Entry > newContent = new HashSet <>();
53
58
source .forEach (
54
- (langKey , text ) -> newContent .put (stringInterner .intern (langKey ), text ));
55
- content = newContent ;
59
+ (langKey , text ) -> newContent .add (Entry .create (langKey , text )));
60
+ content = Collections .unmodifiableSet (newContent );
61
+ }
62
+
63
+ private MultiLanguageString (@ NonNull String langKey , @ NonNull String value ) {
64
+ this (Set .of (Entry .create (langKey , value )));
65
+ }
66
+
67
+ private MultiLanguageString (@ NonNull MultiLanguageString first , @ NonNull MultiLanguageString second ) {
68
+ var fullContent = new HashSet <>(first .getContent ());
69
+ fullContent .addAll (second .getContent ());
70
+ content = Collections .unmodifiableSet (fullContent );
56
71
}
57
72
58
- public MultiLanguageString (@ NonNull MultiLanguageString first , @ NonNull MultiLanguageString second ) {
59
- var fullContent = new HashMap <>(first .getContent ());
60
- putContent (fullContent , second );
61
- content = fullContent ;
73
+ private MultiLanguageString (Set <Entry > content ) {
74
+ this .content = Collections .unmodifiableSet (content );
62
75
}
63
76
64
77
/**
@@ -69,26 +82,42 @@ public MultiLanguageString(@NonNull MultiLanguageString first, @NonNull MultiLan
69
82
* @param strings Список мультиязычных строк
70
83
* @return Объединенное значение
71
84
*/
72
- public static MultiLanguageString of (@ NonNull List <MultiLanguageString > strings ) {
85
+ public static MultiLanguageString create (@ NonNull List <MultiLanguageString > strings ) {
73
86
if (strings .isEmpty ()) {
74
87
return EMPTY ;
75
88
} else if (strings .size () == 1 ) {
76
89
return strings .get (0 );
77
90
} else {
78
- Map < String , String > content = new HashMap <>();
79
- strings .forEach (string -> putContent ( content , string ));
80
- return new MultiLanguageString (content );
91
+ Set < Entry > content = new HashSet <>();
92
+ strings .forEach (string -> content . addAll ( string . getContent () ));
93
+ return new MultiLanguageString (content ). intern () ;
81
94
}
82
95
}
83
96
97
+ public static MultiLanguageString create (@ NonNull Set <Entry > langContent ) {
98
+ return new MultiLanguageString (langContent ).intern ();
99
+ }
100
+
101
+ public static MultiLanguageString create (@ NonNull MultiLanguageString first , @ NonNull MultiLanguageString second ) {
102
+ return new MultiLanguageString (first , second ).intern ();
103
+ }
104
+
105
+ public static MultiLanguageString create (@ NonNull String langKey , @ NonNull String value ) {
106
+ return new MultiLanguageString (langKey , value ).intern ();
107
+ }
108
+
84
109
/**
85
110
* Возвращает содержимое для указанного языка
86
111
*
87
112
* @param lang Требуемый язык
88
113
* @return Содержимое для указанного языка
89
114
*/
90
115
public @ NonNull String get (@ NonNull String lang ) {
91
- return content .getOrDefault (lang , "" );
116
+ return content .stream ()
117
+ .filter (entry -> entry .getLangKey ().equals (lang ))
118
+ .map (Entry ::getValue )
119
+ .findFirst ()
120
+ .orElse ("" );
92
121
}
93
122
94
123
/**
@@ -100,7 +129,7 @@ public static MultiLanguageString of(@NonNull List<MultiLanguageString> strings)
100
129
if (content .isEmpty ()) {
101
130
return "" ;
102
131
}
103
- return content .entrySet (). iterator ().next ().getValue ();
132
+ return content .iterator ().next ().getValue ();
104
133
}
105
134
106
135
/**
@@ -112,8 +141,83 @@ public boolean isEmpty() {
112
141
return this == EMPTY ;
113
142
}
114
143
115
- private static void putContent (Map <String , String > destination , MultiLanguageString source ) {
116
- source .getContent ().forEach (
117
- (langKey , text ) -> destination .put (stringInterner .intern (langKey ), text ));
144
+ @ Override
145
+ public int compareTo (@ Nullable MultiLanguageString multiLanguageString ) {
146
+ if (multiLanguageString == null ) {
147
+ return 1 ;
148
+ }
149
+
150
+ if (this .equals (multiLanguageString )) {
151
+ return 0 ;
152
+ }
153
+
154
+ int compareResult = content .size () - multiLanguageString .content .size ();
155
+ if (compareResult != 0 ) {
156
+ return compareResult ;
157
+ }
158
+
159
+ // количество равно, но списки не равны
160
+ // попробуем оставить в списках только уникальные элементы
161
+ // если останется больше 0 (а странно будет, если не так), то сравним по первому элементу
162
+ var left = new HashSet <>(content );
163
+ var right = new HashSet <>(multiLanguageString .content );
164
+ left .removeAll (right );
165
+ right .removeAll (left );
166
+ if (left .isEmpty () && right .isEmpty ()) {
167
+ return 0 ; // хз как это получилось
168
+ } else if (left .isEmpty ()) {
169
+ return -1 ;
170
+ } else if (right .isEmpty ()) {
171
+ return 1 ;
172
+ } else {
173
+ var leftOne = left .iterator ().next ();
174
+ var rightOne = right .iterator ().next ();
175
+ return leftOne .compareTo (rightOne );
176
+ }
177
+ }
178
+
179
+ private MultiLanguageString intern () {
180
+ return interner .intern (this );
181
+ }
182
+
183
+ @ EqualsAndHashCode
184
+ public static class Entry implements Comparable <Entry > {
185
+ @ Getter
186
+ private final String langKey ;
187
+ @ Getter
188
+ private final String value ;
189
+ private static final StringInterner stringInterner = new StringInterner ();
190
+ private static final GenericInterner <Entry > interner = new GenericInterner <>();
191
+
192
+ private Entry (String langKey , String value ) {
193
+ this .langKey = stringInterner .intern (langKey );
194
+ this .value = value ;
195
+ }
196
+
197
+ public static Entry create (String langKey , String value ) {
198
+ return new Entry (langKey , value ).intern ();
199
+ }
200
+
201
+ @ Override
202
+ public int compareTo (@ Nullable Entry entry ) {
203
+ if (entry == null ) {
204
+ return 1 ;
205
+ }
206
+
207
+ if (this .equals (entry )) {
208
+ return 0 ;
209
+ }
210
+
211
+ int compareResult = langKey .compareTo (entry .langKey );
212
+ if (compareResult != 0 ) {
213
+ return compareResult ;
214
+ }
215
+
216
+ return value .compareTo (entry .value );
217
+ }
218
+
219
+ private Entry intern () {
220
+ return interner .intern (this );
221
+ }
118
222
}
119
223
}
0 commit comments