Created
July 28, 2016 21:18
-
-
Save rascio/7f9dc1edc2462cc2693e7eab9cdc885c to your computer and use it in GitHub Desktop.
MetaModel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.gson.JsonElement; | |
import com.google.gson.JsonObject; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class Content { | |
private final JsonObject data; | |
public Content(JsonObject values) { | |
this.data = values; | |
} | |
public JsonElement get(String key) { | |
return data.get(key); | |
} | |
public JsonObject getData() { | |
return data; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.common.collect.ImmutableSet; | |
import com.google.gson.JsonElement; | |
import java.util.Set; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class EnumValueType extends StringValue{ | |
public static EnumValueType of(String...values) { | |
return new EnumValueType(ImmutableSet.copyOf(values)); | |
} | |
private final Set<String> values; | |
public EnumValueType(Set<String> values) { | |
this.values = values; | |
} | |
@Override | |
public ValidationResult validate(JsonElement value) { | |
return super.validate(value) | |
.and(() -> values.contains(value.getAsString()) | |
? ValidationResult.valid() | |
: ValidationResult.error(String.format("%s is not a valid value, should be one of %s", value, values)) | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.gson.JsonElement; | |
import java.util.List; | |
import java.util.stream.Collectors; | |
import java.util.stream.Stream; | |
import java.util.stream.StreamSupport; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class ListValue<T> extends ValueType<List<T>>{ | |
public static <T> ListValue<T> of(ValueType<T> type) { | |
return new ListValue<>(type); | |
} | |
private final ValueType<T> innerType; | |
public ListValue(ValueType<T> innerType) { | |
this.innerType = innerType; | |
} | |
@Override | |
public ValidationResult validate(JsonElement value) { | |
return value.isJsonArray() | |
? stream(value) | |
.map(innerType::validate) | |
.filter(ValidationResult::isError) | |
.reduce((v1, v2) -> v1.map(msg -> msg + ", " + v2.error())) | |
.orElse(ValidationResult.valid()) | |
: ValidationResult.error("is not a list"); | |
} | |
@Override | |
public List<T> value(JsonElement value) { | |
return stream(value) | |
.map(innerType::value) | |
.collect(Collectors.toList()); | |
} | |
private Stream<JsonElement> stream(JsonElement value) { | |
return StreamSupport.stream(value.getAsJsonArray().spliterator(), false); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.gson.JsonElement; | |
import java.util.Locale; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class LocaleValueType extends ValueType<Locale>{ | |
@Override | |
public ValidationResult validate(JsonElement value) { | |
if (!value.isJsonPrimitive()) { | |
return ValidationResult.error("is not a string"); | |
} | |
else if (!value.getAsString().matches("[a-zA-Z]{2}(_[a-zA-Z]{2})?")) { | |
return ValidationResult.error("is not a valid Locale"); | |
} | |
else { | |
return ValidationResult.valid(); | |
} | |
} | |
@Override | |
public Locale value(JsonElement value) { | |
return new Locale(value.getAsString()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.common.collect.ImmutableList; | |
import com.google.common.collect.ImmutableMap; | |
import com.google.gson.JsonObject; | |
import java.util.HashMap; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.function.Function; | |
import java.util.stream.Collectors; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class MetaModel { | |
public static Builder definition(String name) { | |
return new Builder(name); | |
} | |
private final String name; | |
private final Map<String, ValueType<?>> properties; | |
private final List<Validator> validators; | |
public MetaModel(String name, Map<String, ValueType<?>> properties, List<Validator> validators) { | |
this.name = name; | |
this.properties = properties; | |
this.validators = validators; | |
} | |
public List<String> validate(Content content) { | |
final List<String> propertiesValidation = properties.entrySet().stream() | |
.map(e -> e.getValue() | |
.validation(content.get(e.getKey())) | |
.map(message -> String.format("[%s] %s", e.getKey(), message)) | |
) | |
.filter(ValidationResult::isError) | |
.map(ValidationResult::error) | |
.collect(Collectors.toList()); | |
if (propertiesValidation.isEmpty()) { | |
return validators.stream() | |
.map(v -> v.apply(content.getData())) | |
.filter(ValidationResult::isError) | |
.map(ValidationResult::error) | |
.collect(Collectors.toList()); | |
} | |
else { | |
return propertiesValidation; | |
} | |
} | |
public interface Validator extends Function<JsonObject, ValidationResult> {} | |
public static class Builder { | |
private final String name; | |
private final Map<String, ValueType<?>> properties = new HashMap<>(); | |
private final List<Validator> validators = new LinkedList<>(); | |
public Builder(String name) { | |
this.name = name; | |
} | |
public Builder property(String name, ValueType<?> type) { | |
this.properties.put(name, type); | |
return this; | |
} | |
public Builder validation(Validator validator) { | |
this.validators.add(validator); | |
return this; | |
} | |
public MetaModel build() { | |
return new MetaModel(name, ImmutableMap.copyOf(this.properties), ImmutableList.copyOf(this.validators)); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.gson.JsonArray; | |
import com.google.gson.JsonObject; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class ModelSet { | |
public static void main(String[] args) { | |
final MetaModel gdSnippet = MetaModel.definition("gd_snippet") | |
.property("locale", OptionalValue.of(new LocaleValueType())) | |
.property("text", new StringValue()) | |
.property("tags", ListValue.of(EnumValueType.of("quick-view", "test"))) | |
.validation(json -> | |
json.get("text").getAsString().length() > 5 && json.get("locale") != null | |
? ValidationResult.error("if text is more than 5 chars locale should be null") | |
: ValidationResult.valid() | |
) | |
.build(); | |
final JsonObject data = new JsonObject(); | |
final JsonArray tags = new JsonArray(); | |
tags.add("pippo"); | |
tags.add("quick-view"); | |
tags.add("pluto"); | |
data.addProperty("locale", "it_IT"); | |
data.addProperty("text", "asdasd"); | |
data.add("tags", tags); | |
final Content content = new Content(data); | |
gdSnippet.validate(content) | |
.forEach(System.out::println); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.gson.JsonElement; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class OptionalValue<T> extends ValueType<T>{ | |
public static <T> OptionalValue<T> of(ValueType<T> type) { | |
return new OptionalValue<>(type); | |
} | |
private final ValueType<T> innerType; | |
public OptionalValue(ValueType<T> innerType) { | |
this.innerType = innerType; | |
} | |
@Override | |
public ValidationResult validate(JsonElement value) { | |
return value != null | |
? innerType.validate(value) | |
: ValidationResult.valid(); | |
} | |
@Override | |
public T value(JsonElement value) { | |
return value != null | |
? innerType.value(value) | |
: null; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.gson.JsonElement; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class StringValue extends ValueType<String>{ | |
@Override | |
public ValidationResult validate(JsonElement value) { | |
return value.isJsonPrimitive() | |
? ValidationResult.valid() | |
: ValidationResult.error("is not a string"); | |
} | |
@Override | |
public String value(JsonElement value) { | |
return value.getAsString(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import java.util.function.Function; | |
import java.util.function.Supplier; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public interface ValidationResult { | |
public static ValidationResult valid() { | |
return new ValidResult(); | |
} | |
public static ValidationResult error(String message) { | |
return new ErrorResult(message); | |
} | |
boolean isError(); | |
String error(); | |
ValidationResult map(Function<String, String> mapping); | |
ValidationResult and(Supplier<ValidationResult> other); | |
static class ValidResult implements ValidationResult { | |
@Override | |
public boolean isError() { | |
return false; | |
} | |
@Override | |
public String error() { | |
throw new IllegalStateException("Is not an error!"); | |
} | |
@Override | |
public ValidationResult map(Function<String, String> mapping) { | |
return this; | |
} | |
@Override | |
public ValidationResult and(Supplier<ValidationResult> other) { | |
return other.get(); | |
} | |
} | |
static class ErrorResult implements ValidationResult { | |
private final String message; | |
public ErrorResult(String message) { | |
this.message = message; | |
} | |
@Override | |
public boolean isError() { | |
return true; | |
} | |
@Override | |
public String error() { | |
return this.message; | |
} | |
@Override | |
public ValidationResult map(Function<String, String> mapping) { | |
return new ErrorResult(mapping.apply(this.message)); | |
} | |
@Override | |
public ValidationResult and(Supplier<ValidationResult> other) { | |
return this; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public class Value<T> { | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package it.r.meta; | |
import com.google.gson.JsonElement; | |
/** | |
* Created by rascio on 28/07/16. | |
*/ | |
public abstract class ValueType<T> { | |
public ValidationResult validation(JsonElement value) { | |
if (value == null) { | |
return ValidationResult.error("is missing"); | |
} | |
else { | |
return validate(value); | |
} | |
} | |
/* | |
* Maybe a ValidationResult object instead of two methods is better | |
*/ | |
protected abstract T value(JsonElement value); | |
protected abstract ValidationResult validate(JsonElement value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment