
com.venky.swf.db.model.io.AbstractModelWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swf-db Show documentation
Show all versions of swf-db Show documentation
Succinct Web Framework - Db
The newest version!
package com.venky.swf.db.model.io;
import com.venky.cache.Cache;
import com.venky.core.collections.SequenceSet;
import com.venky.core.log.SWFLogger;
import com.venky.core.log.TimerUtils;
import com.venky.core.string.StringUtil;
import com.venky.core.util.ObjectUtil;
import com.venky.swf.db.Database;
import com.venky.swf.db.annotations.column.ATTRIBUTE_GROUP;
import com.venky.swf.db.annotations.column.ui.mimes.MimeType;
import com.venky.swf.db.model.Model;
import com.venky.swf.db.model.reflection.ModelReflector;
import com.venky.swf.integration.FormatHelper;
import com.venky.swf.integration.FormatHelper.KeyCase;
import com.venky.swf.routing.Config;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public abstract class AbstractModelWriter extends ModelIO implements ModelWriter{
boolean parentIdExposed = true;
public void setParentIdExposed(boolean parentIdExposed){
this.parentIdExposed = parentIdExposed;
}
public boolean isParentIdExposed() {
return this.parentIdExposed;
}
protected AbstractModelWriter(Class beanClass) {
super(beanClass);
}
@SuppressWarnings("unchecked")
public Class getFormatClass(){
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
return (Class) pt.getActualTypeArguments()[1];
}
public MimeType getMimeType(){
return FormatHelper.getMimeType(getFormatClass());
}
private List getFields(List includeFields){
return getFields(getReflector(),includeFields);
}
private static List getFields(ModelReflector reflector, List includeFields) {
List fields = includeFields;
if (fields == null){
fields = reflector.getVisibleFields();
}
return fields;
}
public void write(List records, OutputStream os,List fields) throws IOException {
FormatHelper helper = FormatHelper.instance(getMimeType(),StringUtil.pluralize(getBeanClass().getSimpleName()),true);
write (records,helper.getRoot(),fields);
os.write(helper.toString().getBytes());
}
public void write(List records, T into,List fields) throws IOException {
Map , List> mapFields = new HashMap<>();
Set> parentsWritten = new HashSet<>();
write (records,into,fields,parentsWritten,mapFields);
}
public void write (List records,OutputStream os, List fields, Set> parentsAlreadyConsidered,
Map,List> templateFields) throws IOException {
FormatHelper helper = FormatHelper.instance(getMimeType(),StringUtil.pluralize(getBeanClass().getSimpleName()),true);
write(records,helper.getRoot(),fields,parentsAlreadyConsidered,templateFields);
os.write(helper.toString().getBytes());
}
public void write (List records,T into, List fields, Set> parentsAlreadyConsidered,
Map,List> templateFields) throws IOException {
write(records,into,fields,parentsAlreadyConsidered,getChildrenToConsider(templateFields),templateFields);
}
public void write (List records,OutputStream os, List fields, Set> parentsAlreadyConsidered ,
Map,List>> childrenToBeConsidered,
Map,List> templateFields) throws IOException {
FormatHelper helper = FormatHelper.instance(getMimeType(),StringUtil.pluralize(getBeanClass().getSimpleName()),true);
write(records,helper.getRoot(),fields,parentsAlreadyConsidered,childrenToBeConsidered,templateFields);
os.write(helper.toString().getBytes());
}
public void write (List records,T into, List fields, Set> parentsAlreadyConsidered ,
Map,List>> childrenToBeConsidered,
Map,List> templateFields) throws IOException {
FormatHelper helper = FormatHelper.instance(into);
for (M record: records){
T childElement = helper.createArrayElement(getBeanClass().getSimpleName());
write(record,childElement,fields,parentsAlreadyConsidered, childrenToBeConsidered, templateFields);
}
}
public void write(M record,T into, List fields){
write(record,into,fields,new HashSet<>(), new HashMap<>());
}
private boolean isParentIgnored(Class extends Model> parent, Set ignoredParents) {
return ignoredParents.contains(parent.getSimpleName());
}
private final SWFLogger cat = Config.instance().getLogger(getClass().getName());
public Map , List>> getChildrenToConsider(Map, List> templateFields){
return getReflector().getChildrenToBeConsidered(templateFields);
}
public void write(M record,T into, List fields, Set> parentsAlreadyConsidered , Map,List> templateFields) {
//Consider first level children.
write(record,into,fields,parentsAlreadyConsidered,getChildrenToConsider(templateFields),templateFields);
}
public void write(M record,T into, List fields, Set> parentsAlreadyConsidered ,
Map, List>> considerChildren,
Map, List> templateFields) {
Set simplifiedParentsConsidered = new HashSet<>();
parentsAlreadyConsidered.forEach(c->simplifiedParentsConsidered.add(c.getSimpleName()));
Map> simplifiedConsiderChildren = new Cache>() {
@Override
protected List getValue(String s) {
return new SequenceSet<>();
}
};
considerChildren.forEach((m,l)->{
for (Class extends Model> child: l){
simplifiedConsiderChildren.get(m.getSimpleName()).add(child.getSimpleName());
}
});
Map> simplifiedTemplateFields = new Cache>() {
@Override
protected List getValue(String s) {
return new SequenceSet<>();
}
};
templateFields.forEach((m,fl)->{
for (String f: fl != null ? fl : ModelReflector.instance(m).getVisibleFields()){
simplifiedTemplateFields.get(m.getSimpleName()).add(f);
}
});
writeSimplified(record,into,fields,simplifiedParentsConsidered,simplifiedConsiderChildren,simplifiedTemplateFields);
}
public void writeSimplified(M record,T into, List fields,
Set parentsAlreadyConsidered ,
Map> considerChildren,
Map> templateFields) {
FormatHelper _formatHelper = FormatHelper.instance(into);
ModelReflector ref = getReflector();
Map> groupedFields = ref.getGroupedFields();
for (String field: getFields(fields)){
FormatHelper formatHelper = _formatHelper;
Object value = TimerUtils.time(cat,"ref.get", ()-> ref.get(record, field));
if (value == null){
continue;
}
Method fieldGetter = TimerUtils.time(cat,"getFieldGetter" , () ->ref.getFieldGetter(field));
Method referredModelGetter = TimerUtils.time(cat,"getReferredModelGetterFor" , ()->ref.getReferredModelGetterFor(fieldGetter));
if (referredModelGetter != null){
Class extends Model> aParent = ref.getReferredModelClass(referredModelGetter);
if (!isParentIgnored(aParent,parentsAlreadyConsidered) || fields != null) {
String refElementName = referredModelGetter.getName().substring("get".length());
T refElement = formatHelper.createElementAttribute(refElementName);
parentsAlreadyConsidered.add(aParent.getSimpleName());
try {
write(aParent, ((Number) value).longValue(), refElement, parentsAlreadyConsidered, considerChildren,templateFields);
}finally {
parentsAlreadyConsidered.remove(aParent.getSimpleName());
}
}
}else {
String attributeName = TimerUtils.time(cat,"getAttributeName()" , ()->getAttributeName(field));
if (!groupedFields.isEmpty()){
ATTRIBUTE_GROUP group = ref.getAnnotation(fieldGetter, ATTRIBUTE_GROUP.class);
if (group != null && !ObjectUtil.isVoid(group.value())){
T groupElement = formatHelper.getElementAttribute(group.value());
if (groupElement == null){
groupElement = formatHelper.createElementAttribute(group.value());
}
formatHelper = FormatHelper.instance(groupElement);
}
}
if (String[].class.isAssignableFrom(value.getClass())) {
formatHelper.setAttribute(attributeName, (String[])value);
}else {
String sValue = Database.getJdbcTypeHelper(getReflector().getPool()).getTypeRef(fieldGetter.getReturnType()).getTypeConverter().toStringISO(value);
if (InputStream.class.isAssignableFrom(fieldGetter.getReturnType())) {
formatHelper.setElementAttribute(attributeName, sValue);
} else {
formatHelper.setAttribute(attributeName, sValue);
}
}
}
}
TimerUtils.time(cat,"Writing all Children Objects",()->{
if (!templateFields.isEmpty()){
parentsAlreadyConsidered.add(ref.getModelClass().getSimpleName());
try {
List childGetters = ref.getChildGetters();
for (Method childGetter : childGetters) {
write(_formatHelper,record,childGetter,parentsAlreadyConsidered,considerChildren,templateFields);
}
}finally {
parentsAlreadyConsidered.remove(ref.getModelClass().getSimpleName());
}
}
return true;
});
}
private boolean containsChild(Class childModelClass, Collection considerChildren){
return considerChildren != null && considerChildren.contains(childModelClass.getSimpleName());
}
private void write(FormatHelper formatHelper, M record, Method childGetter, Set parentsWritten ,
Map> considerChildren,
Map> templateFields){
@SuppressWarnings("unchecked")
Class childModelClass = (Class) getReflector().getChildModelClass(childGetter);
if (!containsChild(childModelClass,considerChildren.get(getBeanClass().getSimpleName()))){
return;
}
if (!containsChild(childModelClass,templateFields.keySet())){
return;
}
ModelWriter childWriter = ModelIOFactory.getWriter(childModelClass, getFormatClass());
try {
@SuppressWarnings("unchecked")
List children = (List)childGetter.invoke(record);
List fields = new ArrayList<>();
List f = templateFields.get(childModelClass.getSimpleName());
if (f != null) {
fields.addAll(f);
}
if (fields.isEmpty()){
fields = null;
}
Map> newConsiderChilden = new HashMap<>(considerChildren);
newConsiderChilden.remove(getBeanClass().getSimpleName()); //Don't print children of parent via children. !! Duplication.
for (R child : children) {
T childElement = formatHelper.createArrayElement(childModelClass.getSimpleName());
childWriter.writeSimplified(child, childElement, fields, parentsWritten, newConsiderChilden, templateFields);
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private void write(Class referredModelClass, long id, T referredModelElement, Set parentsAlreadyConsidered,
Map> considerChildren,
Map> templateFields){
Class formatClass = getFormatClass();
ModelWriter writer = ModelIOFactory.getWriter(referredModelClass,formatClass);
R referredModel = Database.getTable(referredModelClass).get(id);
if (referredModel == null){
return;
}
ModelReflector referredModelReflector = ModelReflector.instance(referredModelClass);
List parentFieldsToAdd = referredModelReflector.getUniqueFields();
parentFieldsToAdd.removeIf(referredModelReflector::isFieldHidden);
if (isParentIdExposed() || parentFieldsToAdd.isEmpty()) {
parentFieldsToAdd.add("ID");
}
if (templateFields != null){
List parentFieldsToAddBasedOnTemplate = new SequenceSet<>();
if (templateFields.get(referredModelClass.getSimpleName()) != null) {
//Never add parent class with null template.
parentFieldsToAddBasedOnTemplate.addAll(getFields(referredModelReflector,templateFields.get(referredModelClass.getSimpleName())));
}
if (!parentFieldsToAddBasedOnTemplate.isEmpty()){
parentFieldsToAdd.clear();
parentFieldsToAdd.addAll(parentFieldsToAddBasedOnTemplate);
}
}
//* Which parent's children to include */
List newChildModelsToConsider = new SequenceSet<>();
if (considerChildren != null){
newChildModelsToConsider = considerChildren.getOrDefault(referredModelClass.getSimpleName(),newChildModelsToConsider);
}
List> childModels = referredModelReflector.getChildModels();
Map> newTemplateFields = null;
if (templateFields != null){
newTemplateFields = new HashMap<>(templateFields);
for (Class extends Model> childModelClass : childModels){
boolean keepChildModelClassInTemplate = newChildModelsToConsider.contains(childModelClass.getSimpleName());
if (!keepChildModelClassInTemplate){
newTemplateFields.remove(childModelClass.getSimpleName());
}
}
}
writer.writeSimplified(referredModel , referredModelElement, parentFieldsToAdd, parentsAlreadyConsidered, considerChildren, newTemplateFields);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy