1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.search.backend.indexer.internal;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.stream.StreamSupport;
29
30 import org.apache.lucene.search.BooleanClause;
31 import org.apache.lucene.search.BooleanQuery;
32 import org.apache.lucene.search.Query;
33 import org.apache.maven.index.ArtifactAvailability;
34 import org.apache.maven.index.ArtifactInfo;
35 import org.apache.maven.index.GroupedSearchRequest;
36 import org.apache.maven.index.GroupedSearchResponse;
37 import org.apache.maven.index.Indexer;
38 import org.apache.maven.index.IteratorSearchRequest;
39 import org.apache.maven.index.IteratorSearchResponse;
40 import org.apache.maven.index.SearchType;
41 import org.apache.maven.index.context.IndexingContext;
42 import org.apache.maven.index.expr.SourcedSearchExpression;
43 import org.apache.maven.index.search.grouping.GAGrouping;
44 import org.apache.maven.search.MAVEN;
45 import org.apache.maven.search.Record;
46 import org.apache.maven.search.SearchRequest;
47 import org.apache.maven.search.backend.indexer.IndexerCoreSearchBackend;
48 import org.apache.maven.search.backend.indexer.IndexerCoreSearchResponse;
49 import org.apache.maven.search.request.Field;
50 import org.apache.maven.search.request.FieldQuery;
51 import org.apache.maven.search.request.Paging;
52 import org.apache.maven.search.support.SearchBackendSupport;
53
54 import static java.util.Objects.requireNonNull;
55
56
57
58
59 public class IndexerCoreSearchBackendImpl extends SearchBackendSupport implements IndexerCoreSearchBackend {
60 private static final Map<Field, org.apache.maven.index.Field> FIELD_TRANSLATION;
61
62 static {
63 HashMap<Field, org.apache.maven.index.Field> map = new HashMap<>();
64 map.put(MAVEN.GROUP_ID, org.apache.maven.index.MAVEN.GROUP_ID);
65 map.put(MAVEN.ARTIFACT_ID, org.apache.maven.index.MAVEN.ARTIFACT_ID);
66 map.put(MAVEN.VERSION, org.apache.maven.index.MAVEN.VERSION);
67 map.put(MAVEN.CLASSIFIER, org.apache.maven.index.MAVEN.CLASSIFIER);
68 map.put(MAVEN.PACKAGING, org.apache.maven.index.MAVEN.PACKAGING);
69 map.put(MAVEN.CLASS_NAME, org.apache.maven.index.MAVEN.CLASSNAMES);
70 map.put(MAVEN.FQ_CLASS_NAME, org.apache.maven.index.MAVEN.CLASSNAMES);
71 map.put(MAVEN.SHA1, org.apache.maven.index.MAVEN.SHA1);
72 FIELD_TRANSLATION = Collections.unmodifiableMap(map);
73 }
74
75 private final Indexer indexer;
76
77 private final IndexingContext indexingContext;
78
79
80
81
82 public IndexerCoreSearchBackendImpl(Indexer indexer, IndexingContext indexingContext) {
83 super(indexingContext.getId(), indexingContext.getRepositoryId());
84 this.indexer = requireNonNull(indexer);
85 this.indexingContext = indexingContext;
86 }
87
88 @Override
89 public IndexingContext getIndexingContext() {
90 return indexingContext;
91 }
92
93 @Override
94 public IndexerCoreSearchResponse search(SearchRequest searchRequest) throws IOException {
95 Paging paging = searchRequest.getPaging();
96 int totalHitsCount;
97 List<ArtifactInfo> artifactInfos = new ArrayList<>(paging.getPageSize());
98 List<Record> page = new ArrayList<>(paging.getPageSize());
99
100
101 HashSet<Field> searchedFields = new HashSet<>();
102 Query query = toQuery(searchedFields, searchRequest.getQuery());
103 if (searchedFields.contains(MAVEN.SHA1)
104 || (searchedFields.contains(MAVEN.GROUP_ID) && searchedFields.contains(MAVEN.ARTIFACT_ID))) {
105 if (!searchedFields.contains(MAVEN.CLASSIFIER)) {
106 query = new BooleanQuery.Builder()
107 .add(new BooleanClause(query, BooleanClause.Occur.MUST))
108 .add(
109 indexer.constructQuery(
110 org.apache.maven.index.MAVEN.CLASSIFIER,
111 new SourcedSearchExpression(org.apache.maven.index.Field.NOT_PRESENT)),
112 BooleanClause.Occur.MUST_NOT)
113 .build();
114 }
115 IteratorSearchRequest iteratorSearchRequest =
116 new IteratorSearchRequest(query, Collections.singletonList(indexingContext));
117 iteratorSearchRequest.setCount(paging.getPageSize());
118 iteratorSearchRequest.setStart(paging.getPageSize() * paging.getPageOffset());
119
120 try (IteratorSearchResponse iteratorSearchResponse = indexer.searchIterator(iteratorSearchRequest)) {
121 totalHitsCount = iteratorSearchResponse.getTotalHitsCount();
122 StreamSupport.stream(iteratorSearchResponse.iterator().spliterator(), false)
123 .sorted(ArtifactInfo.VERSION_COMPARATOR)
124 .forEach(ai -> {
125 artifactInfos.add(ai);
126 page.add(convert(ai, null));
127 });
128 }
129 return new IndexerCoreSearchResponseImpl(searchRequest, totalHitsCount, page, query, artifactInfos);
130 } else {
131 GroupedSearchRequest groupedSearchRequest =
132 new GroupedSearchRequest(query, new GAGrouping(), indexingContext);
133
134 try (GroupedSearchResponse groupedSearchResponse = indexer.searchGrouped(groupedSearchRequest)) {
135 totalHitsCount = groupedSearchResponse.getResults().size();
136 groupedSearchResponse.getResults().values().stream()
137 .skip((long) paging.getPageSize() * paging.getPageOffset())
138 .limit(paging.getPageSize())
139 .forEach(aig -> {
140 ArtifactInfo ai = aig.getArtifactInfos().iterator().next();
141 artifactInfos.add(ai);
142 page.add(convert(ai, aig.getArtifactInfos().size()));
143 });
144 }
145 return new IndexerCoreSearchResponseImpl(searchRequest, totalHitsCount, page, query, artifactInfos);
146 }
147 }
148
149 private Query toQuery(HashSet<Field> searchedFields, org.apache.maven.search.request.Query query) {
150 if (query instanceof org.apache.maven.search.request.BooleanQuery.And) {
151 org.apache.maven.search.request.BooleanQuery bq = (org.apache.maven.search.request.BooleanQuery) query;
152 return new BooleanQuery.Builder()
153 .add(new BooleanClause(toQuery(searchedFields, bq.getLeft()), BooleanClause.Occur.MUST))
154 .add(new BooleanClause(toQuery(searchedFields, bq.getRight()), BooleanClause.Occur.MUST))
155 .build();
156 } else if (query instanceof FieldQuery) {
157 FieldQuery fq = (FieldQuery) query;
158 org.apache.maven.index.Field icFieldName = FIELD_TRANSLATION.get(fq.getField());
159 if (icFieldName != null) {
160 searchedFields.add(fq.getField());
161 if (fq.getValue().endsWith("*")) {
162 return indexer.constructQuery(icFieldName, fq.getValue(), SearchType.SCORED);
163 } else {
164 return indexer.constructQuery(icFieldName, fq.getValue(), SearchType.EXACT);
165 }
166 } else {
167 throw new IllegalArgumentException("Unsupported Indexer field: " + fq.getField());
168 }
169 }
170 return new BooleanQuery.Builder()
171 .add(new BooleanClause(
172 indexer.constructQuery(
173 org.apache.maven.index.MAVEN.GROUP_ID, query.getValue(), SearchType.SCORED),
174 BooleanClause.Occur.SHOULD))
175 .add(new BooleanClause(
176 indexer.constructQuery(
177 org.apache.maven.index.MAVEN.ARTIFACT_ID, query.getValue(), SearchType.SCORED),
178 BooleanClause.Occur.SHOULD))
179 .add(new BooleanClause(
180 indexer.constructQuery(org.apache.maven.index.MAVEN.NAME, query.getValue(), SearchType.SCORED),
181 BooleanClause.Occur.SHOULD))
182 .build();
183 }
184
185 private Record convert(ArtifactInfo ai, Integer versionCount) {
186 HashMap<Field, Object> result = new HashMap<>();
187
188 mayPut(result, MAVEN.GROUP_ID, ai.getGroupId());
189 mayPut(result, MAVEN.ARTIFACT_ID, ai.getArtifactId());
190 mayPut(result, MAVEN.VERSION, ai.getVersion());
191 mayPut(result, MAVEN.PACKAGING, ai.getPackaging());
192 mayPut(result, MAVEN.CLASSIFIER, ai.getClassifier());
193 mayPut(result, MAVEN.FILE_EXTENSION, ai.getFileExtension());
194
195 mayPut(result, MAVEN.VERSION_COUNT, versionCount);
196
197 mayPut(result, MAVEN.HAS_SOURCE, ai.getSourcesExists() == ArtifactAvailability.PRESENT);
198 mayPut(result, MAVEN.HAS_JAVADOC, ai.getJavadocExists() == ArtifactAvailability.PRESENT);
199 mayPut(result, MAVEN.HAS_GPG_SIGNATURE, ai.getSignatureExists() == ArtifactAvailability.PRESENT);
200
201 return new Record(getBackendId(), getRepositoryId(), ai.getUinfo(), ai.getLastModified(), result);
202 }
203
204 private static void mayPut(Map<Field, Object> result, Field fieldName, Object value) {
205 if (value != null) {
206 result.put(fieldName, value);
207 }
208 }
209 }