Skip to content

Commit 42a93e9

Browse files
alonblcowtowncoder
authored andcommitted
properties: add properties prefix as filter/append
Properties may contain multiple objects based on prefix, for example: a.b.c.name = a.b.c.id = x.y.z.name = x.y.z.color = To read these formats a prefix should be used as a filter when reading and as append when generating. A new optional JavaPropsSchema::prefix() and JavaPropsSchema::withPrefix() are added to control the behavior. As each path component is an object, use of ObjectReader::withRootName has a different meaning so schema property was used. PR #100
1 parent a027e13 commit 42a93e9

File tree

4 files changed

+83
-3
lines changed

4 files changed

+83
-3
lines changed

properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/JavaPropsGenerator.java

+3
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ public void setSchema(FormatSchema schema) {
143143
_basePath.append(indent);
144144
_jpropContext = JPropWriteContext.createRootContext(_indentLength);
145145
}
146+
if (_schema.prefix() != null) {
147+
_basePath.append(_schema.prefix());
148+
}
146149
}
147150
return;
148151
}

properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/JavaPropsSchema.java

+20
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ public class JavaPropsSchema
139139
*/
140140
protected String _header = "";
141141

142+
/**
143+
* Optional prefix to strip and append to key names.
144+
* Useful when subset of properties need to be processed.
145+
*/
146+
protected String _prefix;
147+
142148
/*
143149
/**********************************************************************
144150
/* Construction, factories, mutant factories
@@ -157,6 +163,7 @@ public JavaPropsSchema(JavaPropsSchema base) {
157163
_keyValueSeparator = base._keyValueSeparator;
158164
_lineEnding = base._lineEnding;
159165
_header = base._header;
166+
_prefix = base._prefix;
160167
}
161168

162169
/**
@@ -287,6 +294,15 @@ public JavaPropsSchema withLineEnding(String v) {
287294
return s;
288295
}
289296

297+
public JavaPropsSchema withPrefix(String v) {
298+
if (_equals(v, _prefix)) {
299+
return this;
300+
}
301+
JavaPropsSchema s = new JavaPropsSchema(this);
302+
s._prefix = v;
303+
return s;
304+
}
305+
290306
/**
291307
* Mutant factory for constructing schema instance where specified
292308
* header section (piece of text written out right before actual
@@ -371,6 +387,10 @@ public String pathSeparator() {
371387
return _pathSeparator;
372388
}
373389

390+
public String prefix() {
391+
return _prefix;
392+
}
393+
374394
public boolean writeIndexUsingMarkers() {
375395
return _writeIndexUsingMarkers && (_indexMarker != null);
376396
}

properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/util/JPropPathSplitter.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public static JPropPathSplitter create(JavaPropsSchema schema)
3535
}
3636
return new FullSplitter(sep, schema.parseSimpleIndexes(),
3737
indexMarker,
38-
pathOnlySplitter(schema));
38+
pathOnlySplitter(schema),
39+
schema.prefix());
3940
}
4041

4142
private static JPropPathSplitter pathOnlySplitter(JavaPropsSchema schema)
@@ -262,14 +263,21 @@ public static class FullSplitter extends JPropPathSplitter
262263
// small but important optimization for cases where index markers are absent
263264
protected final int _indexFirstChar;
264265
protected final JPropPathSplitter _simpleSplitter;
265-
266+
protected final String _prefix;
267+
266268
public FullSplitter(String pathSeparator, boolean useSimpleIndex,
267-
Markers indexMarker, JPropPathSplitter fallbackSplitter)
269+
Markers indexMarker, JPropPathSplitter fallbackSplitter,
270+
String prefix)
268271
{
269272
super(useSimpleIndex);
270273
String startMarker = indexMarker.getStart();
271274
_indexFirstChar = startMarker.charAt(0);
272275
_simpleSplitter = fallbackSplitter;
276+
if (prefix == null || prefix.isEmpty()) {
277+
_prefix = null;
278+
} else {
279+
_prefix = prefix + pathSeparator;
280+
}
273281
_indexMatch = Pattern.compile(String.format
274282
("(%s)|(%s(\\d{1,9})%s)",
275283
Pattern.quote(pathSeparator),
@@ -281,6 +289,13 @@ public FullSplitter(String pathSeparator, boolean useSimpleIndex,
281289
public JPropNode splitAndAdd(JPropNode parent,
282290
String key, String value)
283291
{
292+
if (_prefix != null) {
293+
if (!key.startsWith(_prefix)) {
294+
return null;
295+
}
296+
key = key.substring(_prefix.length());
297+
}
298+
284299
if (key.indexOf(_indexFirstChar) < 0) { // no index start marker
285300
return _simpleSplitter.splitAndAdd(parent, key, value);
286301
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.fasterxml.jackson.dataformat.javaprop;
2+
3+
import java.util.Map;
4+
import java.util.Properties;
5+
6+
import com.fasterxml.jackson.databind.ObjectMapper;
7+
8+
public class PrefixTest extends ModuleTestBase
9+
{
10+
private final JavaPropsMapper MAPPER = mapperForProps();
11+
12+
public void testPrefixParsing() throws Exception {
13+
final String INPUT = "org.o1.firstName=Bob\n"
14+
+"org.o1.lastName=Palmer\n"
15+
+"org.o2.firstName=Alice\n"
16+
+"org.o2.lastName=Black\n"
17+
+"junk=AQIDBA==\n";
18+
FiveMinuteUser result1 = _mapFrom(MAPPER.reader(JavaPropsSchema.emptySchema().withPrefix("org.o1")), INPUT, FiveMinuteUser.class, false);
19+
assertEquals("Bob", result1.firstName);
20+
assertEquals("Palmer", result1.lastName);
21+
FiveMinuteUser result2 = _mapFrom(MAPPER.reader(JavaPropsSchema.emptySchema().withPrefix("org.o2")), INPUT, FiveMinuteUser.class, false);
22+
assertEquals("Alice", result2.firstName);
23+
assertEquals("Black", result2.lastName);
24+
}
25+
26+
public void testPrefixGeneration() throws Exception
27+
{
28+
FiveMinuteUser input = new FiveMinuteUser("Bob", "Palmer", true, Gender.MALE,
29+
new byte[] { 1, 2, 3, 4 });
30+
String output = MAPPER.writer(JavaPropsSchema.emptySchema().withPrefix("org.o1")).writeValueAsString(input);
31+
assertEquals("org.o1.firstName=Bob\n"
32+
+"org.o1.lastName=Palmer\n"
33+
+"org.o1.gender=MALE\n"
34+
+"org.o1.verified=true\n"
35+
+"org.o1.userImage=AQIDBA==\n"
36+
,output);
37+
Properties props = MAPPER.writeValueAsProperties(input, JavaPropsSchema.emptySchema().withPrefix("org.o1"));
38+
assertEquals(5, props.size());
39+
assertEquals("true", props.get("org.o1.verified"));
40+
assertEquals("MALE", props.get("org.o1.gender"));
41+
}
42+
}

0 commit comments

Comments
 (0)