Skip to content

Commit cd87943

Browse files
committed
Implemnting theme system
This fixes issue #8
1 parent 778d011 commit cd87943

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1116
-101
lines changed

src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java

+9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import pl.wavesoftware.utils.stringify.spi.BeanFactory;
2020
import pl.wavesoftware.utils.stringify.spi.Configurator;
21+
import pl.wavesoftware.utils.stringify.spi.theme.Theme;
2122

2223
/**
2324
* A interface that represents a configuration options for this library
@@ -60,4 +61,12 @@ public interface Configuration {
6061
* @return a self reference
6162
*/
6263
Configuration beanFactory(BeanFactory beanFactory);
64+
65+
/**
66+
* Configures a user provided theme
67+
*
68+
* @param theme a theme provided by user
69+
* @return a self reference
70+
*/
71+
Configuration theme(Theme theme);
6372
}

src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultConfiguration.java

+13
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import pl.wavesoftware.utils.stringify.api.Configuration;
2020
import pl.wavesoftware.utils.stringify.api.Mode;
2121
import pl.wavesoftware.utils.stringify.impl.beans.BeansModule;
22+
import pl.wavesoftware.utils.stringify.impl.theme.ThemeModule;
2223
import pl.wavesoftware.utils.stringify.spi.BeanFactory;
24+
import pl.wavesoftware.utils.stringify.spi.theme.Theme;
2325

2426
/**
2527
* @author <a href="mailto:krzysztof.suszynski@wavesoftware.pl">Krzysztof Suszynski</a>
@@ -31,6 +33,7 @@ final class DefaultConfiguration implements Configuration {
3133

3234
private Mode mode = Mode.DEFAULT_MODE;
3335
private BeanFactory beanFactory = DEFAULT_BEAN_FACTORY;
36+
private Theme theme = ThemeModule.INSTANCE.defaultTheme();
3437

3538
@Override
3639
public Configuration mode(Mode mode) {
@@ -44,6 +47,12 @@ public Configuration beanFactory(BeanFactory beanFactory) {
4447
return this;
4548
}
4649

50+
@Override
51+
public Configuration theme(Theme theme) {
52+
this.theme = theme;
53+
return this;
54+
}
55+
4756
DefaultConfiguration dup() {
4857
DefaultConfiguration dup = new DefaultConfiguration();
4958
dup.beanFactory = beanFactory;
@@ -58,4 +67,8 @@ Mode getMode() {
5867
BeanFactory getBeanFactory() {
5968
return beanFactory;
6069
}
70+
71+
Theme getTheme() {
72+
return theme;
73+
}
6174
}

src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultInspectionContext.java

+22-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package pl.wavesoftware.utils.stringify.impl;
1818

1919
import pl.wavesoftware.utils.stringify.impl.inspector.InspectionContext;
20+
import pl.wavesoftware.utils.stringify.impl.inspector.RootInpector;
21+
import pl.wavesoftware.utils.stringify.spi.theme.Theme;
2022

2123
import java.util.IdentityHashMap;
2224
import java.util.Map;
@@ -28,14 +30,13 @@
2830
final class DefaultInspectionContext implements InspectionContext {
2931
private static final Object CONTAIN = new Object();
3032

31-
private final Map<Object, Object> resolved;
33+
private final Map<Object, Object> resolved = new IdentityHashMap<>();
34+
private final Theme theme;
3235

33-
DefaultInspectionContext() {
34-
this(new IdentityHashMap<>());
35-
}
36+
private RootInpector rootInpector;
3637

37-
private DefaultInspectionContext(Map<Object, Object> resolved) {
38-
this.resolved = resolved;
38+
DefaultInspectionContext(Theme theme) {
39+
this.theme = theme;
3940
}
4041

4142
@Override
@@ -44,7 +45,21 @@ public boolean wasInspected(Object object) {
4445
}
4546

4647
@Override
47-
public void markIsInspected(Object object) {
48+
public void markAsInspected(Object object) {
4849
resolved.put(object, CONTAIN);
4950
}
51+
52+
@Override
53+
public RootInpector rootInspector() {
54+
return rootInpector;
55+
}
56+
57+
@Override
58+
public Theme theme() {
59+
return theme;
60+
}
61+
62+
public void rootInpector(RootInpector rootInpector) {
63+
this.rootInpector = rootInpector;
64+
}
5065
}

src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultStringify.java

+8
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package pl.wavesoftware.utils.stringify.impl;
1818

1919
import pl.wavesoftware.utils.stringify.Stringify;
20+
import pl.wavesoftware.utils.stringify.api.Configuration;
2021
import pl.wavesoftware.utils.stringify.api.Inspect;
2122
import pl.wavesoftware.utils.stringify.api.Mode;
2223
import pl.wavesoftware.utils.stringify.spi.BeanFactory;
24+
import pl.wavesoftware.utils.stringify.spi.theme.Theme;
2325

2426
/**
2527
* A default implementation of {@link Stringify}.
@@ -84,4 +86,10 @@ public Stringify beanFactory(BeanFactory beanFactory) {
8486
resolver.beanFactory(beanFactory);
8587
return this;
8688
}
89+
90+
@Override
91+
public Configuration theme(Theme theme) {
92+
resolver.theme(theme);
93+
return this;
94+
}
8795
}

src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java

+25-21
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
import pl.wavesoftware.utils.stringify.impl.inspector.InspectionContext;
2222
import pl.wavesoftware.utils.stringify.impl.inspector.InspectorModule;
2323
import pl.wavesoftware.utils.stringify.impl.inspector.ObjectInspector;
24+
import pl.wavesoftware.utils.stringify.spi.theme.ComplexObjectStyle;
2425

2526
import java.lang.reflect.Field;
2627
import java.util.LinkedHashMap;
2728
import java.util.Map;
28-
import java.util.function.Function;
2929

3030
import static pl.wavesoftware.eid.utils.EidExecutions.tryToExecute;
3131

@@ -40,56 +40,56 @@ final class InspectorBasedToStringResolver implements ToStringResolver {
4040
private final DefaultConfiguration configuration;
4141
private final Object target;
4242
private final InspectionContext inspectionContext;
43-
private final Function<Object, CharSequence> alternative;
4443
private final BeanFactoryCache beanFactoryCache;
4544
private final InspectingFieldFactory inspectingFieldFactory;
4645

4746
InspectorBasedToStringResolver(
4847
DefaultConfiguration configuration,
4948
Object target,
5049
InspectionContext inspectionContext,
51-
Function<Object, CharSequence> alternative,
5250
BeanFactoryCache beanFactoryCache,
5351
InspectingFieldFactory inspectingFieldFactory
5452
) {
5553
this.configuration = configuration;
5654
this.target = target;
5755
this.inspectionContext = inspectionContext;
58-
this.alternative = alternative;
5956
this.beanFactoryCache = beanFactoryCache;
6057
this.inspectingFieldFactory = inspectingFieldFactory;
6158
}
6259

6360
@Override
6461
public CharSequence resolve() {
65-
inspectionContext.markIsInspected(target);
62+
inspectionContext.markAsInspected(target);
63+
ComplexObjectStyle style = inspectionContext.theme().complexObject();
6664
StringBuilder sb = new StringBuilder();
67-
sb.append('<');
68-
sb.append(target.getClass().getSimpleName());
65+
sb.append(style.begin());
66+
sb.append(style.name(target::getClass, target::hashCode));
6967
CharSequence props = propertiesForToString();
7068
if (props.length() != 0) {
71-
sb.append(' ');
69+
sb.append(style.nameSeparator());
7270
sb.append(props);
7371
}
74-
sb.append('>');
72+
sb.append(style.end());
7573
return sb;
7674
}
7775

7876
private CharSequence propertiesForToString() {
7977
Map<String, CharSequence> props;
8078
props = inspectTargetAsClass(target.getClass());
79+
ComplexObjectStyle style = inspectionContext.theme().complexObject();
8180
StringBuilder sb = new StringBuilder();
8281
for (Map.Entry<String, CharSequence> entry : props.entrySet()) {
8382
String fieldName = entry.getKey();
8483
CharSequence fieldStringValue = entry.getValue();
8584
sb.append(fieldName);
86-
sb.append("=");
85+
sb.append(style.propertyEquals());
8786
sb.append(fieldStringValue);
88-
sb.append(", ");
87+
sb.append(style.propertySeparator());
8988
}
90-
if (sb.length() > 0) {
91-
sb.deleteCharAt(sb.length() - 1);
92-
sb.deleteCharAt(sb.length() - 1);
89+
if (!props.isEmpty()) {
90+
for (int i = 0; i < style.propertySeparator().length(); i++) {
91+
sb.deleteCharAt(sb.length() - 1);
92+
}
9393
}
9494
return sb;
9595
}
@@ -106,11 +106,13 @@ private Map<String, CharSequence> inspectTargetAsClass(Class<?> type) {
106106
return props;
107107
}
108108

109-
private void inspectFields(Field[] fields,
110-
Map<String, CharSequence> properties) {
109+
private void inspectFields(
110+
Field[] fields, Map<String, CharSequence> properties
111+
) {
111112
for (Field field : fields) {
112113
InspectionPoint inspectionPoint = createInspectionPoint(field);
113-
InspectingField inspectingField = inspectingFieldFactory.create(inspectionPoint, beanFactoryCache);
114+
InspectingField inspectingField = inspectingFieldFactory
115+
.create(inspectionPoint, beanFactoryCache);
114116
if (inspectingField.shouldInspect()) {
115117
inspectAnnotatedField(properties, field, inspectingField);
116118
}
@@ -121,9 +123,11 @@ private InspectionPoint createInspectionPoint(Field field) {
121123
return new InspectionPointImpl(field, target);
122124
}
123125

124-
private void inspectAnnotatedField(final Map<String, CharSequence> properties,
125-
final Field field,
126-
final InspectingField inspectingField) {
126+
private void inspectAnnotatedField(
127+
final Map<String, CharSequence> properties,
128+
final Field field,
129+
final InspectingField inspectingField
130+
) {
127131
tryToExecute(() -> {
128132
ensureAccessible(field);
129133
Object value = field.get(target);
@@ -146,7 +150,7 @@ private static void ensureAccessible(Field field) {
146150
CharSequence inspectObject(Object object) {
147151
for (ObjectInspector inspector : OBJECT_INSPECTORS) {
148152
if (inspector.consentTo(object, inspectionContext)) {
149-
return inspector.inspect(object, alternative);
153+
return inspector.inspect(object, inspectionContext);
150154
}
151155
}
152156
ToStringResolverImpl sub = new ToStringResolverImpl(

src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java

+21-12
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
import pl.wavesoftware.utils.stringify.impl.beans.BeansModule;
2323
import pl.wavesoftware.utils.stringify.impl.inspector.InspectionContext;
2424
import pl.wavesoftware.utils.stringify.spi.BeanFactory;
25-
26-
import java.util.function.Function;
25+
import pl.wavesoftware.utils.stringify.spi.theme.Theme;
2726

2827
/**
2928
* @author <a href="mailto:krzysztof.suszynski@wavesoftware.pl">Krzysztof Suszynski</a>
@@ -44,7 +43,7 @@ final class ToStringResolverImpl implements ToStringResolver, Configuration {
4443
this(
4544
target,
4645
configuration,
47-
new DefaultInspectionContext(),
46+
new DefaultInspectionContext(configuration.getTheme()),
4847
BeansModule.INSTANCE.cachedBeanFactory(
4948
configuration::getBeanFactory, target
5049
),
@@ -61,9 +60,23 @@ final class ToStringResolverImpl implements ToStringResolver, Configuration {
6160
) {
6261
this.configuration = configuration;
6362
this.delegateResolver = new InspectorBasedToStringResolver(
64-
configuration, target, inspectionContext, new ObjectInspectorImpl(),
63+
configuration, target, inspectionContext,
64+
beanFactoryCache, inspectingFieldFactory
65+
);
66+
}
67+
68+
private ToStringResolverImpl(
69+
Object target,
70+
DefaultConfiguration configuration,
71+
DefaultInspectionContext inspectionContext,
72+
BeanFactoryCache beanFactoryCache,
73+
InspectingFieldFactory inspectingFieldFactory
74+
) {
75+
this(
76+
target, configuration, (InspectionContext) inspectionContext,
6577
beanFactoryCache, inspectingFieldFactory
6678
);
79+
inspectionContext.rootInpector(delegateResolver::inspectObject);
6780
}
6881

6982
@Override
@@ -83,13 +96,9 @@ public Configuration beanFactory(BeanFactory beanFactory) {
8396
return configuration.beanFactory(beanFactory);
8497
}
8598

86-
private final class ObjectInspectorImpl implements Function<Object, CharSequence> {
87-
88-
@Override
89-
public CharSequence apply(Object object) {
90-
return delegateResolver.inspectObject(object);
91-
}
92-
99+
@Override
100+
public Configuration theme(Theme theme) {
101+
delegateResolver.clear();
102+
return configuration.theme(theme);
93103
}
94-
95104
}

src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java

+5-6
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,21 @@
1616

1717
package pl.wavesoftware.utils.stringify.impl.inspector;
1818

19-
import java.util.function.Function;
20-
2119
/**
2220
* @author <a href="mailto:krzysztof.suszynski@coi.gov.pl">Krzysztof Suszynski</a>
2321
* @since 1.0.0
2422
*/
2523
final class CharSequenceInspector implements ObjectInspector {
2624
@Override
27-
public boolean consentTo(Object candidate, InspectionContext inspectionContext) {
25+
public boolean consentTo(Object candidate, InspectionContext context) {
2826
return candidate instanceof CharSequence;
2927
}
3028

3129
@Override
32-
public CharSequence inspect(Object object,
33-
Function<Object, CharSequence> alternative) {
34-
return "\"" + object.toString() + "\"";
30+
public CharSequence inspect(Object object, InspectionContext context) {
31+
CharSequence quote = context.theme().charSequence().quote();
32+
StringBuilder stringBuilder = new StringBuilder(quote);
33+
return stringBuilder.append(object.toString()).append(quote);
3534
}
3635

3736
}

src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@
1616

1717
package pl.wavesoftware.utils.stringify.impl.inspector;
1818

19-
import java.util.function.Function;
20-
2119
/**
2220
* @author <a href="mailto:krzysztof.suszynski@coi.gov.pl">Krzysztof Suszynski</a>
2321
* @since 1.0.0
2422
*/
2523
final class CharacterInspector implements ObjectInspector {
2624

2725
@Override
28-
public boolean consentTo(Object candidate, InspectionContext inspectionContext) {
26+
public boolean consentTo(Object candidate, InspectionContext context) {
2927
return candidate instanceof Character;
3028
}
3129

3230
@Override
33-
public CharSequence inspect(Object object, Function<Object, CharSequence> alternative) {
34-
return "'" + object.toString() + "'";
31+
public CharSequence inspect(Object object, InspectionContext context) {
32+
CharSequence quote = context.theme().character().quote();
33+
StringBuilder stringBuilder = new StringBuilder(quote);
34+
return stringBuilder.append(object.toString()).append(quote);
3535
}
3636
}

0 commit comments

Comments
 (0)