Skip to content

Commit

Permalink
properties: add properties prefix as filter/append
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alonbl authored and cowtowncoder committed May 31, 2019
1 parent a027e13 commit 42a93e9
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ public void setSchema(FormatSchema schema) {
_basePath.append(indent);
_jpropContext = JPropWriteContext.createRootContext(_indentLength);
}
if (_schema.prefix() != null) {
_basePath.append(_schema.prefix());
}
}
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ public class JavaPropsSchema
*/
protected String _header = "";

/**
* Optional prefix to strip and append to key names.
* Useful when subset of properties need to be processed.
*/
protected String _prefix;

/*
/**********************************************************************
/* Construction, factories, mutant factories
Expand All @@ -157,6 +163,7 @@ public JavaPropsSchema(JavaPropsSchema base) {
_keyValueSeparator = base._keyValueSeparator;
_lineEnding = base._lineEnding;
_header = base._header;
_prefix = base._prefix;
}

/**
Expand Down Expand Up @@ -287,6 +294,15 @@ public JavaPropsSchema withLineEnding(String v) {
return s;
}

public JavaPropsSchema withPrefix(String v) {
if (_equals(v, _prefix)) {
return this;
}
JavaPropsSchema s = new JavaPropsSchema(this);
s._prefix = v;
return s;
}

/**
* Mutant factory for constructing schema instance where specified
* header section (piece of text written out right before actual
Expand Down Expand Up @@ -371,6 +387,10 @@ public String pathSeparator() {
return _pathSeparator;
}

public String prefix() {
return _prefix;
}

public boolean writeIndexUsingMarkers() {
return _writeIndexUsingMarkers && (_indexMarker != null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public static JPropPathSplitter create(JavaPropsSchema schema)
}
return new FullSplitter(sep, schema.parseSimpleIndexes(),
indexMarker,
pathOnlySplitter(schema));
pathOnlySplitter(schema),
schema.prefix());
}

private static JPropPathSplitter pathOnlySplitter(JavaPropsSchema schema)
Expand Down Expand Up @@ -262,14 +263,21 @@ public static class FullSplitter extends JPropPathSplitter
// small but important optimization for cases where index markers are absent
protected final int _indexFirstChar;
protected final JPropPathSplitter _simpleSplitter;

protected final String _prefix;

public FullSplitter(String pathSeparator, boolean useSimpleIndex,
Markers indexMarker, JPropPathSplitter fallbackSplitter)
Markers indexMarker, JPropPathSplitter fallbackSplitter,
String prefix)
{
super(useSimpleIndex);
String startMarker = indexMarker.getStart();
_indexFirstChar = startMarker.charAt(0);
_simpleSplitter = fallbackSplitter;
if (prefix == null || prefix.isEmpty()) {
_prefix = null;
} else {
_prefix = prefix + pathSeparator;
}
_indexMatch = Pattern.compile(String.format
("(%s)|(%s(\\d{1,9})%s)",
Pattern.quote(pathSeparator),
Expand All @@ -281,6 +289,13 @@ public FullSplitter(String pathSeparator, boolean useSimpleIndex,
public JPropNode splitAndAdd(JPropNode parent,
String key, String value)
{
if (_prefix != null) {
if (!key.startsWith(_prefix)) {
return null;
}
key = key.substring(_prefix.length());
}

if (key.indexOf(_indexFirstChar) < 0) { // no index start marker
return _simpleSplitter.splitAndAdd(parent, key, value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.fasterxml.jackson.dataformat.javaprop;

import java.util.Map;
import java.util.Properties;

import com.fasterxml.jackson.databind.ObjectMapper;

public class PrefixTest extends ModuleTestBase
{
private final JavaPropsMapper MAPPER = mapperForProps();

public void testPrefixParsing() throws Exception {
final String INPUT = "org.o1.firstName=Bob\n"
+"org.o1.lastName=Palmer\n"
+"org.o2.firstName=Alice\n"
+"org.o2.lastName=Black\n"
+"junk=AQIDBA==\n";
FiveMinuteUser result1 = _mapFrom(MAPPER.reader(JavaPropsSchema.emptySchema().withPrefix("org.o1")), INPUT, FiveMinuteUser.class, false);
assertEquals("Bob", result1.firstName);
assertEquals("Palmer", result1.lastName);
FiveMinuteUser result2 = _mapFrom(MAPPER.reader(JavaPropsSchema.emptySchema().withPrefix("org.o2")), INPUT, FiveMinuteUser.class, false);
assertEquals("Alice", result2.firstName);
assertEquals("Black", result2.lastName);
}

public void testPrefixGeneration() throws Exception
{
FiveMinuteUser input = new FiveMinuteUser("Bob", "Palmer", true, Gender.MALE,
new byte[] { 1, 2, 3, 4 });
String output = MAPPER.writer(JavaPropsSchema.emptySchema().withPrefix("org.o1")).writeValueAsString(input);
assertEquals("org.o1.firstName=Bob\n"
+"org.o1.lastName=Palmer\n"
+"org.o1.gender=MALE\n"
+"org.o1.verified=true\n"
+"org.o1.userImage=AQIDBA==\n"
,output);
Properties props = MAPPER.writeValueAsProperties(input, JavaPropsSchema.emptySchema().withPrefix("org.o1"));
assertEquals(5, props.size());
assertEquals("true", props.get("org.o1.verified"));
assertEquals("MALE", props.get("org.o1.gender"));
}
}

0 comments on commit 42a93e9

Please sign in to comment.