Skip to content

Commit

Permalink
#616 first passing test
Browse files Browse the repository at this point in the history
  • Loading branch information
bartoszwalacik committed Jan 14, 2018
1 parent 7d6a852 commit fc47037
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 47 deletions.
36 changes: 20 additions & 16 deletions javers-core/src/main/java/org/javers/core/JaversBuilder.java
Expand Up @@ -194,7 +194,7 @@ public JaversBuilder registerEntity(Class<?> entityClass) {
*/
public JaversBuilder registerValueObject(Class<?> valueObjectClass) {
argumentIsNotNull(valueObjectClass);
registerClassDefinition(new ValueObjectDefinition(valueObjectClass));
registerType(new ValueObjectDefinition(valueObjectClass));
return this;
}

Expand Down Expand Up @@ -225,7 +225,16 @@ public JaversBuilder registerValueObject(Class<?> valueObjectClass) {
*/
public JaversBuilder registerEntity(EntityDefinition entityDefinition){
argumentIsNotNull(entityDefinition);
registerClassDefinition(entityDefinition);
return registerType(entityDefinition);
}

/**
* Generic version of {@link #registerEntity(EntityDefinition)} and
* {@link #registerValueObject(ValueObjectDefinition)}
*/
public JaversBuilder registerType(ClientsClassDefinition clientsClassDefinition) {
argumentIsNotNull(clientsClassDefinition);
clientsClassDefinitions.put(clientsClassDefinition.getBaseJavaClass(), clientsClassDefinition);
return this;
}

Expand Down Expand Up @@ -254,13 +263,13 @@ public JaversBuilder registerEntity(EntityDefinition entityDefinition){
*/
public JaversBuilder registerValueObject(ValueObjectDefinition valueObjectDefinition) {
argumentIsNotNull(valueObjectDefinition);
registerClassDefinition(valueObjectDefinition);
registerType(valueObjectDefinition);
return this;
}

/**
* Comma separated list of packages.<br/>
* Allows you to registerClassDefinition all your classes with &#64;{@link TypeName} annotation
* Allows you to registerType all your classes with &#64;{@link TypeName} annotation
* in order to use them in all kinds of JQL queries<br/>
* (without getting TYPE_NAME_NOT_FOUND exception).
*
Expand Down Expand Up @@ -314,13 +323,13 @@ public JaversBuilder scanTypeName(Class userType){
*
* Values are compared using default {@link Object#equals(Object)}.
* If you don't want to use it,
* registerClassDefinition a custom value comparator with {@link #registerValue(Class, CustomValueComparator)}.
* registerType a custom value comparator with {@link #registerValue(Class, CustomValueComparator)}.
*
* @see <a href="http://javers.org/documentation/domain-configuration/#ValueType">http://javers.org/documentation/domain-configuration/#ValueType</a>
*/
public JaversBuilder registerValue(Class<?> valueClass) {
argumentIsNotNull(valueClass);
registerClassDefinition(new ValueDefinition(valueClass));
registerType(new ValueDefinition(valueClass));
return this;
}

Expand Down Expand Up @@ -360,7 +369,7 @@ public <T> JaversBuilder registerValue(Class<T> valueClass, CustomValueComparato
argumentsAreNotNull(valueClass, customValueComparator);

if (!clientsClassDefinitions.containsKey(valueClass)){
registerClassDefinition(new ValueDefinition(valueClass));
registerType(new ValueDefinition(valueClass));
}
ValueDefinition def = getClassDefinition(valueClass);
def.setCustomValueComparator(customValueComparator);
Expand Down Expand Up @@ -428,7 +437,7 @@ public <T> JaversBuilder registerValueWithCustomToString(Class<T> valueClass, Fu
argumentsAreNotNull(valueClass, toString);

if (!clientsClassDefinitions.containsKey(valueClass)){
registerClassDefinition(new ValueDefinition(valueClass));
registerType(new ValueDefinition(valueClass));
}
ValueDefinition def = getClassDefinition(valueClass);
def.setToStringFunction((Function)toString);
Expand All @@ -446,7 +455,7 @@ public <T> JaversBuilder registerValueWithCustomToString(Class<T> valueClass, Fu
*/
public JaversBuilder registerIgnoredClass(Class<?> ignoredClass) {
argumentIsNotNull(ignoredClass);
registerClassDefinition(new IgnoredTypeDefinition(ignoredClass));
registerType(new IgnoredTypeDefinition(ignoredClass));
return this;
}

Expand Down Expand Up @@ -611,7 +620,7 @@ public JaversBuilder withObjectAccessHook(ObjectAccessHook objectAccessHook) {
* @see CustomType
*/
public <T> JaversBuilder registerCustomComparator(CustomPropertyComparator<T, ?> comparator, Class<T> customType){
registerClassDefinition(new CustomDefinition(customType));
registerType(new CustomDefinition(customType));
bindComponent(comparator, new CustomToNativeAppenderAdapter(comparator, customType));
return this;
}
Expand Down Expand Up @@ -719,7 +728,7 @@ private void bootDateTimeProvider() {

private void bootRepository(){
if (repository == null){
logger.info("using fake InMemoryRepository, registerClassDefinition actual implementation via JaversBuilder.registerJaversRepository()");
logger.info("using fake InMemoryRepository, registerType actual implementation via JaversBuilder.registerJaversRepository()");
addModule(new InMemoryRepositoryModule(getContainer()));
repository = getContainerComponent(JaversRepository.class);
} else {
Expand All @@ -734,9 +743,4 @@ private void bootRepository(){
private <T extends ClientsClassDefinition> T getClassDefinition(Class<?> baseJavaClass) {
return (T)clientsClassDefinitions.get(baseJavaClass);
}

private void registerClassDefinition(ClientsClassDefinition clientsClassDefinition) {
argumentIsNotNull(clientsClassDefinition);
clientsClassDefinitions.put(clientsClassDefinition.getBaseJavaClass(), clientsClassDefinition);
}
}
Expand Up @@ -21,7 +21,7 @@
* @author bartosz walacik
*/
public abstract class ClientsClassDefinition {
private final List<String> includedProperties;
private final List<String> whitelistedProperties;
private final Class<?> baseJavaClass;
private final List<String> ignoredProperties;
private final Optional<String> typeName;
Expand All @@ -35,20 +35,20 @@ public abstract class ClientsClassDefinition {
}

ClientsClassDefinition(ClientsClassDefinitionBuilder builder) {
this(builder.getClazz(), builder.getIgnoredProperties(), builder.getTypeName(), builder.getIncludedProperties());
this(builder.getClazz(), builder.getIgnoredProperties(), builder.getTypeName(), builder.getWhitelistedProperties());
}

private ClientsClassDefinition(Class<?> baseJavaClass, List<String> ignoredProperties, Optional<String> typeName, List<String> includedProperties) {
argumentsAreNotNull(baseJavaClass, typeName, ignoredProperties, includedProperties);
private ClientsClassDefinition(Class<?> baseJavaClass, List<String> ignoredProperties, Optional<String> typeName, List<String> whitelistedProperties) {
argumentsAreNotNull(baseJavaClass, typeName, ignoredProperties, whitelistedProperties);

Validate.argumentCheck(!(includedProperties.size() > 0 && ignoredProperties.size() > 0),
Validate.argumentCheck(!(whitelistedProperties.size() > 0 && ignoredProperties.size() > 0),
"Can't create ClientsClassDefinition for " + baseJavaClass.getSimpleName() +
", you can't define both ignored and included properties");
", you can't define both ignored and whitelisted properties");

this.baseJavaClass = baseJavaClass;
this.ignoredProperties = new ArrayList<>(ignoredProperties);
this.typeName = typeName;
this.includedProperties = new ArrayList<>(includedProperties);
this.whitelistedProperties = new ArrayList<>(whitelistedProperties);
}

public Class<?> getBaseJavaClass() {
Expand Down Expand Up @@ -80,13 +80,23 @@ public List<String> getIgnoredProperties() {
return Collections.unmodifiableList(ignoredProperties);
}

public boolean hasIgnoredProperties() {
return !ignoredProperties.isEmpty();
}

public boolean hasWhitelistedProperties() {
return !whitelistedProperties.isEmpty();
}

/**
* If this list is defined, only given properties are
* If whitelisted properties list is defined, only those props are
* visible for JaVers, and the rest is ignored.
* Included properties can be defined only if ignored properties are not defined.
* <br/>
*
* Whitelisted props can be defined only if ignored properties are not defined.
*/
public List<String> getIncludedProperties() {
return Collections.unmodifiableList(includedProperties);
public List<String> getWhitelistedProperties() {
return Collections.unmodifiableList(whitelistedProperties);
}

public Optional<String> getTypeName() {
Expand Down
Expand Up @@ -14,7 +14,7 @@
public abstract class ClientsClassDefinitionBuilder<T extends ClientsClassDefinitionBuilder> {
private Class<?> clazz;
private List<String> ignoredProperties = Collections.emptyList();
private List<String> includedProperties = Collections.emptyList();
private List<String> whitelistedProperties = Collections.emptyList();
private Optional<String> typeName = Optional.empty();

ClientsClassDefinitionBuilder(Class<?> clazz) {
Expand All @@ -39,11 +39,11 @@ public T withIgnoredProperties(List<String> ignoredProperties) {
}

/**
* See {@link ClientsClassDefinition#getIncludedProperties()}
* See {@link ClientsClassDefinition#getWhitelistedProperties()}
*/
public T withIncludedProperties(List<String> includedProperties) {
Validate.argumentIsNotNull(includedProperties);
this.ignoredProperties = includedProperties;
public T withWhitelistedProperties(List<String> whitelistedProperties) {
Validate.argumentIsNotNull(whitelistedProperties);
this.whitelistedProperties = whitelistedProperties;
return (T) this;
}

Expand All @@ -61,19 +61,19 @@ public ClientsClassDefinition build() {
throw new RuntimeException("not implemented");
}

public Class<?> getClazz() {
Class<?> getClazz() {
return clazz;
}

public List<String> getIgnoredProperties() {
List<String> getIgnoredProperties() {
return ignoredProperties;
}

public List<String> getIncludedProperties() {
return includedProperties;
List<String> getWhitelistedProperties() {
return whitelistedProperties;
}

public Optional<String> getTypeName() {
Optional<String> getTypeName() {
return typeName;
}

Expand Down
Expand Up @@ -46,11 +46,11 @@ public EntityDefinition build() {
return new EntityDefinition(this);
}

public Optional<String> getIdPropertyName() {
Optional<String> getIdPropertyName() {
return idPropertyName;
}

public boolean isShallowReference() {
boolean isShallowReference() {
return shallowReference;
}
}
Expand Up @@ -35,7 +35,7 @@ public ValueObjectDefinition build() {
return new ValueObjectDefinition(this);
}

public boolean isDefault() {
boolean isDefault() {
return defaultType;
}
}
Expand Up @@ -35,9 +35,7 @@ ManagedClass create(Class<?> baseJavaClass, ClassScan scan){
ManagedClass create(ClientsClassDefinition def, ClassScan scan){
List<JaversProperty> allProperties = convert(scan.getProperties());

List<JaversProperty> filtered = filterIgnored(allProperties, def);

//TODO if def.getIncludedProperties() are defined, use Included, otherwise use Ignored
List<JaversProperty> filtered = filterProperties(allProperties, def);

filtered = filterIgnoredType(filtered, def.getBaseJavaClass());

Expand Down Expand Up @@ -71,12 +69,32 @@ private List<JaversProperty> filterIgnoredType(List<JaversProperty> properties,
});
}

private List<JaversProperty> filterIgnored(List<JaversProperty> properties, ClientsClassDefinition definition){
if (definition.getIgnoredProperties().isEmpty()){
return properties;
private List<JaversProperty> filterProperties(List<JaversProperty> allProperties, ClientsClassDefinition definition){
if (definition.hasWhitelistedProperties()) {
return onlyWhitelisted(allProperties, definition);
}

if (definition.hasIgnoredProperties()) {
return filterIgnored(allProperties, definition);
}

List<JaversProperty> filtered = new ArrayList<>(properties);
return allProperties;
}

private List<JaversProperty> onlyWhitelisted(List<JaversProperty> allProperties, ClientsClassDefinition definition){
List<JaversProperty> filtered = new ArrayList<>();
for (String whiteName : definition.getWhitelistedProperties()) {
JaversProperty whiteProperty = allProperties.stream()
.filter(p -> p.getName().equals(whiteName))
.findFirst()
.orElseThrow(() -> new JaversException(JaversExceptionCode.PROPERTY_NOT_FOUND, whiteName, definition.getBaseJavaClass().getName()));
filtered.add(whiteProperty);
}
return filtered;
}

private List<JaversProperty> filterIgnored(List<JaversProperty> allProperties, ClientsClassDefinition definition){
List<JaversProperty> filtered = new ArrayList<>(allProperties);
for (String ignored : definition.getIgnoredProperties()){
filterOneProperty(filtered, ignored, definition.getBaseJavaClass());
}
Expand Down
Expand Up @@ -23,6 +23,8 @@ import javax.persistence.EmbeddedId
import static org.javers.core.JaversBuilder.javers
import static org.javers.core.MappingStyle.BEAN
import static org.javers.core.MappingStyle.FIELD
import static org.javers.core.metamodel.clazz.EntityDefinitionBuilder.entityDefinition
import static org.javers.core.metamodel.clazz.ValueObjectDefinitionBuilder.valueObjectDefinition
import static org.javers.core.model.DummyUser.Sex.FEMALE
import static org.javers.core.model.DummyUser.Sex.MALE
import static org.javers.core.model.DummyUser.dummyUser
Expand All @@ -34,6 +36,35 @@ import static org.javers.repository.jql.InstanceIdDTO.instanceId
*/
class JaversDiffE2ETest extends AbstractDiffTest {

class WhitelistedClass {
int id
int a
int b
}

@Unroll
def "should ignore all props of #classType which are not whitelisted"(){
given:
def javers = JaversBuilder.javers().registerType(definition).build()

when:
def left = new WhitelistedClass(id:1, a:2, b:3)
def right = new WhitelistedClass(id:1, a:4, b:6)
def diff = javers.compare(left, right)

then:
!diff.changes.size()

where:
definition << [entityDefinition(WhitelistedClass)
.withIdPropertyName("id")
.withWhitelistedProperties(["id"]).build(),
valueObjectDefinition(WhitelistedClass)
.withWhitelistedProperties(["id"]).build()
]
classType << ["EntityType", "ValueObjectType"]
}

def "should extract Property from PropertyChange"(){
given:
def javers = JaversTestBuilder.newInstance()
Expand Down

0 comments on commit fc47037

Please sign in to comment.