diff --git a/src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java b/src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java index f80642d..5c5e650 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java @@ -18,6 +18,7 @@ import pl.wavesoftware.utils.stringify.spi.BeanFactory; import pl.wavesoftware.utils.stringify.spi.Configurator; +import pl.wavesoftware.utils.stringify.spi.theme.Theme; /** * A interface that represents a configuration options for this library @@ -60,4 +61,12 @@ public interface Configuration { * @return a self reference */ Configuration beanFactory(BeanFactory beanFactory); + + /** + * Configures a user provided theme + * + * @param theme a theme provided by user + * @return a self reference + */ + Configuration theme(Theme theme); } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultConfiguration.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultConfiguration.java index 69d224f..060af33 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultConfiguration.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultConfiguration.java @@ -20,6 +20,7 @@ import pl.wavesoftware.utils.stringify.api.Mode; import pl.wavesoftware.utils.stringify.impl.beans.BeansModule; import pl.wavesoftware.utils.stringify.spi.BeanFactory; +import pl.wavesoftware.utils.stringify.spi.theme.Theme; /** * @author Krzysztof Suszynski @@ -31,6 +32,7 @@ final class DefaultConfiguration implements Configuration { private Mode mode = Mode.DEFAULT_MODE; private BeanFactory beanFactory = DEFAULT_BEAN_FACTORY; + private Theme theme = new Theme() {}; @Override public Configuration mode(Mode mode) { @@ -44,10 +46,17 @@ public Configuration beanFactory(BeanFactory beanFactory) { return this; } + @Override + public Configuration theme(Theme theme) { + this.theme = theme; + return this; + } + DefaultConfiguration dup() { DefaultConfiguration dup = new DefaultConfiguration(); dup.beanFactory = beanFactory; dup.mode = mode; + dup.theme = theme; return dup; } @@ -58,4 +67,8 @@ Mode getMode() { BeanFactory getBeanFactory() { return beanFactory; } + + Theme getTheme() { + return theme; + } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultInspectionContext.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultInspectionContext.java index 2df42cf..37b4cb2 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultInspectionContext.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultInspectionContext.java @@ -17,9 +17,12 @@ package pl.wavesoftware.utils.stringify.impl; import pl.wavesoftware.utils.stringify.impl.inspector.InspectionContext; +import pl.wavesoftware.utils.stringify.impl.inspector.RootInpector; +import pl.wavesoftware.utils.stringify.spi.theme.Theme; import java.util.IdentityHashMap; import java.util.Map; +import java.util.function.Supplier; /** * @author Krzysztof Suszynski @@ -28,14 +31,13 @@ final class DefaultInspectionContext implements InspectionContext { private static final Object CONTAIN = new Object(); - private final Map resolved; + private final Map resolved = new IdentityHashMap<>(); + private final Supplier theme; - DefaultInspectionContext() { - this(new IdentityHashMap<>()); - } + private RootInpector rootInpector; - private DefaultInspectionContext(Map resolved) { - this.resolved = resolved; + DefaultInspectionContext(Supplier theme) { + this.theme = theme; } @Override @@ -44,7 +46,21 @@ public boolean wasInspected(Object object) { } @Override - public void markIsInspected(Object object) { + public void markAsInspected(Object object) { resolved.put(object, CONTAIN); } + + @Override + public RootInpector rootInspector() { + return rootInpector; + } + + @Override + public Theme theme() { + return theme.get(); + } + + public void rootInpector(RootInpector rootInpector) { + this.rootInpector = rootInpector; + } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultStringify.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultStringify.java index 5e46d04..51dd7ca 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultStringify.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultStringify.java @@ -17,9 +17,11 @@ package pl.wavesoftware.utils.stringify.impl; import pl.wavesoftware.utils.stringify.Stringify; +import pl.wavesoftware.utils.stringify.api.Configuration; import pl.wavesoftware.utils.stringify.api.Inspect; import pl.wavesoftware.utils.stringify.api.Mode; import pl.wavesoftware.utils.stringify.spi.BeanFactory; +import pl.wavesoftware.utils.stringify.spi.theme.Theme; /** * A default implementation of {@link Stringify}. @@ -84,4 +86,10 @@ public Stringify beanFactory(BeanFactory beanFactory) { resolver.beanFactory(beanFactory); return this; } + + @Override + public Configuration theme(Theme theme) { + resolver.theme(theme); + return this; + } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java index a6c528a..55825f8 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java @@ -21,11 +21,11 @@ import pl.wavesoftware.utils.stringify.impl.inspector.InspectionContext; import pl.wavesoftware.utils.stringify.impl.inspector.InspectorModule; import pl.wavesoftware.utils.stringify.impl.inspector.ObjectInspector; +import pl.wavesoftware.utils.stringify.spi.theme.ComplexObjectStyle; import java.lang.reflect.Field; import java.util.LinkedHashMap; import java.util.Map; -import java.util.function.Function; import static pl.wavesoftware.eid.utils.EidExecutions.tryToExecute; @@ -40,7 +40,6 @@ final class InspectorBasedToStringResolver implements ToStringResolver { private final DefaultConfiguration configuration; private final Object target; private final InspectionContext inspectionContext; - private final Function alternative; private final BeanFactoryCache beanFactoryCache; private final InspectingFieldFactory inspectingFieldFactory; @@ -48,48 +47,50 @@ final class InspectorBasedToStringResolver implements ToStringResolver { DefaultConfiguration configuration, Object target, InspectionContext inspectionContext, - Function alternative, BeanFactoryCache beanFactoryCache, InspectingFieldFactory inspectingFieldFactory ) { this.configuration = configuration; this.target = target; this.inspectionContext = inspectionContext; - this.alternative = alternative; this.beanFactoryCache = beanFactoryCache; this.inspectingFieldFactory = inspectingFieldFactory; } @Override public CharSequence resolve() { - inspectionContext.markIsInspected(target); + inspectionContext.markAsInspected(target); + ComplexObjectStyle style = inspectionContext.theme().complexObject(); StringBuilder sb = new StringBuilder(); - sb.append('<'); - sb.append(target.getClass().getSimpleName()); + sb.append(style.begin()); + sb.append(style.name(target)); CharSequence props = propertiesForToString(); if (props.length() != 0) { - sb.append(' '); + sb.append(style.nameSeparator()); sb.append(props); } - sb.append('>'); + sb.append(style.end()); return sb; } private CharSequence propertiesForToString() { Map props; props = inspectTargetAsClass(target.getClass()); + ComplexObjectStyle style = inspectionContext.theme().complexObject(); StringBuilder sb = new StringBuilder(); + CharSequence propertySeparator = style.propertySeparator(); for (Map.Entry entry : props.entrySet()) { String fieldName = entry.getKey(); CharSequence fieldStringValue = entry.getValue(); sb.append(fieldName); - sb.append("="); + sb.append(style.propertyEquals()); sb.append(fieldStringValue); - sb.append(", "); + sb.append(propertySeparator); } - if (sb.length() > 0) { - sb.deleteCharAt(sb.length() - 1); - sb.deleteCharAt(sb.length() - 1); + if (!props.isEmpty()) { + for (int i = 0; i < propertySeparator.length(); i++) { + sb.deleteCharAt(sb.length() - 1); + } } return sb; } @@ -106,11 +107,13 @@ private Map inspectTargetAsClass(Class type) { return props; } - private void inspectFields(Field[] fields, - Map properties) { + private void inspectFields( + Field[] fields, Map properties + ) { for (Field field : fields) { InspectionPoint inspectionPoint = createInspectionPoint(field); - InspectingField inspectingField = inspectingFieldFactory.create(inspectionPoint, beanFactoryCache); + InspectingField inspectingField = inspectingFieldFactory + .create(inspectionPoint, beanFactoryCache); if (inspectingField.shouldInspect()) { inspectAnnotatedField(properties, field, inspectingField); } @@ -121,9 +124,11 @@ private InspectionPoint createInspectionPoint(Field field) { return new InspectionPointImpl(field, target); } - private void inspectAnnotatedField(final Map properties, - final Field field, - final InspectingField inspectingField) { + private void inspectAnnotatedField( + final Map properties, + final Field field, + final InspectingField inspectingField + ) { tryToExecute(() -> { ensureAccessible(field); Object value = field.get(target); @@ -146,7 +151,7 @@ private static void ensureAccessible(Field field) { CharSequence inspectObject(Object object) { for (ObjectInspector inspector : OBJECT_INSPECTORS) { if (inspector.consentTo(object, inspectionContext)) { - return inspector.inspect(object, alternative); + return inspector.inspect(object, inspectionContext); } } ToStringResolverImpl sub = new ToStringResolverImpl( diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java index b9f5ae8..fa2d8fa 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java @@ -22,8 +22,7 @@ import pl.wavesoftware.utils.stringify.impl.beans.BeansModule; import pl.wavesoftware.utils.stringify.impl.inspector.InspectionContext; import pl.wavesoftware.utils.stringify.spi.BeanFactory; - -import java.util.function.Function; +import pl.wavesoftware.utils.stringify.spi.theme.Theme; /** * @author Krzysztof Suszynski @@ -44,7 +43,7 @@ final class ToStringResolverImpl implements ToStringResolver, Configuration { this( target, configuration, - new DefaultInspectionContext(), + new DefaultInspectionContext(configuration::getTheme), BeansModule.INSTANCE.cachedBeanFactory( configuration::getBeanFactory, target ), @@ -61,9 +60,23 @@ final class ToStringResolverImpl implements ToStringResolver, Configuration { ) { this.configuration = configuration; this.delegateResolver = new InspectorBasedToStringResolver( - configuration, target, inspectionContext, new ObjectInspectorImpl(), + configuration, target, inspectionContext, + beanFactoryCache, inspectingFieldFactory + ); + } + + private ToStringResolverImpl( + Object target, + DefaultConfiguration configuration, + DefaultInspectionContext inspectionContext, + BeanFactoryCache beanFactoryCache, + InspectingFieldFactory inspectingFieldFactory + ) { + this( + target, configuration, (InspectionContext) inspectionContext, beanFactoryCache, inspectingFieldFactory ); + inspectionContext.rootInpector(delegateResolver::inspectObject); } @Override @@ -83,13 +96,9 @@ public Configuration beanFactory(BeanFactory beanFactory) { return configuration.beanFactory(beanFactory); } - private final class ObjectInspectorImpl implements Function { - - @Override - public CharSequence apply(Object object) { - return delegateResolver.inspectObject(object); - } - + @Override + public Configuration theme(Theme theme) { + delegateResolver.clear(); + return configuration.theme(theme); } - } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java index 72b93e7..a755cde 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java @@ -16,22 +16,21 @@ package pl.wavesoftware.utils.stringify.impl.inspector; -import java.util.function.Function; - /** * @author Krzysztof Suszynski * @since 1.0.0 */ final class CharSequenceInspector implements ObjectInspector { @Override - public boolean consentTo(Object candidate, InspectionContext inspectionContext) { + public boolean consentTo(Object candidate, InspectionContext context) { return candidate instanceof CharSequence; } @Override - public CharSequence inspect(Object object, - Function alternative) { - return "\"" + object.toString() + "\""; + public CharSequence inspect(Object object, InspectionContext context) { + CharSequence quote = context.theme().charSequence().quote(); + StringBuilder stringBuilder = new StringBuilder(quote); + return stringBuilder.append(object.toString()).append(quote); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java index d4463d1..8c84cee 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java @@ -16,8 +16,6 @@ package pl.wavesoftware.utils.stringify.impl.inspector; -import java.util.function.Function; - /** * @author Krzysztof Suszynski * @since 1.0.0 @@ -25,12 +23,14 @@ final class CharacterInspector implements ObjectInspector { @Override - public boolean consentTo(Object candidate, InspectionContext inspectionContext) { + public boolean consentTo(Object candidate, InspectionContext context) { return candidate instanceof Character; } @Override - public CharSequence inspect(Object object, Function alternative) { - return "'" + object.toString() + "'"; + public CharSequence inspect(Object object, InspectionContext context) { + CharSequence quote = context.theme().character().quote(); + StringBuilder stringBuilder = new StringBuilder(quote); + return stringBuilder.append(object.toString()).append(quote); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectionContext.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectionContext.java index 2da510e..a79d393 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectionContext.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectionContext.java @@ -16,11 +16,42 @@ package pl.wavesoftware.utils.stringify.impl.inspector; +import pl.wavesoftware.utils.stringify.spi.theme.Theme; + /** + * Represents a context while complex object is being inspected. This object is created + * while staring inspection and lives until inspection is over. + * * @author Krzysztof Suszynski * @since 1.0.0 */ public interface InspectionContext { + /** + * Determine if given object was already inspected. + * + * @param object a object to test + * @return true, if object was already inspected, false otherwise. + */ boolean wasInspected(Object object); - void markIsInspected(Object object); + + /** + * Marks an object as inspected. This is to prevent recursion. + * + * @param object an object to be marked + */ + void markAsInspected(Object object); + + /** + * Retrieves a root inspector. + * + * @return a root inspector. + */ + RootInpector rootInspector(); + + /** + * Retrieves a currently configured theme to be used by inspectors + * + * @return a theme + */ + Theme theme(); } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/IterableInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/IterableInspector.java index 391cd65..e59857b 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/IterableInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/IterableInspector.java @@ -16,7 +16,7 @@ package pl.wavesoftware.utils.stringify.impl.inspector; -import java.util.function.Function; +import pl.wavesoftware.utils.stringify.spi.theme.IterableStyle; /** * @author Krzysztof Suszynski @@ -24,28 +24,29 @@ */ final class IterableInspector implements ObjectInspector { @Override - public boolean consentTo(Object candidate, InspectionContext inspectionContext) { + public boolean consentTo(Object candidate, InspectionContext context) { return candidate instanceof Iterable; } @Override - public CharSequence inspect(Object object, - Function alternative) { - return inspectIterable((Iterable) object, alternative); + public CharSequence inspect(Object object, InspectionContext context) { + return inspectIterable((Iterable) object, context); } - private static CharSequence inspectIterable(Iterable iterable, - Function alternative) { + private static CharSequence inspectIterable( + Iterable iterable, InspectionContext context + ) { + IterableStyle style = context.theme().iterable(); StringBuilder sb = new StringBuilder(); - sb.append("["); + sb.append(style.begin()); for (Object elem : iterable) { - sb.append(alternative.apply(elem)); - sb.append(","); + sb.append(context.rootInspector().apply(elem)); + sb.append(style.separator()); } - if (sb.length() > 1) { - sb.deleteCharAt(sb.length() - 1); + if (sb.length() > style.begin().length()) { + sb.deleteCharAt(sb.length() - style.separator().length()); } - sb.append("]"); + sb.append(style.end()); return sb.toString(); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/JpaLazyInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/JpaLazyInspector.java index b9d989e..3d2eba6 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/JpaLazyInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/JpaLazyInspector.java @@ -18,23 +18,22 @@ import pl.wavesoftware.utils.stringify.impl.jpa.JpaModule; -import java.util.function.Function; - /** * @author Krzysztof Suszynski * @since 1.0.0 */ final class JpaLazyInspector implements ObjectInspector { @Override - public boolean consentTo(Object candidate, InspectionContext inspectionContext) { + public boolean consentTo(Object candidate, InspectionContext context) { return JpaModule.INSTANCE .lazyChecker() .isLazy(candidate); } @Override - public CharSequence inspect(Object object, - Function alternative) { - return "⁂Lazy"; + public CharSequence inspect(Object object, InspectionContext context) { + return context.theme() + .jpaLazy() + .representation(object); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/MapInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/MapInspector.java index 76224c7..fe0ff93 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/MapInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/MapInspector.java @@ -16,8 +16,9 @@ package pl.wavesoftware.utils.stringify.impl.inspector; +import pl.wavesoftware.utils.stringify.spi.theme.MapStyle; + import java.util.Map; -import java.util.function.Function; /** * @author Krzysztof Suszynski @@ -26,30 +27,30 @@ final class MapInspector implements ObjectInspector { @Override - public boolean consentTo(Object candidate, - InspectionContext inspectionContext) { + public boolean consentTo(Object candidate, InspectionContext context) { return candidate instanceof Map; } @Override - public CharSequence inspect(Object object, - Function alternative) { + public CharSequence inspect(Object object, InspectionContext context) { Map map = (Map) object; + MapStyle style = context.theme().map(); StringBuilder sb = new StringBuilder(); - sb.append("{"); + sb.append(style.begin()); for (Map.Entry entry : map.entrySet()) { Object key = entry.getKey(); Object value = entry.getValue(); - sb.append(alternative.apply(key)); - sb.append(": "); - sb.append(alternative.apply(value)); - sb.append(", "); + sb.append(context.rootInspector().apply(key)); + sb.append(style.entryEquals()); + sb.append(context.rootInspector().apply(value)); + sb.append(style.separator()); } - if (sb.length() > 1) { - sb.deleteCharAt(sb.length() - 1); - sb.deleteCharAt(sb.length() - 1); + if (!map.isEmpty()) { + for (int i=0; i < style.separator().length(); i++) { + sb.deleteCharAt(sb.length() - 1); + } } - sb.append("}"); + sb.append(style.end()); return sb.toString(); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/ObjectInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/ObjectInspector.java index 547a06f..69d6e37 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/ObjectInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/ObjectInspector.java @@ -16,16 +16,30 @@ package pl.wavesoftware.utils.stringify.impl.inspector; -import java.util.function.Function; - /** + * Represents a basic object inspector that can handle specific type of object, which + * is determined by call to {@link #consentTo(Object, InspectionContext)} + * method. + * * @author Krzysztof Suszynski * @since 1.0.0 */ public interface ObjectInspector { - boolean consentTo(Object candidate, InspectionContext inspectionContext); + /** + * Determines if this inspector is suitable for a given object + * + * @param candidate a candidate to inspect + * @param context a context of inspection + * @return true, if this object inspector can inspect candidate object + */ + boolean consentTo(Object candidate, InspectionContext context); - CharSequence inspect( - Object object, Function alternative - ); + /** + * Will inspect a given object to character sequence + * + * @param object a object to inspect + * @param context a context of inspection + * @return a character sequence representation of given object + */ + CharSequence inspect(Object object, InspectionContext context); } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/PrimitiveInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/PrimitiveInspector.java index d0366bc..cd948ea 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/PrimitiveInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/PrimitiveInspector.java @@ -18,7 +18,6 @@ import java.time.temporal.Temporal; import java.util.Date; -import java.util.function.Function; /** * @author Krzysztof Suszynski @@ -27,14 +26,12 @@ final class PrimitiveInspector implements ObjectInspector { @Override - public boolean consentTo(Object candidate, - InspectionContext inspectionContext) { + public boolean consentTo(Object candidate, InspectionContext context) { return isPrimitive(candidate); } @Override - public CharSequence inspect(Object object, - Function alternative) { + public CharSequence inspect(Object object, InspectionContext context) { return object.toString(); } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RecursionInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RecursionInspector.java index d360fea..76afb1b 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RecursionInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RecursionInspector.java @@ -16,8 +16,6 @@ package pl.wavesoftware.utils.stringify.impl.inspector; -import java.util.function.Function; - /** * @author Krzysztof Suszynski * @since 1.0.0 @@ -29,8 +27,9 @@ public boolean consentTo(Object candidate, InspectionContext context) { } @Override - public CharSequence inspect(Object object, - Function alternative) { - return "(↻)"; + public CharSequence inspect(Object object, InspectionContext context) { + return context.theme() + .recursion() + .representation(object); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RootInpector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RootInpector.java new file mode 100644 index 0000000..784ccb4 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RootInpector.java @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.impl.inspector; + +import java.util.function.Function; + +/** + * An root inspector is a reference to the entrypoint of this library, a class + * configured ready to inspect an object. + * + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface RootInpector extends Function { +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/CharSequenceStyle.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/CharSequenceStyle.java new file mode 100644 index 0000000..4cd6a44 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/CharSequenceStyle.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface CharSequenceStyle { + default CharSequence quote() { + return "\""; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/CharacterStyle.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/CharacterStyle.java new file mode 100644 index 0000000..7ab4752 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/CharacterStyle.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface CharacterStyle { + default CharSequence quote() { + return "'"; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/ComplexObjectStyle.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/ComplexObjectStyle.java new file mode 100644 index 0000000..4e5def8 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/ComplexObjectStyle.java @@ -0,0 +1,47 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface ComplexObjectStyle { + default CharSequence begin() { + return "<"; + } + + default CharSequence name(Object target) { + return target.getClass().getSimpleName(); + } + + default CharSequence end() { + return ">"; + } + + default CharSequence nameSeparator() { + return " "; + } + + default CharSequence propertyEquals() { + return "="; + } + + default CharSequence propertySeparator() { + return ", "; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/IterableStyle.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/IterableStyle.java new file mode 100644 index 0000000..767995e --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/IterableStyle.java @@ -0,0 +1,35 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface IterableStyle { + default CharSequence begin() { + return "["; + } + + default CharSequence separator() { + return ","; + } + + default CharSequence end() { + return "]"; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/JpaLazyStyle.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/JpaLazyStyle.java new file mode 100644 index 0000000..8ea9223 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/JpaLazyStyle.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface JpaLazyStyle { + default CharSequence representation(Object target) { + return "⁂Lazy"; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/MapStyle.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/MapStyle.java new file mode 100644 index 0000000..7ff0a91 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/MapStyle.java @@ -0,0 +1,39 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * @author Krzysztof Suszynski + * @since 0.1.0 + */ +public interface MapStyle { + default CharSequence begin() { + return "{"; + } + + default CharSequence separator() { + return ", "; + } + + default CharSequence entryEquals() { + return ": "; + } + + default CharSequence end() { + return "}"; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/RecursionStyle.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/RecursionStyle.java new file mode 100644 index 0000000..ea5c2c0 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/RecursionStyle.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface RecursionStyle { + default CharSequence representation(Object target) { + return "(↻)"; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/Theme.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/Theme.java new file mode 100644 index 0000000..ffd0dd5 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/Theme.java @@ -0,0 +1,53 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.spi.theme; + +/** + * Theme represents a set of styles for object inspectors. + * + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface Theme { + default ComplexObjectStyle complexObject() { + return new ComplexObjectStyle() {}; + } + + default MapStyle map() { + return new MapStyle() {}; + } + + default CharacterStyle character() { + return new CharacterStyle() {}; + } + + default CharSequenceStyle charSequence() { + return new CharSequenceStyle() {}; + } + + default IterableStyle iterable() { + return new IterableStyle() {}; + } + + default JpaLazyStyle jpaLazy() { + return new JpaLazyStyle() {}; + } + + default RecursionStyle recursion() { + return new RecursionStyle() {}; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/package-info.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/package-info.java new file mode 100644 index 0000000..f428d32 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/theme/package-info.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Krzysztof Suszynski + * @since 20.04.18 + */ +@ReturnTypesAreNonnullByDefault +@ParametersAreNonnullByDefault +package pl.wavesoftware.utils.stringify.spi.theme; + +import pl.wavesoftware.eid.api.ReturnTypesAreNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/test/java/pl/wavesoftware/utils/stringify/Beta.java b/src/test/java/pl/wavesoftware/utils/stringify/Beta.java new file mode 100644 index 0000000..e760acc --- /dev/null +++ b/src/test/java/pl/wavesoftware/utils/stringify/Beta.java @@ -0,0 +1,25 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +final class Beta { + Object value; +} diff --git a/src/test/java/pl/wavesoftware/utils/stringify/Earth.java b/src/test/java/pl/wavesoftware/utils/stringify/Earth.java index 25012f5..0701501 100644 --- a/src/test/java/pl/wavesoftware/utils/stringify/Earth.java +++ b/src/test/java/pl/wavesoftware/utils/stringify/Earth.java @@ -26,7 +26,7 @@ */ @Data @EqualsAndHashCode(callSuper = true) -final class Earth extends Planet { +public final class Earth extends Planet { private static final long serialVersionUID = 20180430201544L; diff --git a/src/test/java/pl/wavesoftware/utils/stringify/Planet.java b/src/test/java/pl/wavesoftware/utils/stringify/Planet.java index 719a36f..b7e9cf5 100644 --- a/src/test/java/pl/wavesoftware/utils/stringify/Planet.java +++ b/src/test/java/pl/wavesoftware/utils/stringify/Planet.java @@ -28,7 +28,7 @@ * @since 2018-04-18 */ @Data -abstract class Planet implements Serializable { +public abstract class Planet implements Serializable { private static final long serialVersionUID = 20180430201529L; diff --git a/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java b/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java index 431ac9a..404a3ed 100644 --- a/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java +++ b/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java @@ -228,6 +228,20 @@ void fallbackToDefault() { } } + @Test + void customLazyChecker() { + // given + Beta beta = new Beta(); + beta.value = new StubLazy(); + + // when + Stringify stringifier = Stringify.of(beta); + CharSequence result = stringifier.stringify(); + + // then + assertThat(result.toString()).isEqualTo(""); + } + private static boolean inspectionPointValue(final InspectionPoint inspectionPoint, final Predicate predicate) { return predicate.test( diff --git a/src/test/java/pl/wavesoftware/utils/stringify/StubLazy.java b/src/test/java/pl/wavesoftware/utils/stringify/StubLazy.java new file mode 100644 index 0000000..603716f --- /dev/null +++ b/src/test/java/pl/wavesoftware/utils/stringify/StubLazy.java @@ -0,0 +1,24 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +final class StubLazy { +} diff --git a/src/test/java/pl/wavesoftware/utils/stringify/StubLazyChecker.java b/src/test/java/pl/wavesoftware/utils/stringify/StubLazyChecker.java new file mode 100644 index 0000000..51590a1 --- /dev/null +++ b/src/test/java/pl/wavesoftware/utils/stringify/StubLazyChecker.java @@ -0,0 +1,37 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify; + +import pl.wavesoftware.utils.stringify.spi.JpaLazyChecker; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public final class StubLazyChecker implements JpaLazyChecker { + + @Override + public boolean isLazy(Object candidate) { + return true; + } + + @Override + public boolean isSuitable(Object candidate) { + return JpaLazyChecker.super.isSuitable(candidate) && + candidate instanceof StubLazy; + } +} diff --git a/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java b/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java index 8d37adb..75e69ab 100644 --- a/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java +++ b/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java @@ -29,9 +29,9 @@ * @author Krzysztof Suszynski * @since 20.04.18 */ -final class TestRepository { +public final class TestRepository { @SuppressWarnings("unchecked") - Planet createTestPlanet() { + public Planet createTestPlanet() { PlanetSystem earthPlanetSystem = new PlanetSystem(); Moon moon = new Moon(Phase.FULL_MOON); moon.setPlanetSystem(earthPlanetSystem); diff --git a/src/test/java/pl/wavesoftware/utils/stringify/impl/lang/LazyTest.java b/src/test/java/pl/wavesoftware/utils/stringify/impl/lang/LazyTest.java new file mode 100644 index 0000000..ded25c1 --- /dev/null +++ b/src/test/java/pl/wavesoftware/utils/stringify/impl/lang/LazyTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2018-2019 Wave Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.wavesoftware.utils.stringify.impl.lang; + +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.Base64; +import java.util.function.Supplier; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +class LazyTest { + + @Test + void of() { + // given + Supplier supplier = () -> 42; + Lazy lazy1 = Lazy.of(supplier); + Lazy lazy2 = Lazy.of(lazy1); + + // when + String toString1 = lazy1.toString(); + String toString2 = lazy2.toString(); + Integer result = lazy2.get(); + String toString3 = lazy1.toString(); + String toString4 = lazy2.toString(); + + // then + assertThat(result).isEqualTo(42); + assertThat(toString1).isEqualTo("Lazy(?)"); + assertThat(toString2).isEqualTo("Lazy(?)"); + assertThat(toString3).isEqualTo("Lazy(42)"); + assertThat(toString4).isEqualTo("Lazy(42)"); + } + + @Test + void equals1() { + // given + Supplier supplier = () -> 42; + Lazy lazy1 = Lazy.of(supplier); + Lazy lazy2 = Lazy.of(lazy1); + + // when + boolean result = lazy1.equals(lazy2); + + // then + assertThat(result).isTrue(); + } + + @Test + void hashCode1() { + // given + Supplier supplier = () -> 42; + Lazy lazy1 = Lazy.of(supplier); + Lazy lazy2 = Lazy.of(lazy1); + + // when + int result1 = lazy1.hashCode(); + int result2 = lazy2.hashCode(); + + // then + assertThat(result1).isEqualTo(result2); + } + + @Test + void serialize() throws IOException { + // given + Supplier supplier = () -> 42; + Lazy lazy = Lazy.of(supplier); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + // when + oos.writeObject(lazy); + byte[] bytes = baos.toByteArray(); + String result = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes); + + // then + assertThat(result).isEqualTo( + "rO0ABXNyAC5wbC53YXZlc29mdHdhcmUudXRpbHMuc3RyaW5naWZ5LmltcGwubGFuZy5MYXp5AAA" + + "SXQQND_YDAAFMAAV2YWx1ZXQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwc3IAEWphdmEubGFuZy5Jbn" + + "RlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4c" + + "AAAACp4" + ); + } + } + +} diff --git a/src/test/java/pl/wavesoftware/utils/stringify/spi/theme/CustomTheme.java b/src/test/java/pl/wavesoftware/utils/stringify/spi/theme/CustomTheme.java new file mode 100644 index 0000000..a618939 --- /dev/null +++ b/src/test/java/pl/wavesoftware/utils/stringify/spi/theme/CustomTheme.java @@ -0,0 +1,64 @@ +package pl.wavesoftware.utils.stringify.spi.theme; + +final class CustomTheme implements Theme { + private static CharSequence name(Object target) { + return target.getClass().getSimpleName() + + "#" + + Integer.toUnsignedString(System.identityHashCode(target), 36); + } + + @Override + public ComplexObjectStyle complexObject() { + return new ComplexObjectStyle() { + @Override + public CharSequence begin() { + return "("; + } + + @Override + public CharSequence name(Object target) { + return CustomTheme.name(target); + } + + @Override + public CharSequence end() { + return ")"; + } + + @Override + public CharSequence propertySeparator() { + return ", "; + } + }; + } + + @Override + public MapStyle map() { + return new MapStyle() { + @Override + public CharSequence entryEquals() { + return " => "; + } + }; + } + + @Override + public JpaLazyStyle jpaLazy() { + return new JpaLazyStyle() { + @Override + public CharSequence representation(Object target) { + return "❄️"; + } + }; + } + + @Override + public RecursionStyle recursion() { + return new RecursionStyle() { + @Override + public CharSequence representation(Object target) { + return "(↻️️ " + CustomTheme.name(target) + ")"; + } + }; + } +} diff --git a/src/test/java/pl/wavesoftware/utils/stringify/spi/theme/ThemeTest.java b/src/test/java/pl/wavesoftware/utils/stringify/spi/theme/ThemeTest.java new file mode 100644 index 0000000..c1807ab --- /dev/null +++ b/src/test/java/pl/wavesoftware/utils/stringify/spi/theme/ThemeTest.java @@ -0,0 +1,56 @@ +package pl.wavesoftware.utils.stringify.spi.theme; + + +import org.junit.jupiter.api.Test; +import pl.wavesoftware.utils.stringify.Earth; +import pl.wavesoftware.utils.stringify.Stringify; +import pl.wavesoftware.utils.stringify.TestRepository; + +import static org.assertj.core.api.Assertions.assertThat; + +class ThemeTest { + private final TestRepository testRepository = new TestRepository(); + + @Test + void customTheme() { + // given + Earth planet = (Earth) testRepository.createTestPlanet(); + Stringify stringifier = Stringify.of(planet); + stringifier.theme(new CustomTheme()); + CharSequence earthHash = hash(planet); + CharSequence planetSystemHash = hash(planet.getPlanetSystem()); + CharSequence moonHash = hash(planet.getMoon()); + + // when + String result = stringifier.stringify().toString(); + + // then + String expected = format( + "(Earth#{0} name=\"Earth\", rocky=true, " + + "planetSystem=(PlanetSystem#{1} planets=❄️), " + + "moon=(Moon#{2} name=\"Moon\", rocky=null, " + + "planetSystem=(↻️️ PlanetSystem#{1}), phase=FULL_MOON, " + + "visits={" + + "\"1969\" => [\"Apollo 11\",\"Apollo 12\"], " + + "\"1971\" => [\"Apollo 14\",\"Apollo 15\"], " + + "\"1972\" => [\"Apollo 16\",\"Apollo 17\"]" + + "}), dayOfYear=14, type='A')", + earthHash, planetSystemHash, moonHash + ); + assertThat(result).isEqualTo(expected); + } + + private String format(String formatStr, Object... args) { + String work = formatStr; + for (int i = 0; i < args.length; i++) { + Object arg = args[i]; + work = work.replace("{" + i + "}", arg.toString()); + } + assertThat(work).isNotEqualTo(formatStr); + return work; + } + + private CharSequence hash(Object object) { + return Integer.toUnsignedString(System.identityHashCode(object), 36); + } +} diff --git a/src/test/resources/META-INF/services/pl.wavesoftware.utils.stringify.spi.JpaLazyChecker b/src/test/resources/META-INF/services/pl.wavesoftware.utils.stringify.spi.JpaLazyChecker new file mode 100644 index 0000000..9a6dd9f --- /dev/null +++ b/src/test/resources/META-INF/services/pl.wavesoftware.utils.stringify.spi.JpaLazyChecker @@ -0,0 +1 @@ +pl.wavesoftware.utils.stringify.StubLazyChecker