Skip to content

Commit dac5fe1

Browse files
renatohdsmiley
andauthored
SOLR-17623: SimpleOrderedMap implements Map (#3048)
Also added NamedList.indexOf(name) convenience method. Does *not* adjust asShallowMap() yet. Coming soon. --------- Co-authored-by: David Smiley <[email protected]>
1 parent e81bc32 commit dac5fe1

File tree

5 files changed

+305
-16
lines changed

5 files changed

+305
-16
lines changed

solr/CHANGES.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ Improvements
162162
other v2 APIs. SolrJ now offers (experimental) SolrRequest implementations for all v2 configset APIs in
163163
`org.apache.solr.client.solrj.request.ConfigsetsApi`. (Jason Gerlowski)
164164

165-
Optimizations
165+
Optimizations
166166
---------------------
167167
* SOLR-17578: Remove ZkController internal core supplier, for slightly faster reconnection after Zookeeper session loss. (Pierre Salagnac)
168168

@@ -209,6 +209,8 @@ Other Changes
209209
* SOLR-17581: Introduce new test variant of waitForState(), that does not wait on live node changes when we're only
210210
interested in the collection state. (Pierre Salagnac)
211211

212+
* SOLR-17623: SimpleOrderedMap (a NamedList) now implements java.util.Map. (Renato Haeberli, David Smiley)
213+
212214
================== 9.8.0 ==================
213215
New Features
214216
---------------------

solr/core/src/java/org/apache/solr/handler/component/PivotFacetProcessor.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,14 @@ public SimpleOrderedMap<List<NamedList<Object>>> process(String[] pivots) throws
168168

169169
for (String refinements : refinementValuesByField) {
170170
pivotResponse.addAll(
171-
processSingle(
172-
pivotFields, refinements, statsFields, parsed, facetQueries, facetRanges));
171+
(Map<String, List<NamedList<Object>>>)
172+
processSingle(
173+
pivotFields, refinements, statsFields, parsed, facetQueries, facetRanges));
173174
}
174175
} else {
175176
pivotResponse.addAll(
176-
processSingle(pivotFields, null, statsFields, parsed, facetQueries, facetRanges));
177+
(Map<String, List<NamedList<Object>>>)
178+
processSingle(pivotFields, null, statsFields, parsed, facetQueries, facetRanges));
177179
}
178180
}
179181
return pivotResponse;

solr/solrj/src/java/org/apache/solr/common/util/NamedList.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,15 @@ public int indexOf(String name, int start) {
238238
return -1;
239239
}
240240

241+
/***
242+
* Scans the names of the list sequentially beginning at index 0 and returns the index of the first
243+
* pair with the specified name.
244+
* @see #indexOf(String, int)
245+
*/
246+
public int indexOf(String name) {
247+
return indexOf(name, 0);
248+
}
249+
241250
/**
242251
* Gets the value for the first instance of the specified name found.
243252
*
@@ -403,8 +412,12 @@ public Map<String, T> asShallowMap() {
403412
return asShallowMap(false);
404413
}
405414

415+
/**
416+
* @deprecated use {@link SimpleOrderedMap} instead of NamedList when a Map is required.
417+
*/
418+
@Deprecated
406419
public Map<String, T> asShallowMap(boolean allowDps) {
407-
return new Map<String, T>() {
420+
return new Map<>() {
408421
@Override
409422
public int size() {
410423
return NamedList.this.size();
@@ -799,7 +812,7 @@ public Collection<String> removeConfigArgs(final String name) throws SolrExcepti
799812
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, err + o.getClass());
800813
}
801814

802-
if (collection.size() > 0) {
815+
if (!collection.isEmpty()) {
803816
killAll(name);
804817
}
805818

@@ -845,7 +858,7 @@ public void forEachKey(Consumer<String> fun) {
845858
}
846859
}
847860

848-
public void forEach(BiConsumer<String, ? super T> action) {
861+
public void forEach(BiConsumer<? super String, ? super T> action) {
849862
int sz = size();
850863
for (int i = 0; i < sz; i++) {
851864
action.accept(getName(i), getVal(i));

solr/solrj/src/java/org/apache/solr/common/util/SimpleOrderedMap.java

Lines changed: 112 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@
1616
*/
1717
package org.apache.solr.common.util;
1818

19+
import java.util.AbstractMap;
20+
import java.util.AbstractSet;
1921
import java.util.ArrayList;
22+
import java.util.Collection;
23+
import java.util.Iterator;
2024
import java.util.List;
2125
import java.util.Map;
26+
import java.util.Set;
2227

2328
/**
2429
* <code>SimpleOrderedMap</code> is a {@link NamedList} where access by key is more important than
@@ -30,10 +35,12 @@
3035
* {"foo":10,"bar":20} and may choose to write a NamedList as ["foo",10,"bar",20]. An XML response
3136
* writer may choose to render both the same way.
3237
*
33-
* <p>This class does not provide efficient lookup by key, its main purpose is to hold data to be
34-
* serialized. It aims to minimize overhead and to be efficient at adding new elements.
38+
* <p>This class does not provide efficient lookup by key. The lookup performance is only O(N), and
39+
* not O(1) or O(Log N) as it is for the most common Map-implementations. Its main purpose is to
40+
* hold data to be serialized. It aims to minimize overhead and to be efficient at adding new
41+
* elements.
3542
*/
36-
public class SimpleOrderedMap<T> extends NamedList<T> {
43+
public class SimpleOrderedMap<T> extends NamedList<T> implements Map<String, T> {
3744

3845
private static final SimpleOrderedMap<Object> EMPTY = new SimpleOrderedMap<>(List.of());
3946

@@ -64,28 +71,124 @@ public SimpleOrderedMap(Map.Entry<String, T>[] nameValuePairs) {
6471
super(nameValuePairs);
6572
}
6673

74+
// TODO override asShallowMap in Solr 10
75+
6776
@Override
6877
public SimpleOrderedMap<T> clone() {
6978
ArrayList<Object> newList = new ArrayList<>(nvPairs.size());
7079
newList.addAll(nvPairs);
7180
return new SimpleOrderedMap<>(newList);
7281
}
7382

83+
@Override
84+
public boolean isEmpty() {
85+
return nvPairs.isEmpty();
86+
}
87+
88+
@Override
89+
public boolean containsKey(final Object key) {
90+
return this.indexOf((String) key) >= 0;
91+
}
92+
93+
@Override
94+
public boolean containsValue(final Object value) {
95+
return values().contains(value);
96+
}
97+
7498
/**
75-
* Returns a shared, empty, and immutable instance of SimpleOrderedMap.
99+
* {@inheritDoc}
100+
*
101+
* <p>Has linear lookup time O(N)
76102
*
77-
* @return Empty SimpleOrderedMap (immutable)
103+
* @see NamedList#get(String)
78104
*/
79-
public static SimpleOrderedMap<Object> of() {
80-
return EMPTY;
105+
@Override
106+
public T get(final Object key) {
107+
return super.get((String) key);
108+
}
109+
110+
@Override
111+
public T put(String key, T value) {
112+
int idx = indexOf(key);
113+
if (idx == -1) {
114+
add(key, value);
115+
return null;
116+
} else {
117+
T t = get(key);
118+
setVal(idx, value);
119+
return t;
120+
}
81121
}
82122

83123
/**
84-
* Returns an immutable instance of SimpleOrderedMap with a single key-value pair.
124+
* @see NamedList#remove(String)
125+
*/
126+
@Override
127+
public T remove(final Object key) {
128+
return super.remove((String) key);
129+
}
130+
131+
@Override
132+
public void putAll(final Map<? extends String, ? extends T> m) {
133+
if (isEmpty()) {
134+
m.forEach(this::add);
135+
} else {
136+
m.forEach(this::put);
137+
}
138+
}
139+
140+
@Override
141+
public Set<String> keySet() {
142+
return new InnerMap().keySet();
143+
}
144+
145+
@Override
146+
public Collection<T> values() {
147+
return new InnerMap().values();
148+
}
149+
150+
@Override
151+
public Set<Entry<String, T>> entrySet() {
152+
153+
return new AbstractSet<>() {
154+
@Override
155+
public Iterator<Entry<String, T>> iterator() {
156+
return SimpleOrderedMap.this.iterator();
157+
}
158+
159+
@Override
160+
public int size() {
161+
return SimpleOrderedMap.this.size();
162+
}
163+
};
164+
}
165+
166+
/**
167+
* Returns an immutable instance of {@link SimpleOrderedMap} with a single key-value pair.
85168
*
86-
* @return SimpleOrderedMap containing one key-value pair
169+
* @return {@link SimpleOrderedMap} containing one key-value pair
87170
*/
88171
public static <T> SimpleOrderedMap<T> of(String name, T val) {
89172
return new SimpleOrderedMap<>(List.of(name, val));
90173
}
174+
175+
/**
176+
* Returns a shared, empty, and immutable instance of {@link SimpleOrderedMap}.
177+
*
178+
* @return Empty {@link SimpleOrderedMap} (immutable)
179+
*/
180+
public static SimpleOrderedMap<Object> of() {
181+
return EMPTY;
182+
}
183+
184+
/**
185+
* {@link SimpleOrderedMap} extending {@link NamedList}, we are not able to extend {@link
186+
* AbstractMap}. With the help of InnerMap we can still use {@link AbstractMap} methods.
187+
*/
188+
private class InnerMap extends AbstractMap<String, T> {
189+
@Override
190+
public Set<Entry<String, T>> entrySet() {
191+
return SimpleOrderedMap.this.entrySet();
192+
}
193+
}
91194
}

0 commit comments

Comments
 (0)