Skip to content

Commit

Permalink
Refactor move DecomposedContainerValueFactory into api module (#690)
Browse files Browse the repository at this point in the history
  • Loading branch information
seongahjo authored Jun 29, 2023
1 parent 47476b9 commit 1316d6d
Show file tree
Hide file tree
Showing 16 changed files with 243 additions and 106 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* 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 com.navercorp.fixturemonkey.api.container;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

/**
* It is used for decomposing the custom container.
*/
@API(since = "0.6.0", status = Status.EXPERIMENTAL)
public class DecomposableJavaContainer {
/**
* It should be one of these Java Container type.
* For example, the implementations of {@link Iterable}, {@link java.util.List}, {@link java.util.Set}, etc.
* {@link Iterable}, {@link java.util.Map}, {@link java.util.Map.Entry}, {@link java.util.Optional}, Array as well.
*/
private final Object javaContainer;
/**
* It is a size of {@link #javaContainer}.
*/
private final int size;

public DecomposableJavaContainer(Object javaContainer, int size) {
this.javaContainer = javaContainer;
this.size = size;
}

public Object getJavaContainer() {
return javaContainer;
}

public int getSize() {
return size;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* 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 com.navercorp.fixturemonkey.api.container;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

/**
* Generate a {@link DecomposableJavaContainer} from the container.
*/
@API(since = "0.6.0", status = Status.EXPERIMENTAL)
@FunctionalInterface
public interface DecomposedContainerValueFactory {
/**
* Generates a {@link DecomposableJavaContainer} from the {@code container}.
* @param container to be converted into {@link DecomposableJavaContainer}
* @return DecomposableJavaContainer
*/
DecomposableJavaContainer from(Object container);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* 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 com.navercorp.fixturemonkey.api.container;

import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.stream.Stream;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.api.collection.IteratorCache;
import com.navercorp.fixturemonkey.api.collection.StreamCache;

/**
* A default implementation of {@link DecomposedContainerValueFactory}.
*/
@API(since = "0.6.0", status = Status.EXPERIMENTAL)
public final class DefaultDecomposedContainerValueFactory implements DecomposedContainerValueFactory {
private final DecomposedContainerValueFactory additionalDecomposedContainerValueFactory;

public DefaultDecomposedContainerValueFactory(
DecomposedContainerValueFactory additionalDecomposedContainerValueFactory
) {
this.additionalDecomposedContainerValueFactory = additionalDecomposedContainerValueFactory;
}

@Override
public DecomposableJavaContainer from(Object container) {
Class<?> actualType = container.getClass();

if (Iterable.class.isAssignableFrom(actualType)) {
Iterator<?> iterator = ((Iterable<?>)container).iterator();
List<?> list = IteratorCache.getList(iterator);
return new DecomposableJavaContainer(list, list.size());
} else if (Iterator.class.isAssignableFrom(actualType)) {
Iterator<?> iterator = ((Iterator<?>)container);
List<?> list = IteratorCache.getList(iterator);
return new DecomposableJavaContainer(list, list.size());
} else if (Stream.class.isAssignableFrom(actualType)) {
List<?> javaContainer = StreamCache.getList((Stream<?>)container);
return new DecomposableJavaContainer(javaContainer, javaContainer.size());
} else if (actualType.isArray()) {
return new DecomposableJavaContainer(container, Array.getLength(container));
} else if (Map.class.isAssignableFrom(actualType)) {
Map<?, ?> map = (Map<?, ?>)container;
return new DecomposableJavaContainer(container, map.size());
} else if (Map.Entry.class.isAssignableFrom(actualType)) {
return new DecomposableJavaContainer(container, 1);
} else if (isOptional(actualType)) {
return new DecomposableJavaContainer(container, 1);
}

return additionalDecomposedContainerValueFactory.from(container);
}

private boolean isOptional(Class<?> type) {
return Optional.class.isAssignableFrom(type)
|| OptionalInt.class.isAssignableFrom(type)
|| OptionalLong.class.isAssignableFrom(type)
|| OptionalDouble.class.isAssignableFrom(type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.api.customizer.FixtureCustomizer;
import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfoGenerator;
import com.navercorp.fixturemonkey.api.generator.ArbitraryGenerator;
Expand Down Expand Up @@ -121,6 +122,7 @@ public final class GenerateOptions {
@Deprecated // It would be removed in 0.6.0
private final List<MatcherOperator<FixtureCustomizer>> arbitraryCustomizers;
private final ArbitraryValidator defaultArbitraryValidator;
private final DecomposedContainerValueFactory decomposedContainerValueFactory;

@SuppressWarnings("rawtypes")
public GenerateOptions(
Expand All @@ -138,7 +140,8 @@ public GenerateOptions(
List<MatcherOperator<ArbitraryGenerator>> arbitraryGenerators,
ArbitraryGenerator defaultArbitraryGenerator,
List<MatcherOperator<FixtureCustomizer>> arbitraryCustomizers,
ArbitraryValidator defaultArbitraryValidator
ArbitraryValidator defaultArbitraryValidator,
DecomposedContainerValueFactory decomposedContainerValueFactory
) {
this.propertyGenerators = propertyGenerators;
this.defaultPropertyGenerator = defaultPropertyGenerator;
Expand All @@ -155,6 +158,7 @@ public GenerateOptions(
this.defaultArbitraryGenerator = defaultArbitraryGenerator;
this.arbitraryCustomizers = arbitraryCustomizers;
this.defaultArbitraryValidator = defaultArbitraryValidator;
this.decomposedContainerValueFactory = decomposedContainerValueFactory;
}

public static GenerateOptionsBuilder builder() {
Expand Down Expand Up @@ -280,6 +284,10 @@ public ArbitraryValidator getDefaultArbitraryValidator() {
return defaultArbitraryValidator;
}

public DecomposedContainerValueFactory getDecomposedContainerValueFactory() {
return decomposedContainerValueFactory;
}

public GenerateOptionsBuilder toBuilder() {
return builder()
.defaultPropertyGenerator(defaultPropertyGenerator)
Expand Down Expand Up @@ -324,7 +332,6 @@ private static List<MatcherOperator<ContainerPropertyGenerator>> getDefaultConta
&& new SingleGenericTypeMatcher().match(property),
OptionalContainerPropertyGenerator.INSTANCE
),

MatcherOperator.exactTypeMatchOperator(
OptionalInt.class,
OptionalContainerPropertyGenerator.INSTANCE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.api.container.DefaultDecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.api.customizer.FixtureCustomizer;
import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo;
import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfoGenerator;
Expand Down Expand Up @@ -87,6 +89,7 @@ public final class GenerateOptionsBuilder {
private UnaryOperator<NullInjectGenerator> defaultNullInjectGeneratorOperator = it -> it;
private ArbitraryValidator defaultArbitraryValidator = (obj) -> {
};
private DecomposedContainerValueFactory additionalDecomposedContainerValueFactory = null;

GenerateOptionsBuilder() {
}
Expand Down Expand Up @@ -504,6 +507,13 @@ public GenerateOptionsBuilder defaultArbitraryValidator(ArbitraryValidator arbit
return this;
}

public GenerateOptionsBuilder additionalDecomposedContainerValueFactory(
DecomposedContainerValueFactory additionalDecomposedContainerValueFactory
) {
this.additionalDecomposedContainerValueFactory = additionalDecomposedContainerValueFactory;
return this;
}

public GenerateOptions build() {
ObjectPropertyGenerator defaultObjectPropertyGenerator = defaultIfNull(
this.defaultObjectPropertyGenerator,
Expand Down Expand Up @@ -537,6 +547,10 @@ public GenerateOptions build() {
ArbitraryGenerator defaultArbitraryGenerator =
defaultIfNull(this.defaultArbitraryGenerator, this.javaDefaultArbitraryGeneratorBuilder::build);

DecomposedContainerValueFactory decomposedContainerValueFactory = new DefaultDecomposedContainerValueFactory(
additionalDecomposedContainerValueFactory
);

return new GenerateOptions(
this.propertyGenerators,
this.defaultPropertyGenerator,
Expand All @@ -552,7 +566,8 @@ public GenerateOptions build() {
this.arbitraryGenerators,
defaultArbitraryGenerator,
this.arbitraryCustomizers,
this.defaultArbitraryValidator
this.defaultArbitraryValidator,
decomposedContainerValueFactory
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ public <T> DefaultArbitraryBuilder<T> giveMeBuilder(TypeReference<T> type) {
new AtomicInteger(),
manipulateOptions.getDefaultMonkeyExpressionFactory(),
traverser,
manipulateOptions.getDecomposedContainerValueFactory()
generateOptions.getDecomposedContainerValueFactory()
);
return new DefaultArbitraryBuilder<>(
manipulateOptions,
generateOptions,
rootProperty,
new ArbitraryResolver(
traverser,
Expand All @@ -134,7 +134,7 @@ public <T> DefaultArbitraryBuilder<T> giveMeBuilder(T value) {
new AtomicInteger(),
manipulateOptions.getDefaultMonkeyExpressionFactory(),
traverser,
manipulateOptions.getDecomposedContainerValueFactory()
generateOptions.getDecomposedContainerValueFactory()
);
ArbitraryBuilderContext context = new ArbitraryBuilderContext();

Expand All @@ -143,7 +143,7 @@ public <T> DefaultArbitraryBuilder<T> giveMeBuilder(T value) {
context.addManipulator(arbitraryManipulator);

return new DefaultArbitraryBuilder<>(
manipulateOptions,
generateOptions,
new RootProperty(new LazyAnnotatedType<>(() -> value)),
new ArbitraryResolver(
traverser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ public <T> FixtureMonkeyBuilder interfaceImplements(
}

public FixtureMonkey build() {
manipulateOptionsBuilder.additionalDecomposedContainerValueFactory(
generateOptionsBuilder.additionalDecomposedContainerValueFactory(
obj -> {
Class<?> actualType = obj.getClass();
for (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import net.jqwik.api.Arbitrary;

import com.navercorp.fixturemonkey.ArbitraryBuilder;
import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo;
import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary;
import com.navercorp.fixturemonkey.api.matcher.MatcherOperator;
Expand All @@ -44,7 +45,6 @@
import com.navercorp.fixturemonkey.customizer.Values.Just;
import com.navercorp.fixturemonkey.expression.MonkeyExpressionFactory;
import com.navercorp.fixturemonkey.resolver.ArbitraryBuilderContext;
import com.navercorp.fixturemonkey.resolver.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.resolver.DefaultArbitraryBuilder;
import com.navercorp.fixturemonkey.tree.ArbitraryTraverser;
import com.navercorp.fixturemonkey.tree.NextNodePredicate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@

import net.jqwik.api.Arbitraries;

import com.navercorp.fixturemonkey.api.container.DecomposableJavaContainer;
import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo;
import com.navercorp.fixturemonkey.api.generator.ContainerProperty;
import com.navercorp.fixturemonkey.api.property.MapEntryElementProperty;
import com.navercorp.fixturemonkey.api.property.Property;
import com.navercorp.fixturemonkey.api.type.Types;
import com.navercorp.fixturemonkey.resolver.DecomposableContainerValue;
import com.navercorp.fixturemonkey.resolver.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.tree.ArbitraryTraverser;
import com.navercorp.fixturemonkey.tree.IdentityNodeResolver;
import com.navercorp.fixturemonkey.tree.ObjectNode;
Expand Down Expand Up @@ -100,9 +100,9 @@ private void setValue(ObjectNode objectNode, @Nullable Object value) {

ContainerProperty containerProperty = objectNode.getArbitraryProperty().getContainerProperty();
if (containerProperty != null) {
DecomposableContainerValue decomposableContainerValue = decomposedContainerValueFactory.from(value);
Object containerValue = decomposableContainerValue.getContainer();
int decomposedContainerSize = decomposableContainerValue.getSize();
DecomposableJavaContainer decomposableJavaContainer = decomposedContainerValueFactory.from(value);
Object containerValue = decomposableJavaContainer.getJavaContainer();
int decomposedContainerSize = decomposableJavaContainer.getSize();

boolean forced = containerProperty.getContainerInfo().getManipulatingSequence() == null
|| sequence > containerProperty.getContainerInfo().getManipulatingSequence();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@

import net.jqwik.api.Arbitrary;

import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary;
import com.navercorp.fixturemonkey.resolver.DecomposedContainerValueFactory;
import com.navercorp.fixturemonkey.tree.ArbitraryTraverser;
import com.navercorp.fixturemonkey.tree.ObjectNode;

Expand Down
Loading

0 comments on commit 1316d6d

Please sign in to comment.