Skip to content

Commit 25fc5c2

Browse files
Example stable plugin (elastic#90805)
Add example stable plugin. This example plugin creates and tests some trivial analysis components. Once we implement settings for stable plugins, we will be able to make the example plugin a little bit more interesting. Co-authored-by: William Brafford <[email protected]>
1 parent e1bdf70 commit 25fc5c2

File tree

18 files changed

+457
-0
lines changed

18 files changed

+457
-0
lines changed

docs/changelog/90805.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 90805
2+
summary: Example stable plugin
3+
area: Infra/Plugins
4+
type: enhancement
5+
issues: []

plugins/examples/settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ gradle.rootProject {
2323
props.load(is)
2424
elasticsearchVersion = "${props.get('elasticsearch')}-SNAPSHOT"
2525
log4jVersion = props.get('log4j')
26+
luceneVersion = props.get('lucene')
2627
}
2728
}
2829
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
apply plugin: 'elasticsearch.stable-esplugin'
2+
apply plugin: 'elasticsearch.yaml-rest-test'
3+
4+
esplugin {
5+
name 'stable-analysis-plugin'
6+
description 'An example analysis plugin using stable plugin api'
7+
}
8+
//TODO write module-info
9+
10+
dependencies {
11+
12+
//TODO transitive dependency off and plugin-api dependency?
13+
compileOnly "org.elasticsearch:elasticsearch-plugin-api:${elasticsearchVersion}"
14+
compileOnly "org.elasticsearch:elasticsearch-plugin-analysis-api:${elasticsearchVersion}"
15+
compileOnly "org.apache.lucene:lucene-analysis-common:${luceneVersion}"
16+
17+
//TODO for testing this also have to be declared
18+
testImplementation "org.elasticsearch:elasticsearch-plugin-api:${elasticsearchVersion}"
19+
testImplementation "org.elasticsearch:elasticsearch-plugin-analysis-api:${elasticsearchVersion}"
20+
testImplementation "org.apache.lucene:lucene-analysis-common:${luceneVersion}"
21+
22+
testImplementation ('junit:junit:4.13.2'){
23+
exclude group: 'org.hamcrest'
24+
}
25+
testImplementation 'org.hamcrest:hamcrest:2.2'
26+
27+
}
28+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.example.analysis;
10+
11+
import org.apache.lucene.analysis.Analyzer;
12+
import org.elasticsearch.example.analysis.lucene.ReplaceHash;
13+
import org.elasticsearch.example.analysis.lucene.Skip1TokenFilter;
14+
import org.elasticsearch.example.analysis.lucene.UnderscoreTokenizer;
15+
import org.elasticsearch.plugin.api.NamedComponent;
16+
17+
@NamedComponent(name = "example_analyzer_factory")
18+
public class ExampleAnalyzerFactory implements org.elasticsearch.plugin.analysis.api.AnalyzerFactory {
19+
20+
@Override
21+
//TODO guide lucene
22+
public Analyzer create() {
23+
return new CustomAnalyzer();
24+
}
25+
26+
static class CustomAnalyzer extends Analyzer {
27+
28+
@Override
29+
protected TokenStreamComponents createComponents(String fieldName) {
30+
var tokenizer = new UnderscoreTokenizer();
31+
var tokenFilter = new Skip1TokenFilter(tokenizer);
32+
return new TokenStreamComponents(r -> tokenizer.setReader(new ReplaceHash(r)), tokenFilter);
33+
}
34+
}
35+
}
36+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.example.analysis;
10+
11+
import org.apache.lucene.util.SuppressForbidden;
12+
import org.elasticsearch.example.analysis.lucene.ReplaceHash;
13+
import org.elasticsearch.plugin.analysis.api.CharFilterFactory;
14+
import org.elasticsearch.plugin.api.NamedComponent;
15+
16+
import java.io.Reader;
17+
18+
@NamedComponent(name = "example_char_filter")
19+
public class ExampleCharFilterFactory implements CharFilterFactory {
20+
@Override
21+
public Reader create(Reader reader) {
22+
return new ReplaceHash(reader);
23+
}
24+
}
25+
26+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.example.analysis;
10+
11+
import org.apache.lucene.analysis.TokenStream;
12+
import org.elasticsearch.example.analysis.lucene.AppendTokenFilter;
13+
import org.elasticsearch.example.analysis.lucene.Skip1TokenFilter;
14+
import org.elasticsearch.plugin.analysis.api.AnalysisMode;
15+
import org.elasticsearch.plugin.api.NamedComponent;
16+
17+
@NamedComponent(name = "example_token_filter_factory")
18+
public class ExampleTokenFilterFactory implements org.elasticsearch.plugin.analysis.api.TokenFilterFactory {
19+
@Override
20+
public TokenStream create(TokenStream tokenStream) {
21+
return new Skip1TokenFilter(tokenStream);
22+
}
23+
24+
@Override
25+
public TokenStream normalize(TokenStream tokenStream) {
26+
return new AppendTokenFilter(tokenStream, "1");
27+
}
28+
29+
@Override
30+
public AnalysisMode getAnalysisMode() {
31+
return org.elasticsearch.plugin.analysis.api.TokenFilterFactory.super.getAnalysisMode();
32+
}
33+
34+
}
35+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.example.analysis;
10+
11+
import org.apache.lucene.analysis.Tokenizer;
12+
import org.elasticsearch.example.analysis.lucene.UnderscoreTokenizer;
13+
import org.elasticsearch.plugin.analysis.api.TokenizerFactory;
14+
import org.elasticsearch.plugin.api.NamedComponent;
15+
16+
@NamedComponent(name = "example_tokenizer_factory")
17+
public class ExampleTokenizerFactory implements TokenizerFactory {
18+
@Override
19+
public Tokenizer create() {
20+
return new UnderscoreTokenizer();
21+
}
22+
23+
}
24+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.example.analysis.lucene;
10+
11+
import org.apache.lucene.analysis.TokenFilter;
12+
import org.apache.lucene.analysis.TokenStream;
13+
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
14+
import org.elasticsearch.plugin.analysis.api.TokenFilterFactory;
15+
16+
import java.io.IOException;
17+
18+
public class AppendTokenFilter extends TokenFilter {
19+
public static TokenFilterFactory factoryForSuffix(String suffix) {
20+
return new TokenFilterFactory() {
21+
@Override
22+
public String name() {
23+
return suffix;
24+
}
25+
26+
@Override
27+
public TokenStream create(TokenStream tokenStream) {
28+
return new AppendTokenFilter(tokenStream, suffix);
29+
}
30+
};
31+
}
32+
33+
private final CharTermAttribute term = addAttribute(CharTermAttribute.class);
34+
private final char[] appendMe;
35+
36+
public AppendTokenFilter(TokenStream input, String appendMe) {
37+
super(input);
38+
this.appendMe = appendMe.toCharArray();
39+
}
40+
41+
@Override
42+
public boolean incrementToken() throws IOException {
43+
if (false == input.incrementToken()) {
44+
return false;
45+
}
46+
term.resizeBuffer(term.length() + appendMe.length);
47+
System.arraycopy(appendMe, 0, term.buffer(), term.length(), appendMe.length);
48+
term.setLength(term.length() + appendMe.length);
49+
return true;
50+
}
51+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.example.analysis.lucene;
10+
11+
import org.apache.lucene.analysis.charfilter.MappingCharFilter;
12+
import org.apache.lucene.analysis.charfilter.NormalizeCharMap;
13+
14+
import java.io.Reader;
15+
16+
public class ReplaceHash extends MappingCharFilter {
17+
18+
public ReplaceHash(Reader in) {
19+
super(charMap(), in);
20+
}
21+
22+
private static NormalizeCharMap charMap() {
23+
NormalizeCharMap.Builder builder = new NormalizeCharMap.Builder();
24+
builder.add("#", "3");
25+
return builder.build();
26+
}
27+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.example.analysis.lucene;
10+
11+
import org.apache.lucene.analysis.FilteringTokenFilter;
12+
import org.apache.lucene.analysis.TokenStream;
13+
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
14+
15+
import java.io.IOException;
16+
17+
public class Skip1TokenFilter extends FilteringTokenFilter {
18+
19+
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
20+
21+
public Skip1TokenFilter(TokenStream in) {
22+
super(in);
23+
}
24+
25+
@Override
26+
protected boolean accept() throws IOException {
27+
return termAtt.buffer()[0] != '1';
28+
}
29+
}

0 commit comments

Comments
 (0)