Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.leeonky.dal.runtime.Data Maven / Gradle / Ivy
package com.github.leeonky.dal.runtime;
import com.github.leeonky.dal.runtime.RuntimeContextBuilder.DALRuntimeContext;
import com.github.leeonky.dal.runtime.inspector.DumpingBuffer;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.github.leeonky.dal.ast.node.SortGroupNode.NOP_COMPARATOR;
import static com.github.leeonky.dal.runtime.CurryingMethod.createCurryingMethod;
import static com.github.leeonky.util.Classes.named;
import static java.lang.String.format;
import static java.util.Optional.of;
import static java.util.stream.Collectors.toList;
//TODO use generic
public class Data {
private final SchemaType schemaType;
private final DALRuntimeContext context;
private final Object instance;
private DataList list;
public Data(Object instance, DALRuntimeContext context, SchemaType schemaType) {
this.instance = instance;
this.schemaType = schemaType;
this.context = context;
}
public Object instance() {
return instance;
}
public Set fieldNames() {
return context.findPropertyReaderNames(instance);
}
public boolean isList() {
return context.isRegisteredList(instance) || (instance != null && instance.getClass().isArray());
}
public DataList list() {
if (list == null) {
if (!isList())
throw new java.lang.RuntimeException(format("Invalid input value, expect a List but: %s", dumpAll().trim()));
list = new DataList(context.createCollection(instance));
}
return list;
}
public boolean isNull() {
return context.isNull(instance);
}
public Data getValue(List propertyChain) {
return propertyChain.isEmpty() ? this :
getValue(propertyChain.get(0)).getValue(propertyChain.subList(1, propertyChain.size()));
}
public Data getValue(Object propertyChain) {
try {
List chain = schemaType.access(propertyChain).getPropertyChainBefore(schemaType);
if (chain.size() == 1 && chain.get(0).equals(propertyChain))
return new Data(getPropertyValue(propertyChain), context, propertySchema(propertyChain));
return getValue(chain);
} catch (IndexOutOfBoundsException ex) {
throw new PropertyAccessException(ex.getMessage(), ex);
} catch (ListMappingElementAccessException ex) {
throw new PropertyAccessException(ex.toDalError(0).getMessage(),
ex.propertyAccessException().getCause());
} catch (Exception e) {
throw new PropertyAccessException(format("Get property `%s` failed, property can be:\n" +
" 1. public field\n" +
" 2. public getter\n" +
" 3. public no args method\n" +
" 4. Map key value\n" +
" 5. customized type getter\n" +
" 6. static method extension\n%s%s",
propertyChain, e.getMessage(), listMappingMessage(this, propertyChain)), e);
}
}
private String listMappingMessage(Data data, Object symbol) {
return data.isList() ? format("\nImplicit list mapping is not allowed in current version of DAL, use `%s[]` instead",
symbol) : "";
}
private Object getPropertyValue(Object property) {
return isList() ? fetchFromList(property) : context.getPropertyValue(this, property);
}
private Object fetchFromList(Object property) {
return property instanceof String ? context.getPropertyValue(this, property) :
list().getByIndex((int) property);
}
private SchemaType propertySchema(Object property) {
if (isList() && property instanceof String)
return schemaType.mappingAccess(property);
return schemaType.access(property);
}
public Object firstFieldFromAlias(Object alias) {
return schemaType.firstFieldFromAlias(alias);
}
public Data convert(Class> target) {
return new Data(context.getConverter().convert(target, instance), context, schemaType);
}
public Data map(Function mapper) {
return new Data(mapper.apply(instance), context, schemaType);
}
public Data filter(String prefix) {
FilteredObject filteredObject = new FilteredObject();
fieldNames().stream().filter(String.class::isInstance).map(String.class::cast)
.filter(field -> field.startsWith(prefix)).forEach(fieldName ->
filteredObject.put(fieldName.substring(prefix.length()), getValue(fieldName).instance()));
return new Data(filteredObject, context, schemaType);
}
public String dumpAll() {
return DumpingBuffer.rootContext(context).dump(this).content();
}
public String dumpValue() {
return DumpingBuffer.rootContext(context).dumpValue(this).content();
}
public T execute(Supplier supplier) {
return context.pushAndExecute(this, supplier);
}
public Optional currying(Object property) {
return currying(instance, property);
}
private Optional currying(Object instance, Object property) {
List methods = context.methodToCurrying(named(instance.getClass()), property).stream()
.map(method -> createCurryingMethod(instance, method, context.getConverter())).collect(toList());
if (!methods.isEmpty())
return of(new CurryingMethodGroup(methods, null));
return context.getImplicitObject(instance).flatMap(obj -> currying(obj, property));
}
static class FilteredObject extends LinkedHashMap implements PartialObject {
}
public class DataList extends DALCollection.Decorated {
public DataList(DALCollection origin) {
super(origin);
}
public DALCollection wraps() {
return map((index, e) -> new Data(e, context, schemaType.access(index)));
}
public Data listMap(Object property) {
return new Data(listMap(data -> data.getValue(property).instance()), context, propertySchema(property));
}
public AutoMappingList listMap(Function mapper) {
return new AutoMappingList(mapper, wraps());
}
public DataList sort(Comparator comparator) {
if (comparator != NOP_COMPARATOR) {
return new DataList(new CollectionDALCollection(wraps().collect().stream()
.sorted(comparator).map(Data::instance).collect(toList())) {
@Override
public int firstIndex() {
return DataList.this.firstIndex();
}
@Override
public boolean infinite() {
return DataList.this.infinite();
}
});
}
return this;
}
public Data wrap() {
return new Data(this, context, schemaType);
}
}
}