Skip to content

Commit 90ce310

Browse files
committed
BUG: User-defined plugins not being serialized (Issue #155)
1 parent 3564d9f commit 90ce310

File tree

10 files changed

+142
-17
lines changed

10 files changed

+142
-17
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11

22
## Changes ##
33

4+
### 17.4.2
5+
- BUG: User-defined plugins not being serialized (Issue #155)
6+
47
### 17.4.1
58
- INT: Bump logback-classic to 1.5.27, google phonenumber to 9.0.23, gradle to 9.3.1
69
- INT: Cleaning.

examples/sampleplugin/src/main/java/sampleplugin/SamplePlugin.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ public static void main(final String[] args) throws IOException, FTAException {
4444
// Add our custom Java plugin for detecting colors
4545
addPlugin(analysis);
4646

47+
final TextAnalyzer hydratedEnglish = TextAnalyzer.deserialize(analysis.serialize());
4748
for (final String input : inputsEnglish)
48-
analysis.train(input);
49+
hydratedEnglish.train(input);
4950

50-
result = analysis.getResult();
51+
result = hydratedEnglish.getResult();
5152

5253
System.err.printf("Result: %s, Semantic Type: %s, Regular Expression: %s, Max: %s, Min: %s.%n", result.getType(), result.getSemanticType(), result.getRegExp(), result.getMaxValue(), result.getMinValue());
5354

@@ -66,10 +67,12 @@ public static void main(final String[] args) throws IOException, FTAException {
6667
// Add our custom Java plugin for detecting colors
6768
addPlugin(analysisFrench);
6869

70+
final TextAnalyzer hydratedFrench = TextAnalyzer.deserialize(analysisFrench.serialize());
71+
6972
for (final String input : inputsFrench)
70-
analysisFrench.train(input);
73+
hydratedFrench.train(input);
7174

72-
result = analysisFrench.getResult();
75+
result = hydratedFrench.getResult();
7376

7477
System.err.printf("Result: %s, Semantic Type: %s, Regular Expression: %s, Max: %s, Min: %s.%n", result.getType(), result.getSemanticType(), result.getRegExp(), result.getMaxValue(), result.getMinValue());
7578

@@ -91,21 +94,26 @@ public static void main(final String[] args) throws IOException, FTAException {
9194
analyzerAugmented.setLocale(Locale.forLanguageTag("en-IN"));
9295
addPlugins(analyzerAugmented);
9396

97+
TextAnalyzer hydratedAugmented = TextAnalyzer.deserialize(analyzerAugmented.serialize());
98+
9499
for (final String input : inputsRE)
95-
analyzerAugmented.train(input);
100+
hydratedAugmented.train(input);
96101

97-
result = analyzerAugmented.getResult();
102+
result = hydratedAugmented.getResult();
98103

99104
System.err.printf("Result: %s, Semantic Type: %s, Regular Expression: %s, Max: %s, Min: %s.%n", result.getType(), result.getSemanticType(), result.getRegExp(), result.getMaxValue(), result.getMinValue());
100105

101106
// Load our new plugins from a file and test the new List-based Semantic Type
102107
analyzerAugmented = new TextAnalyzer("Element");
103108
analyzerAugmented.setLocale(Locale.US);
104109
addPlugins(analyzerAugmented);
110+
111+
hydratedAugmented = TextAnalyzer.deserialize(analyzerAugmented.serialize());
112+
105113
for (final String input : inputList)
106-
analyzerAugmented.train(input);
114+
hydratedAugmented.train(input);
107115

108-
result = analyzerAugmented.getResult();
116+
result = hydratedAugmented.getResult();
109117

110118
System.err.printf("Result: %s, Semantic Type: %s, Regular Expression: %s, Max: %s, Min: %s.%n", result.getType(), result.getSemanticType(), result.getRegExp(), result.getMaxValue(), result.getMinValue());
111119
}

settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ includeBuild 'examples/core/speed'
4040
dependencyResolutionManagement {
4141
versionCatalogs {
4242
libs {
43-
version('fta', '17.4.1')
43+
version('fta', '17.4.2')
4444
version('jacoco', '0.8.12')
4545

4646
// https://mvnrepository.com/artifact/de.siegmar/fastcsv

types/src/main/java/com/cobber/fta/Content.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import java.util.Arrays;
1919

20+
import com.fasterxml.jackson.annotation.JsonIgnore;
21+
2022
/**
2123
* Used to capture the members for a set of items - defined either inline or via a file or resource.
2224
*/
@@ -43,6 +45,7 @@ public Content(final String[] members) {
4345
this.members = members;
4446
}
4547

48+
@JsonIgnore
4649
public String getCacheKey() {
4750
if (INLINE.equals(type))
4851
return type + "---" + Arrays.hashCode(members);

types/src/main/java/com/cobber/fta/PluginDefinition.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.cobber.fta.core.FTAType;
3131
import com.cobber.fta.core.HeaderEntry;
3232
import com.cobber.fta.core.InternalErrorException;
33+
import com.fasterxml.jackson.annotation.JsonIgnore;
3334
import com.fasterxml.jackson.core.type.TypeReference;
3435
import com.fasterxml.jackson.databind.ObjectMapper;
3536

@@ -111,6 +112,7 @@ public PluginDefinition() {
111112
*
112113
* @return The order for this plugin.
113114
*/
115+
@JsonIgnore
114116
public int getOrder() {
115117
switch (precedence) {
116118
case BUILTIN:
@@ -276,6 +278,7 @@ public boolean isLocaleSupported(final Locale locale) throws FTAPluginException
276278
return getLocaleEntry(locale) != null;
277279
}
278280

281+
@JsonIgnore
279282
public String getLocaleDescription() {
280283
final StringBuilder ret = new StringBuilder();
281284
for (final PluginLocaleEntry validLocale : validLocales)

types/src/main/java/com/cobber/fta/PluginMatchEntry.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package com.cobber.fta;
1717

18+
import com.fasterxml.jackson.annotation.JsonProperty;
19+
1820
/*
1921
* Used by RegExp plugins. Each RegExp plugin has a set of PluginMatchEntries which have an ordered list of regular Expressions used to match against the Stream Data.
2022
* If the data matches one of the regular expressions then the regExpReturned is the answer returned to the user. For example for a SSN the "regExpsToMatch" is
@@ -27,7 +29,8 @@ public class PluginMatchEntry {
2729
/** RegExp plugins: the RegExp to be returned for this Semantic Type. */
2830
public String regExpReturned;
2931
/** Is the returned Regular Expression a complete representation of the Semantic Type. */
30-
public boolean isRegExpComplete;
32+
@JsonProperty("isRegExpComplete")
33+
public boolean regExpComplete;
3134

3235
PluginMatchEntry() {
3336
}
@@ -43,7 +46,7 @@ public class PluginMatchEntry {
4346
PluginMatchEntry(final PluginMatchEntry other) {
4447
this.regExpsToMatch = other.regExpsToMatch == null ? null : other.regExpsToMatch.clone();
4548
this.regExpReturned = other.regExpReturned;
46-
this.isRegExpComplete = other.isRegExpComplete;
49+
this.regExpComplete = other.regExpComplete;
4750
}
4851

4952
public String[] getRegExpsToMatch() {
@@ -56,7 +59,7 @@ public String[] getRegExpsToMatch() {
5659
}
5760

5861
public boolean isRegExpComplete() {
59-
return isRegExpComplete;
62+
return regExpComplete;
6063
}
6164

6265
public String getRegExpReturned() {

types/src/main/java/com/cobber/fta/TextAnalyzer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3775,7 +3775,7 @@ public String serialize() throws FTAPluginException, FTAUnsupportedLocaleExcepti
37753775
if (facts.getMatchTypeInfo() == null)
37763776
determineType();
37773777

3778-
final TextAnalyzerWrapper wrapper = new TextAnalyzerWrapper(analysisConfig, context, facts.calculateFacts());
3778+
final TextAnalyzerWrapper wrapper = new TextAnalyzerWrapper(analysisConfig, context, getPlugins().getUserDefinedPlugins(), facts.calculateFacts());
37793779

37803780
// We are serializing the analyzer (assume it will not be used again - so persist the samples)
37813781
if (traceConfig != null) {
@@ -3809,6 +3809,7 @@ public static TextAnalyzer deserialize(final String serialized) throws FTAMergeE
38093809

38103810
ret.facts = wrapper.facts;
38113811
ret.facts.setConfig(wrapper.analysisConfig);
3812+
ret.getPlugins().registerPluginListWithPrecedence(wrapper.userDefinedPlugins, wrapper.analysisConfig);
38123813
ret.initializeTrace();
38133814
ret.initialize();
38143815
ret.facts.hydrate();

types/src/main/java/com/cobber/fta/TextAnalyzerWrapper.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,24 @@
1515
*/
1616
package com.cobber.fta;
1717

18+
import java.util.List;
19+
1820
/**
1921
* Simple class used to aid serialization/de-serialization of a TextAnalyzer.
2022
*/
2123
class TextAnalyzerWrapper {
2224
public AnalysisConfig analysisConfig;
2325
public AnalyzerContext analyzerContext;
2426
public Facts facts;
27+
public List<PluginDefinition> userDefinedPlugins;
2528

2629
TextAnalyzerWrapper() {
2730
}
2831

29-
TextAnalyzerWrapper(final AnalysisConfig analysisConfig, final AnalyzerContext analyzerContext, final Facts facts) {
32+
TextAnalyzerWrapper(final AnalysisConfig analysisConfig, final AnalyzerContext analyzerContext, final List<PluginDefinition> userDefinedPlugins, final Facts facts) {
3033
this.analysisConfig = analysisConfig;
3134
this.analyzerContext = analyzerContext;
3235
this.facts = facts;
36+
this.userDefinedPlugins = userDefinedPlugins;
3337
}
3438
}

types/src/test/java/com/cobber/fta/TestIssues.java

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,99 @@ public void checkJSON() throws IOException, FTAException {
425425
final String[] inputsRE = {
426426
"2345:AQ", "5993:FG", "3898:WW", "5543:NH", "1992:WW", "4002:CS", "5982:KG", "1090:DD", "3030:XX", "1088:TR",
427427
"2547:DE", "6587:DS", "3215:QQ", "7745:VD", "4562:DD", "4582:SS", "2257:WE", "3578:HT", "4568:FB", "1587:SW",
428-
"4573:LF", "3574:SS", "8122:GK", "4523:EW", "7128:RT", "2548:RF", "6873:HH", "4837:NR", "2358:EE", "3731:HY"
428+
"4573:LF", "3574:SS", "8122:GK", "4523:EW", "7128:RT", "2548:RF", "6873:HH", "4837:NR", "2358:EE", "3731:HY",
429+
"0010:AA", "0011:DB", "0012:FT", "0013:KG", "0014:EM", "0015:RP", "0016:TA", "0017:AP", "0018:AA", "0019:AA",
430+
"0020:QA", "0021:UT", "0022:AA", "0023:AA", "0024:AQ", "0025:PA", "0026:AA", "0027:AA", "0028:AQ", "0029:AG",
431+
"0030:OA", "0031:AA", "0032:AA", "0033:AA", "0034:AA", "0035:NA", "0036:AI", "0037:AI", "0038:AA", "0039:FA",
432+
"0040:AH", "0041:AL", "0042:AL", "0043:EA", "0044:AA", "0045:WA", "0046:AA", "0047:QA", "0048:AS", "0049:XA",
433+
"0050:AS", "0051:ZA", "0052:AA", "0053:BS", "0054:JA", "0055:MA", "0056:AA", "0057:AV", "0058:AC", "0059:AA",
434+
"0060:AA", "0061:AC", "0062:AA", "0063:AD", "0064:AF", "0065:AA", "0066:AZ", "0067:AA", "0068:AK", "0069:AI",
435+
"0070:AA", "0071:AA", "0072:AA", "0073:AA", "0074:AF", "0075:AG", "0076:AY", "0077:AI", "0078:AU", "0079:AA"
429436
};
430437

438+
final String[] primaryColors = {
439+
"Red", "Green", "Green", "Red", "Red", "Blue", "Green", "Green", "Green", "Blue",
440+
"Green", "Blue", "Blue", "Red", "Red", "Blue", "Green", "Blue", "Blue", "Red",
441+
"Blue", "Green", "Blue"
442+
};
443+
444+
@Test(groups = { TestGroups.ALL, TestGroups.RANDOM })
445+
public void issue155_serialize_pre() throws FTAPluginException, FTAUnsupportedLocaleException, FTAMergeException {
446+
// Load our new plugins from a file and test the new Regular Expression Semantic Type
447+
TextAnalyzer analysis = new TextAnalyzer("ID");
448+
analysis.setLocale(Locale.forLanguageTag("en-US"));
449+
450+
// Register our sample list and regex plugins from a JSON definition file (before the built-in plugins have been registered)
451+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(TextAnalyzer.class.getResourceAsStream("/custom_id.json"), StandardCharsets.UTF_8))) {
452+
analysis.getPlugins().registerPlugins(reader, analysis.getConfig(), true);
453+
} catch (FTAPluginException e) {
454+
System.err.println("ERROR: Failed to register plugin: " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()));
455+
} catch (IOException e) {
456+
System.err.println("ERROR: Failed to register plugin: " + e.getMessage());
457+
}
458+
459+
TextAnalyzer hydrated = TextAnalyzer.deserialize(analysis.serialize());
460+
461+
for (final String input : inputsRE)
462+
hydrated.train(input);
463+
464+
TextAnalysisResult result = hydrated.getResult();
465+
466+
assertEquals(result.getSemanticType(), "CUSTOM.DIGIT_ALPHA_ID");
467+
}
468+
469+
@Test(groups = { TestGroups.ALL, TestGroups.RANDOM })
470+
public void issue155_serialize_color_pre() throws FTAPluginException, FTAUnsupportedLocaleException, FTAMergeException {
471+
// Load our new plugins from a file and test the new Regular Expression Semantic Type
472+
TextAnalyzer analysis = new TextAnalyzer("Color");
473+
analysis.setLocale(Locale.forLanguageTag("en-US"));
474+
475+
// Register our sample list and regex plugins from a JSON definition file (before the built-in plugins have been registered)
476+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(TextAnalyzer.class.getResourceAsStream("/custom_id.json"), StandardCharsets.UTF_8))) {
477+
analysis.getPlugins().registerPlugins(reader, analysis.getConfig(), true);
478+
} catch (FTAPluginException e) {
479+
System.err.println("ERROR: Failed to register plugin: " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()));
480+
} catch (IOException e) {
481+
System.err.println("ERROR: Failed to register plugin: " + e.getMessage());
482+
}
483+
484+
TextAnalyzer hydrated = TextAnalyzer.deserialize(analysis.serialize());
485+
486+
for (final String input : primaryColors)
487+
hydrated.train(input);
488+
489+
TextAnalysisResult result = hydrated.getResult();
490+
491+
assertEquals(result.getSemanticType(), "CUSTOM.PRIMARY_COLOR");
492+
}
493+
494+
@Test(groups = { TestGroups.ALL, TestGroups.RANDOM })
495+
public void issue155_serialize_color_post() throws FTAPluginException, FTAUnsupportedLocaleException, FTAMergeException {
496+
// Load our new plugins from a file and test the new Regular Expression Semantic Type
497+
TextAnalyzer analysis = new TextAnalyzer("Color");
498+
analysis.setLocale(Locale.forLanguageTag("en-US"));
499+
500+
// Register our sample list and regex plugins from a JSON definition file (before the built-in plugins have been registered)
501+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(TextAnalyzer.class.getResourceAsStream("/custom_id.json"), StandardCharsets.UTF_8))) {
502+
analysis.getPlugins().registerPlugins(reader, analysis.getConfig(), false);
503+
} catch (FTAPluginException e) {
504+
System.err.println("ERROR: Failed to register plugin: " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()));
505+
} catch (IOException e) {
506+
System.err.println("ERROR: Failed to register plugin: " + e.getMessage());
507+
}
508+
509+
TextAnalyzer hydrated = TextAnalyzer.deserialize(analysis.serialize());
510+
511+
for (final String input : primaryColors)
512+
hydrated.train(input);
513+
514+
TextAnalysisResult result = hydrated.getResult();
515+
516+
assertEquals(result.getSemanticType(), "COLOR.TEXT_EN");
517+
}
518+
431519
@Test(groups = { TestGroups.ALL, TestGroups.RANDOM })
432-
public void issue155() throws FTAPluginException, FTAUnsupportedLocaleException, FTAMergeException {
520+
public void issue155_merge() throws FTAPluginException, FTAUnsupportedLocaleException, FTAMergeException {
433521
// Load our new plugins from a file and test the new Regular Expression Semantic Type
434522
TextAnalyzer shardOne = new TextAnalyzer("ID");
435523
shardOne.setLocale(Locale.forLanguageTag("en-US"));
@@ -457,7 +545,7 @@ public void issue155() throws FTAPluginException, FTAUnsupportedLocaleException,
457545
shardTwo.train(input);
458546
}
459547

460-
TextAnalyzer merged = TextAnalyzer.merge(shardOne, shardTwo);
548+
TextAnalyzer merged = TextAnalyzer.merge(TextAnalyzer.deserialize(shardOne.serialize()), TextAnalyzer.deserialize(shardTwo.serialize()));
461549
TextAnalysisResult result = merged.getResult();
462550

463551
assertEquals(result.getSemanticType(), "CUSTOM.DIGIT_ALPHA_ID");

types/src/test/resources/custom_id.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,17 @@
1010
} ],
1111
"threshold": 95,
1212
"baseType": "STRING"
13+
},
14+
{
15+
"semanticType": "CUSTOM.PRIMARY_COLOR",
16+
"description": "Additive primary colors",
17+
"pluginType": "list",
18+
"validLocales": [ { "localeTag": "*", "headerRegExps": [ { "regExp": ".*(?i)(color|colour).*", "confidence": 90 } ] } ],
19+
"content": {
20+
"type": "inline",
21+
"members": [ "RED", "GREEN", "BLUE" ]
22+
},
23+
"backout": "[ \\p{IsAlphabetic}]+",
24+
"threshold": 99
1325
}
1426
]

0 commit comments

Comments
 (0)