diff --git a/.travis.yml b/.travis.yml index 3fe6a0e..46558fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ matrix: env: JACOCO=true - jdk: openjdk8 env: JACOCO=true SONAR=publish - script: ./mvnw -V clean verify sonar:sonar --fail-at-end -U notifications: email: on_failure: change diff --git a/pom.xml b/pom.xml old mode 100755 new mode 100644 diff --git a/src/main/java/pl/wavesoftware/utils/stringify/Stringify.java b/src/main/java/pl/wavesoftware/utils/stringify/Stringify.java old mode 100755 new mode 100644 diff --git a/src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java b/src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java old mode 100755 new mode 100644 diff --git a/src/main/java/pl/wavesoftware/utils/stringify/api/Inspect.java b/src/main/java/pl/wavesoftware/utils/stringify/api/Inspect.java old mode 100755 new mode 100644 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 6bf7fd7..69d224f 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultConfiguration.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultConfiguration.java @@ -18,6 +18,7 @@ import pl.wavesoftware.utils.stringify.api.Configuration; import pl.wavesoftware.utils.stringify.api.Mode; +import pl.wavesoftware.utils.stringify.impl.beans.BeansModule; import pl.wavesoftware.utils.stringify.spi.BeanFactory; /** @@ -25,8 +26,8 @@ * @since 2.0.0 */ final class DefaultConfiguration implements Configuration { - static final DefaultBeanFactory DEFAULT_BEAN_FACTORY = - new DefaultBeanFactory(); + private static final BeanFactory DEFAULT_BEAN_FACTORY = + BeansModule.INSTANCE.defaultBeanFactory(); private Mode mode = Mode.DEFAULT_MODE; private BeanFactory beanFactory = DEFAULT_BEAN_FACTORY; 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 1514e2e..2df42cf 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultInspectionContext.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultInspectionContext.java @@ -16,6 +16,8 @@ package pl.wavesoftware.utils.stringify.impl; +import pl.wavesoftware.utils.stringify.impl.inspector.InspectionContext; + import java.util.IdentityHashMap; import java.util.Map; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/HibernateLazyChecker.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/HibernateLazyChecker.java deleted file mode 100644 index cb7523a..0000000 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/HibernateLazyChecker.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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; - -import pl.wavesoftware.eid.utils.UnsafeSupplier; - -import javax.annotation.Nonnull; -import java.lang.reflect.Method; - -import static pl.wavesoftware.eid.utils.EidExecutions.tryToExecute; - - -/** - * @author Krzysztof Suszynski - * @since 2018-04-18 - */ -final class HibernateLazyChecker implements JpaLazyChecker { - private static final ClassLocator HIBERNATE_LOCATOR = - new ClassLocator("org.hibernate.Hibernate"); - private static Method isInitializedMethod; - - static boolean isSuitable() { - return HIBERNATE_LOCATOR.isAvailable(); - } - - @Override - public boolean isLazy(final Object candidate) { - Class cls = HIBERNATE_LOCATOR.get(); - final Method method = getIsInitializedMethod(cls); - return !tryToExecute( - new UnsafeSupplier() { - @Override - @Nonnull - public Boolean get() throws Exception { - return (Boolean) method.invoke(null, candidate); - } - }, - "20180418:231314" - ); - } - - private static Method getIsInitializedMethod(final Class hibernateClass) { - if (isInitializedMethod == null) { - isInitializedMethod = tryToExecute( - new UnsafeSupplier() { - @Override - @Nonnull - public Method get() throws Exception { - return hibernateClass.getDeclaredMethod("isInitialized", Object.class); - } - }, - "20180418:231029" - ); - } - return isInitializedMethod; - } -} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/Inspectable.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/Inspectable.java deleted file mode 100755 index 349c918..0000000 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/Inspectable.java +++ /dev/null @@ -1,5 +0,0 @@ -package pl.wavesoftware.utils.stringify.impl; - -interface Inspectable { - String inspect(); -} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectionUtils.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectionUtils.java deleted file mode 100755 index 64d0343..0000000 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectionUtils.java +++ /dev/null @@ -1,14 +0,0 @@ -package pl.wavesoftware.utils.stringify.impl; - -final class InspectionUtils { - private InspectionUtils() { - // nothing - } - - static String safeInspect(Object object) { - if (object instanceof Inspectable) { - return ((Inspectable) object).inspect(); - } - return object.getClass().getName() + '@' + Integer.toHexString(object.hashCode()); - } -} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/Inspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java similarity index 91% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/Inspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java index 9bd6076..a6c528a 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/Inspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectorBasedToStringResolver.java @@ -17,9 +17,12 @@ package pl.wavesoftware.utils.stringify.impl; import pl.wavesoftware.utils.stringify.api.InspectionPoint; +import pl.wavesoftware.utils.stringify.impl.beans.BeanFactoryCache; +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 java.lang.reflect.Field; -import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; @@ -30,16 +33,9 @@ * @author Krzysztof Suszynski * @since 2.0.0 */ -final class Inspector implements ToStringResolver { - private static final Iterable OBJECT_INSPECTORS = Arrays.asList( - new CharSequenceInspector(), - new PrimitiveInspector(), - new CharacterInspector(), - new JpaLazyInspector(), - new MapInspector(), - new IterableInspector(), - new RecursionInspector() - ); +final class InspectorBasedToStringResolver implements ToStringResolver { + private static final Iterable OBJECT_INSPECTORS = + InspectorModule.INSTANCE.inspectors(); private final DefaultConfiguration configuration; private final Object target; @@ -48,7 +44,7 @@ final class Inspector implements ToStringResolver { private final BeanFactoryCache beanFactoryCache; private final InspectingFieldFactory inspectingFieldFactory; - Inspector( + InspectorBasedToStringResolver( DefaultConfiguration configuration, Object target, InspectionContext inspectionContext, diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java old mode 100755 new mode 100644 index 04ba80b..b9f5ae8 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/ToStringResolverImpl.java @@ -18,6 +18,9 @@ import pl.wavesoftware.utils.stringify.api.Configuration; import pl.wavesoftware.utils.stringify.api.Mode; +import pl.wavesoftware.utils.stringify.impl.beans.BeanFactoryCache; +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; @@ -29,7 +32,7 @@ final class ToStringResolverImpl implements ToStringResolver, Configuration { private final DefaultConfiguration configuration; - private final Inspector inspector; + private final InspectorBasedToStringResolver delegateResolver; /** * A default constructor @@ -42,10 +45,8 @@ final class ToStringResolverImpl implements ToStringResolver, Configuration { target, configuration, new DefaultInspectionContext(), - new BeanFactoryCache(() -> - new FallbackBootFactory( - new BootAwareBootFactory(configuration.getBeanFactory(), target) - ) + BeansModule.INSTANCE.cachedBeanFactory( + configuration::getBeanFactory, target ), new InspectingFieldFactory(configuration::getMode) ); @@ -59,7 +60,7 @@ final class ToStringResolverImpl implements ToStringResolver, Configuration { InspectingFieldFactory inspectingFieldFactory ) { this.configuration = configuration; - this.inspector = new Inspector( + this.delegateResolver = new InspectorBasedToStringResolver( configuration, target, inspectionContext, new ObjectInspectorImpl(), beanFactoryCache, inspectingFieldFactory ); @@ -67,18 +68,18 @@ configuration, target, inspectionContext, new ObjectInspectorImpl(), @Override public CharSequence resolve() { - return inspector.resolve(); + return delegateResolver.resolve(); } @Override public Configuration mode(Mode mode) { - inspector.clear(); + delegateResolver.clear(); return configuration.mode(mode); } @Override public Configuration beanFactory(BeanFactory beanFactory) { - inspector.clear(); + delegateResolver.clear(); return configuration.beanFactory(beanFactory); } @@ -86,7 +87,7 @@ private final class ObjectInspectorImpl implements FunctionKrzysztof Suszynski + * @since 0.1.0 + */ +public interface BeanFactoryCache extends BeanFactory { + /** + * Clears a bean factory. + */ + void clear(); +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/BeansModule.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/BeansModule.java new file mode 100644 index 0000000..8cfb6b6 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/BeansModule.java @@ -0,0 +1,41 @@ +/* + * 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.beans; + +import pl.wavesoftware.utils.stringify.spi.BeanFactory; + +import java.util.function.Supplier; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public enum BeansModule { + INSTANCE; + + public BeanFactory defaultBeanFactory() { + return new DefaultBeanFactory(); + } + + public BeanFactoryCache cachedBeanFactory(Supplier beanFactory, Object target) { + return new DefaultBeanFactoryCache(() -> + new FallbackBootFactory( + new BootAwareBootFactory(beanFactory, target) + ) + ); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/BootAwareBootFactory.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/BootAwareBootFactory.java old mode 100755 new mode 100644 similarity index 74% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/BootAwareBootFactory.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/beans/BootAwareBootFactory.java index 9c7aa65..5fd8c7f --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/BootAwareBootFactory.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/BootAwareBootFactory.java @@ -14,14 +14,16 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.beans; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import pl.wavesoftware.utils.stringify.impl.lang.Inspectable; +import pl.wavesoftware.utils.stringify.impl.lang.LangModule; import pl.wavesoftware.utils.stringify.spi.BeanFactory; import pl.wavesoftware.utils.stringify.spi.BootingAware; -import static pl.wavesoftware.utils.stringify.impl.InspectionUtils.safeInspect; +import java.util.function.Supplier; /** * @author Krzysztof Suszynski @@ -30,11 +32,11 @@ final class BootAwareBootFactory implements BeanFactory, Inspectable { private static final Logger LOGGER = LoggerFactory.getLogger(BootAwareBootFactory.class); - private final BeanFactory delegate; + private final Supplier delegateSupplier; private final Object target; - BootAwareBootFactory(BeanFactory delegate, Object target) { - this.delegate = delegate; + BootAwareBootFactory(Supplier delegateSupplier, Object target) { + this.delegateSupplier = delegateSupplier; this.target = target; } @@ -44,6 +46,7 @@ public T create(Class contractClass) { } private BeanFactory getBeanFactory(Class contractClass) { + BeanFactory delegate = delegateSupplier.get(); if (delegate instanceof BootingAware) { BootingAware bootingAware = (BootingAware) delegate; if (!bootingAware.isReady() && LOGGER.isWarnEnabled()) { @@ -54,7 +57,7 @@ private BeanFactory getBeanFactory(Class contractClass) { "fallback for this call.", safeInspect(delegate), safeInspect(target), contractClass ); - return DefaultConfiguration.DEFAULT_BEAN_FACTORY; + return BeansModule.INSTANCE.defaultBeanFactory(); } } return delegate; @@ -62,6 +65,10 @@ private BeanFactory getBeanFactory(Class contractClass) { @Override public String inspect() { - return safeInspect(delegate); + return safeInspect(delegateSupplier); + } + + private static String safeInspect(Object object) { + return LangModule.INSTANCE.safeInspector().inspect(object); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultBeanFactory.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/DefaultBeanFactory.java old mode 100755 new mode 100644 similarity index 95% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultBeanFactory.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/beans/DefaultBeanFactory.java index 4669def..3f095a6 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/DefaultBeanFactory.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/DefaultBeanFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.beans; import pl.wavesoftware.utils.stringify.spi.BeanFactory; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/BeanFactoryCache.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/DefaultBeanFactoryCache.java similarity index 91% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/BeanFactoryCache.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/beans/DefaultBeanFactoryCache.java index 657b1fd..540cbb0 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/BeanFactoryCache.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/DefaultBeanFactoryCache.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.beans; import lombok.RequiredArgsConstructor; import pl.wavesoftware.utils.stringify.spi.BeanFactory; @@ -28,7 +28,7 @@ * @since 2.0.0 */ @RequiredArgsConstructor -final class BeanFactoryCache implements BeanFactory { +final class DefaultBeanFactoryCache implements BeanFactoryCache { private final Map, Object> created = new ConcurrentHashMap<>(); private final Supplier delegate; @@ -42,7 +42,8 @@ public T create(final Class contractClass) { return predicate; } - void clear() { + @Override + public void clear() { created.clear(); } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/FallbackBootFactory.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/FallbackBootFactory.java old mode 100755 new mode 100644 similarity index 58% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/FallbackBootFactory.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/beans/FallbackBootFactory.java index 323aedc..58e3075 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/FallbackBootFactory.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/FallbackBootFactory.java @@ -1,14 +1,30 @@ -package pl.wavesoftware.utils.stringify.impl; +/* + * 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.beans; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.helpers.MessageFormatter; +import pl.wavesoftware.utils.stringify.impl.lang.LangModule; import pl.wavesoftware.utils.stringify.spi.BeanFactory; import javax.annotation.Nullable; import static pl.wavesoftware.eid.utils.EidPreconditions.checkState; -import static pl.wavesoftware.utils.stringify.impl.InspectionUtils.safeInspect; final class FallbackBootFactory implements BeanFactory { private static final Logger LOGGER = LoggerFactory.getLogger(FallbackBootFactory.class); @@ -30,7 +46,7 @@ public T create(Class contractClass) { MessageFormatter.format( "Configured BeanFactory {} thrown an exception while trying to " + "resolve {}. Fallback to default BeanFactory.", - safeInspect(beanFactory), contractClass + LangModule.INSTANCE.safeInspector().inspect(beanFactory), contractClass ).getMessage(), ex ); return DEFAULT.create(contractClass); diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/ReflectionBeanFactory.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/ReflectionBeanFactory.java old mode 100755 new mode 100644 similarity index 96% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/ReflectionBeanFactory.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/beans/ReflectionBeanFactory.java index db677e0..65cc58a --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/ReflectionBeanFactory.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/ReflectionBeanFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.beans; import pl.wavesoftware.eid.utils.UnsafeSupplier; import pl.wavesoftware.utils.stringify.spi.BeanFactory; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/package-info.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/package-info.java new file mode 100644 index 0000000..6c5e6cb --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/beans/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 2018-04-18 + */ +@ReturnTypesAreNonnullByDefault +@ParametersAreNonnullByDefault +package pl.wavesoftware.utils.stringify.impl.beans; + +import pl.wavesoftware.eid.api.ReturnTypesAreNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/CharSequenceInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java similarity index 93% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/CharSequenceInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java index 9633b14..72b93e7 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/CharSequenceInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharSequenceInspector.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ final class CharSequenceInspector implements ObjectInspector { @Override diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/CharacterInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java similarity index 93% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/CharacterInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java index 7c60228..d4463d1 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/CharacterInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/CharacterInspector.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ final class CharacterInspector implements ObjectInspector { diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectionContext.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectionContext.java similarity index 87% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/InspectionContext.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectionContext.java index 69cf99e..2da510e 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/InspectionContext.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectionContext.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ -interface InspectionContext { +public interface InspectionContext { boolean wasInspected(Object object); void markIsInspected(Object object); } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectorModule.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectorModule.java new file mode 100644 index 0000000..3c9d70c --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/InspectorModule.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.impl.inspector; + +import java.util.Arrays; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public enum InspectorModule { + INSTANCE; + + public Iterable inspectors() { + return Arrays.asList( + new CharSequenceInspector(), + new PrimitiveInspector(), + new CharacterInspector(), + new JpaLazyInspector(), + new MapInspector(), + new IterableInspector(), + new RecursionInspector() + ); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/IterableInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/IterableInspector.java similarity index 95% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/IterableInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/IterableInspector.java index 05a36eb..391cd65 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/IterableInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/IterableInspector.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ final class IterableInspector implements ObjectInspector { @Override diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/JpaLazyInspector.java similarity index 83% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/JpaLazyInspector.java index 60324b1..b9d989e 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/JpaLazyInspector.java @@ -14,20 +14,22 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; + +import pl.wavesoftware.utils.stringify.impl.jpa.JpaModule; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ final class JpaLazyInspector implements ObjectInspector { - private static final JpaLazyChecker LAZY_CHECKER = new JpaLazyCheckerFacade(); - @Override public boolean consentTo(Object candidate, InspectionContext inspectionContext) { - return LAZY_CHECKER.isLazy(candidate); + return JpaModule.INSTANCE + .lazyChecker() + .isLazy(candidate); } @Override diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/MapInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/MapInspector.java similarity index 95% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/MapInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/MapInspector.java index 4e12542..76224c7 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/MapInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/MapInspector.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; import java.util.Map; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ final class MapInspector implements ObjectInspector { diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/ObjectInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/ObjectInspector.java similarity index 89% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/ObjectInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/ObjectInspector.java index 08baef8..547a06f 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/ObjectInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/ObjectInspector.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ -interface ObjectInspector { +public interface ObjectInspector { boolean consentTo(Object candidate, InspectionContext inspectionContext); CharSequence inspect( diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/PrimitiveInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/PrimitiveInspector.java similarity index 75% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/PrimitiveInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/PrimitiveInspector.java index fca9f82..d0366bc 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/PrimitiveInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/PrimitiveInspector.java @@ -14,19 +14,17 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; +import java.time.temporal.Temporal; import java.util.Date; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ final class PrimitiveInspector implements ObjectInspector { - private static final ClassLocator TEMPORAL_CLASS_LOCATOR = - new ClassLocator("java.time.temporal.Temporal"); - @Override public boolean consentTo(Object candidate, @@ -49,14 +47,7 @@ private static boolean isPrimitive(Object object) { private static boolean isDatelike(Object object) { return object instanceof Date - || isInstanceOfTemporal(object); + || object instanceof Temporal; } - private static boolean isInstanceOfTemporal(Object candidate) { - if (TEMPORAL_CLASS_LOCATOR.isAvailable()) { - Class temporalCls = TEMPORAL_CLASS_LOCATOR.get(); - return temporalCls.isInstance(candidate); - } - return false; - } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/RecursionInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RecursionInspector.java similarity index 93% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/RecursionInspector.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RecursionInspector.java index 98d45a6..d360fea 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/RecursionInspector.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/RecursionInspector.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.inspector; import java.util.function.Function; /** * @author Krzysztof Suszynski - * @since 20.04.18 + * @since 1.0.0 */ final class RecursionInspector implements ObjectInspector { @Override diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/package-info.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/package-info.java new file mode 100644 index 0000000..7bf5e34 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/inspector/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 2018-04-18 + */ +@ReturnTypesAreNonnullByDefault +@ParametersAreNonnullByDefault +package pl.wavesoftware.utils.stringify.impl.inspector; + +import pl.wavesoftware.eid.api.ReturnTypesAreNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/HibernateLazyChecker.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/HibernateLazyChecker.java new file mode 100644 index 0000000..6b5eb45 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/HibernateLazyChecker.java @@ -0,0 +1,51 @@ +/* + * 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.jpa; + +import pl.wavesoftware.utils.stringify.impl.lang.LangModule; +import pl.wavesoftware.utils.stringify.impl.reflect.ClassInfo; +import pl.wavesoftware.utils.stringify.impl.reflect.MethodInfo; +import pl.wavesoftware.utils.stringify.impl.reflect.ReflectModule; +import pl.wavesoftware.utils.stringify.spi.JpaLazyChecker; + +import java.util.function.Supplier; + + +/** + * @author Krzysztof Suszynski + * @since 2018-04-18 + */ +final class HibernateLazyChecker implements JpaLazyChecker { + private static final ClassInfo HIBERNATE = ReflectModule.INSTANCE + .classLocator().locate("org.hibernate.Hibernate"); + private static Supplier> isInitializedMethod = + LangModule.INSTANCE.lazy(() -> + ReflectModule.INSTANCE.methodLocator() + .locate(HIBERNATE, "isInitialized", Object.class) + ); + + @Override + public boolean isSuitable(Object candidate) { + return HIBERNATE.isAvailable(); + } + + @Override + public boolean isLazy(Object candidate) { + return !isInitializedMethod.get().invoke(null, candidate); + } + +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyCheckerFacade.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckerFacade.java similarity index 68% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyCheckerFacade.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckerFacade.java index e918583..c2bdeaa 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyCheckerFacade.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckerFacade.java @@ -14,10 +14,14 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.jpa; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import pl.wavesoftware.utils.stringify.impl.lang.LangModule; +import pl.wavesoftware.utils.stringify.spi.JpaLazyChecker; + +import java.util.function.Supplier; /** * @author Krzysztof Suszynski @@ -26,26 +30,11 @@ @NoArgsConstructor(access = AccessLevel.PACKAGE) final class JpaLazyCheckerFacade implements JpaLazyChecker { private static final JpaLazyChecker NOOP_CHECKER = candidate -> false; - - private JpaLazyChecker lazyChecker; + private static final Supplier CHECKERS = + LangModule.INSTANCE.lazy(new JpaLazyCheckersSupplier(NOOP_CHECKER)); @Override public boolean isLazy(Object candidate) { - JpaLazyChecker checker = getImpl(); - return checker.isLazy(candidate); - } - - private JpaLazyChecker getImpl() { - if (lazyChecker == null) { - lazyChecker = resolveImpl(); - } - return lazyChecker; - } - - private static JpaLazyChecker resolveImpl() { - if (HibernateLazyChecker.isSuitable()) { - return new HibernateLazyChecker(); - } - return NOOP_CHECKER; + return CHECKERS.get().isLazy(candidate); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyChecker.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckers.java similarity index 76% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyChecker.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckers.java index 2304730..135c176 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/JpaLazyChecker.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckers.java @@ -14,18 +14,12 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.jpa; /** * @author Krzysztof Suszynski - * @since 2018-04-18 + * @since 2.0.0 */ -interface JpaLazyChecker { - /** - * Checks if given object is lazy - * - * @param candidate a candidate to be checked - * @return true, if object is lazy - */ +interface JpaLazyCheckers { boolean isLazy(Object candidate); } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckersImpl.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckersImpl.java new file mode 100644 index 0000000..175c0be --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckersImpl.java @@ -0,0 +1,44 @@ +/* + * 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.jpa; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import pl.wavesoftware.utils.stringify.spi.JpaLazyChecker; + +import java.util.Set; +import java.util.function.Supplier; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +final class JpaLazyCheckersImpl implements JpaLazyCheckers { + private final Supplier> checkersSupplier; + private final JpaLazyChecker fallback; + + @Override + public boolean isLazy(Object candidate) { + Set checkers = checkersSupplier.get(); + return checkers.stream() + .filter(checker -> checker.isSuitable(candidate)) + .map(checker -> checker.isLazy(candidate)) + .reduce((a, b) -> a || b) + .orElseGet(() -> fallback.isLazy(candidate)); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckersSupplier.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckersSupplier.java new file mode 100644 index 0000000..c1e4af3 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaLazyCheckersSupplier.java @@ -0,0 +1,56 @@ +/* + * 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.jpa; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import pl.wavesoftware.utils.stringify.impl.lang.LangModule; +import pl.wavesoftware.utils.stringify.spi.JpaLazyChecker; + +import java.util.Collections; +import java.util.HashSet; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.function.Supplier; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +final class JpaLazyCheckersSupplier implements Supplier { + private static final Supplier> IMPLS = LangModule.INSTANCE.lazy( + JpaLazyCheckersSupplier::computeImplementations + ); + + private final JpaLazyChecker fallback; + + @Override + public JpaLazyCheckers get() { + return new JpaLazyCheckersImpl(IMPLS, fallback); + } + + private static Set computeImplementations() { + Set impls = new HashSet<>(); + impls.add(new HibernateLazyChecker()); + ServiceLoader serviceLoader = ServiceLoader.load(JpaLazyChecker.class); + for (JpaLazyChecker checker : serviceLoader) { + impls.add(checker); + } + return Collections.unmodifiableSet(impls); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaModule.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaModule.java new file mode 100644 index 0000000..b124a40 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/JpaModule.java @@ -0,0 +1,31 @@ +/* + * 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.jpa; + +import pl.wavesoftware.utils.stringify.spi.JpaLazyChecker; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public enum JpaModule { + INSTANCE; + + public JpaLazyChecker lazyChecker() { + return new JpaLazyCheckerFacade(); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/package-info.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/package-info.java new file mode 100644 index 0000000..861c53f --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/jpa/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 2018-04-18 + */ +@ReturnTypesAreNonnullByDefault +@ParametersAreNonnullByDefault +package pl.wavesoftware.utils.stringify.impl.jpa; + +import pl.wavesoftware.eid.api.ReturnTypesAreNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/Inspectable.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/Inspectable.java new file mode 100644 index 0000000..a8044e5 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/Inspectable.java @@ -0,0 +1,21 @@ +/* + * 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; + +public interface Inspectable { + String inspect(); +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/InspectionUtils.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/InspectionUtils.java new file mode 100644 index 0000000..da07142 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/InspectionUtils.java @@ -0,0 +1,30 @@ +/* + * 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; + +final class InspectionUtils { + private InspectionUtils() { + // nothing + } + + static String safeInspect(Object object) { + if (object instanceof Inspectable) { + return ((Inspectable) object).inspect(); + } + return object.getClass().getName() + '@' + Integer.toHexString(object.hashCode()); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/LangModule.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/LangModule.java new file mode 100644 index 0000000..e962ecf --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/LangModule.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.impl.lang; + +import java.util.function.Supplier; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public enum LangModule { + INSTANCE; + + public Supplier lazy(Supplier supplier) { + return Lazy.of(supplier); + } + + public SafeInspector safeInspector() { + return InspectionUtils::safeInspect; + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/Lazy.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/Lazy.java new file mode 100644 index 0000000..1dda798 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/Lazy.java @@ -0,0 +1,128 @@ +/* + * 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 java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Objects; +import java.util.function.Supplier; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +final class Lazy implements Supplier, Serializable { + private static final long serialVersionUID = 20190709223414L; + + /** + * @see + * Doublde checked locking + */ + private transient volatile Supplier supplier; + + /** + * Will behave as a volatile in reality, because a supplier volatile read will update + * all fields. + * + * @see + * What does volatile do? + */ + private T value; + + // should not be called directly + private Lazy(Supplier supplier) { + this.supplier = supplier; + } + + /** + * Creates a {@code Lazy} that requests its value from a given {@code Supplier}. + * The supplier is asked only once, the value is memoized. + * + * @param type of the lazy value + * @param supplier A supplier + * @return A new instance of Lazy + */ + @SuppressWarnings("unchecked") + static Lazy of(Supplier supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + if (supplier instanceof Lazy) { + return (Lazy) supplier; + } else { + return new Lazy<>(supplier); + } + } + + /** + * Evaluates this lazy value and caches it, when called the first time. + * On subsequent calls, returns the cached value. + * + * @return the lazy evaluated value + */ + @Override + public T get() { + return (supplier == null) ? value : computeValue(); + } + + private synchronized T computeValue() { + final Supplier s = supplier; + if (s != null) { + value = s.get(); + supplier = null; + } + return value; + } + + /** + * Checks, if this lazy value is evaluated. + *

+ * Note: A value is internally evaluated (once) by calling {@link #get()}. + * + * @return true, if the value is evaluated, false otherwise. + * @throws UnsupportedOperationException if this value is undefined + */ + private boolean isEvaluated() { + return supplier == null; + } + + @Override + public boolean equals(Object obj) { + return (obj == this) || (obj instanceof Lazy && Objects.equals(((Lazy) obj).get(), get())); + } + + @Override + public int hashCode() { + return Objects.hashCode(get()); + } + + @Override + public String toString() { + return "Lazy(" + (!isEvaluated() ? "?" : value) + ")"; + } + + /** + * Ensures that the value is evaluated before serialization. + * + * @param stream An object serialization stream. + * @throws java.io.IOException If an error occurs writing to the stream. + */ + private void writeObject(ObjectOutputStream stream) throws IOException { + // evaluates the lazy value if it isn't evaluated yet! + get(); + stream.defaultWriteObject(); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/SafeInspector.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/SafeInspector.java new file mode 100644 index 0000000..b1ec6ad --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/SafeInspector.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.impl.lang; + +/** + * @author Krzysztof Suszynski + * @since 0.1.0 + */ +public interface SafeInspector { + String inspect(Object object); +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/package-info.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/package-info.java new file mode 100644 index 0000000..fac934e --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/lang/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 2018-04-18 + */ +@ReturnTypesAreNonnullByDefault +@ParametersAreNonnullByDefault +package pl.wavesoftware.utils.stringify.impl.lang; + +import pl.wavesoftware.eid.api.ReturnTypesAreNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassInfo.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassInfo.java new file mode 100644 index 0000000..7411bda --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassInfo.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.impl.reflect; + +import pl.wavesoftware.eid.exceptions.EidIllegalStateException; + +import java.util.Optional; + +/** + * Represents a information about a given class + * + * @author Krzysztof Suszynski + * @since 2.0.0 + * @param a type of a class + */ +public interface ClassInfo { + /** + * Provides a optional class reference. Reference is {@link Optional#empty()} if target + * class isn't found. + * + * @return an optional class reference + */ + Optional> maybeClass(); + + default Class get() { + return maybeClass() + .orElseThrow(() -> new EidIllegalStateException("20190712:012032")); + } + + default boolean isAvailable() { + return maybeClass().isPresent(); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/ClassLocator.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassInfoImpl.java similarity index 52% rename from src/main/java/pl/wavesoftware/utils/stringify/impl/ClassLocator.java rename to src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassInfoImpl.java index fc5c669..ea0a4ae 100644 --- a/src/main/java/pl/wavesoftware/utils/stringify/impl/ClassLocator.java +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassInfoImpl.java @@ -14,48 +14,30 @@ * limitations under the License. */ -package pl.wavesoftware.utils.stringify.impl; +package pl.wavesoftware.utils.stringify.impl.reflect; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import javax.annotation.Nullable; - -import static pl.wavesoftware.eid.utils.EidPreconditions.checkNotNull; +import java.util.Optional; /** * @author Krzysztof Suszynski - * @since 2018-04-18 + * @since 2.0.0 */ @RequiredArgsConstructor(access = AccessLevel.PACKAGE) -final class ClassLocator { - - private final String fqcn; - private Class targetClass; - private boolean located; +final class ClassInfoImpl implements ClassInfo { - boolean isAvailable() { - return getTargetClass() != null; - } + @Nullable + private final Class cls; - Class get() { - return checkNotNull(getTargetClass(), "20180418:230411"); + static ClassInfo empty() { + return new ClassInfoImpl<>(null); } - @SuppressWarnings({"squid:S1166", "squid:S2658"}) - @Nullable - private Class getTargetClass() { - if (!located) { - ClassLoader cl = Thread - .currentThread() - .getContextClassLoader(); - try { - targetClass = Class.forName(fqcn, false, cl); - } catch (ClassNotFoundException e) { - // do nothing - } - located = true; - } - return targetClass; + @Override + public Optional> maybeClass() { + return Optional.ofNullable(cls); } } diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLoaderUtils.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLoaderUtils.java new file mode 100644 index 0000000..df2affd --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLoaderUtils.java @@ -0,0 +1,44 @@ +/* + * 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.reflect; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +final class ClassLoaderUtils { + + private ClassLoaderUtils() { + // not reachable + } + + private static final Logger LOGGER = LoggerFactory.getLogger(ClassLoaderUtils.class); + static ClassLoader getDefaultClassLoader() { + try { + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + if (contextClassLoader != null) { + return contextClassLoader; + } + } catch (RuntimeException ex) { + LOGGER.trace("Silenced", ex); + } + return ClassLoader.getSystemClassLoader(); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLocator.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLocator.java new file mode 100644 index 0000000..72aea3d --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLocator.java @@ -0,0 +1,34 @@ +/* + * 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.reflect; + +/** + * Locates class by their fully qualified class name. + * + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface ClassLocator { + /** + * Locates a class by their fully qualified class name. + * + * @param fqcn a fully qualified class name + * @param a type of a class + * @return an info about a class + */ + ClassInfo locate(String fqcn); +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLocatorImpl.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLocatorImpl.java new file mode 100644 index 0000000..7b5d2b4 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ClassLocatorImpl.java @@ -0,0 +1,46 @@ +/* + * 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.reflect; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +final class ClassLocatorImpl implements ClassLocator { + + private static final Logger LOGGER = LoggerFactory.getLogger(ClassLocatorImpl.class); + + private final ClassLoader classLoader; + + @Override + @SuppressWarnings({"squid:S1166", "squid:S2658", "unchecked"}) + public ClassInfo locate(String fqcn) { + try { + Class targetClass = (Class) Class.forName(fqcn, false, classLoader); + return new ClassInfoImpl<>(targetClass); + } catch (ClassNotFoundException ex) { + LOGGER.trace("Silenced exception", ex); + return ClassInfoImpl.empty(); + } + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodInfo.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodInfo.java new file mode 100644 index 0000000..40985d3 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodInfo.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.impl.reflect; + +import javax.annotation.Nullable; + +/** + * Represents a method that can be invoked + * + * @author Krzysztof Suszynski + * @since 2.0.0 + * @param a type of method returns + */ +public interface MethodInfo { + /** + * Invokes a method with parameters given. + * + * @param target a target object, if {@code null} method will be called statically. + * @param parameters a parameters for a method + * @return a method return value + */ + T invoke(@Nullable Object target, Object... parameters); +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodInfoImpl.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodInfoImpl.java new file mode 100644 index 0000000..71543e1 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodInfoImpl.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.impl.reflect; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import pl.wavesoftware.eid.utils.UnsafeSupplier; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.function.Supplier; + +import static pl.wavesoftware.eid.utils.EidExecutions.tryToExecute; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +final class MethodInfoImpl implements MethodInfo { + + private final Supplier methodSupplier; + + @Override + @SuppressWarnings("unchecked") + public T invoke(@Nullable Object target, Object... parameters) { + return tryToExecute(new UnsafeSupplier() { + @Override + @Nonnull + public T get() throws InvocationTargetException, IllegalAccessException { + return (T) methodSupplier.get().invoke(target, parameters); + } + }, + "20180418:231314" + ); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodLocator.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodLocator.java new file mode 100644 index 0000000..285a9da --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodLocator.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.impl.reflect; + +/** + * Locates a method withing a given class info + * + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public interface MethodLocator { + /** + * Return a method info if described method exists, throws runtime exception otherwise. + * + * @param classInfo a class info + * @param methodName a method name + * @param parametersTypes parameter types for a method + * @param method return type + * @param class info type + * @return a method info + */ + MethodInfo locate(ClassInfo classInfo, String methodName, Class... parametersTypes); +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodLocatorImpl.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodLocatorImpl.java new file mode 100644 index 0000000..1fee634 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/MethodLocatorImpl.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.impl.reflect; + +import pl.wavesoftware.eid.utils.UnsafeSupplier; + +import javax.annotation.Nonnull; +import java.lang.reflect.Method; + +import static pl.wavesoftware.eid.utils.EidExecutions.tryToExecute; + +/** + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +final class MethodLocatorImpl implements MethodLocator { + @Override + public MethodInfo locate( + ClassInfo classInfo, + String methodName, + Class... parametersTypes + ) { + return new MethodInfoImpl<>(() -> + tryToExecute(new UnsafeSupplier() { + @Override + @Nonnull + public Method get() throws NoSuchMethodException { + return classInfo.get().getDeclaredMethod(methodName, parametersTypes); + } + }, "20180418:231029") + ); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ReflectModule.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ReflectModule.java new file mode 100644 index 0000000..5a3486a --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/ReflectModule.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.impl.reflect; + +import static pl.wavesoftware.utils.stringify.impl.reflect.ClassLoaderUtils.getDefaultClassLoader; + +/** + * Reflect module entry point + * + * @author Krzysztof Suszynski + * @since 2.0.0 + */ +public enum ReflectModule { + INSTANCE; + + /** + * Return a class locator + * + * @return a class locator + */ + public ClassLocator classLocator() { + return new ClassLocatorImpl(getDefaultClassLoader()); + } + + /** + * Return a method locator + * + * @return a method locator + */ + public MethodLocator methodLocator() { + return new MethodLocatorImpl(); + } +} diff --git a/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/package-info.java b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/package-info.java new file mode 100644 index 0000000..5f1ac35 --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/impl/reflect/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 2018-04-18 + */ +@ReturnTypesAreNonnullByDefault +@ParametersAreNonnullByDefault +package pl.wavesoftware.utils.stringify.impl.reflect; + +import pl.wavesoftware.eid.api.ReturnTypesAreNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/Configurator.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/Configurator.java old mode 100755 new mode 100644 diff --git a/src/main/java/pl/wavesoftware/utils/stringify/spi/JpaLazyChecker.java b/src/main/java/pl/wavesoftware/utils/stringify/spi/JpaLazyChecker.java new file mode 100644 index 0000000..697fe7c --- /dev/null +++ b/src/main/java/pl/wavesoftware/utils/stringify/spi/JpaLazyChecker.java @@ -0,0 +1,45 @@ +/* + * 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; + +/** + * Checks a field, if it isn't loaded from persistence. If checker returns {@code true}, + * Stringify shouldn't inspect that field, but will display a lazy indicating + * representation, for ex.: {@code "⁂Lazy"}. + * + * @author Krzysztof Suszynski + * @since 1.0.0 + */ +public interface JpaLazyChecker { + /** + * Checks if given object is lazy + * + * @param candidate a candidate to be checked + * @return true, if object is lazy + */ + boolean isLazy(Object candidate); + + /** + * Returns {@code true}, if this checker is suitable to check given candidate. + * + * @param candidate a candidate object to be checked. + * @return true, if this checker can be used to determine if candidate is lazy. + */ + default boolean isSuitable(Object candidate) { + return true; + } +} diff --git a/src/test/java/pl/wavesoftware/utils/stringify/Acme.java b/src/test/java/pl/wavesoftware/utils/stringify/Acme.java old mode 100755 new mode 100644 diff --git a/src/test/java/pl/wavesoftware/utils/stringify/StringifyIT.java b/src/test/java/pl/wavesoftware/utils/stringify/StringifyIT.java old mode 100755 new mode 100644 diff --git a/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java b/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java old mode 100755 new mode 100644 index cccee51..431ac9a --- a/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java +++ b/src/test/java/pl/wavesoftware/utils/stringify/StringifyTest.java @@ -189,10 +189,10 @@ void onPersonWithCustomPerdicateLogic() { stringifier.beanFactory(productionBeanFactory); // when - String productionResult = stringifier.toString(); + CharSequence productionResult = stringifier.stringify(); // then - assertThat(productionResult).isEqualTo( + assertThat(productionResult).isEqualToIgnoringWhitespace( ", childs=[], " + "account=⁂Lazy>" @@ -237,10 +237,10 @@ private static boolean inspectionPointValue(final InspectionPoint inspectionPoin ); } - private StaticBeanFactory getBeanFactory(IsInDevelopment isInDevelopmentFalse) { + private StaticBeanFactory getBeanFactory(IsInDevelopment isInDevelopment) { return new StaticBeanFactory( new AbstractMap.SimpleImmutableEntry<>( - IsInDevelopment.class, isInDevelopmentFalse + IsInDevelopment.class, isInDevelopment ) ); } diff --git a/src/test/java/pl/wavesoftware/utils/stringify/TestBeanFactory.java b/src/test/java/pl/wavesoftware/utils/stringify/TestBeanFactory.java old mode 100755 new mode 100644 diff --git a/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java b/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java index d067ff6..8d37adb 100644 --- a/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java +++ b/src/test/java/pl/wavesoftware/utils/stringify/TestRepository.java @@ -69,7 +69,7 @@ Person createPerson() { parent.setIgnored("Ignore it!"); child.setId(15); child.setParent(parent); - child.setChilds(new ArrayList()); + child.setChilds(new ArrayList<>()); child.setAccount(a1); child.setPassword("rewq1234$#@!"); child.setIgnored("Dump this"); diff --git a/src/test/java/pl/wavesoftware/utils/stringify/TestingConfigurator.java b/src/test/java/pl/wavesoftware/utils/stringify/TestingConfigurator.java old mode 100755 new mode 100644 diff --git a/src/test/java/pl/wavesoftware/utils/stringify/UnlessContainsSecret.java b/src/test/java/pl/wavesoftware/utils/stringify/UnlessContainsSecret.java old mode 100755 new mode 100644 diff --git a/src/test/resources/META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator b/src/test/resources/META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator old mode 100755 new mode 100644