public static <T extends FactoryBase<?,?,?>> void setup(Class<T> clazz,BiConsumer<T,AttributeVisitor> visitAttributesFlat, BiConsumer<T,Consumer<FactoryBase<?,?,?>>> visitDataChildren){ FactoryDictionary.getFactoryDictionary(clazz).setVisitChildFactoriesAndViewsFlat(visitDataChildren); DataDictionary.getDataDictionary(clazz).setUseTemporaryAttributes(); DataDictionary.getDataDictionary(clazz).setVisitAttributesFlat(visitAttributesFlat); DataDictionary.getDataDictionary(clazz).setVisitDataChildren((t, dataConsumer) -> visitDataChildren.accept(t, dataConsumer::accept)); }
@SuppressWarnings("unchecked") public static <T extends Data> DataDictionary<T> getDataDictionary(Class<T> clazz){ DataDictionary<T> result=(DataDictionary<T>)dataReferences.get(clazz); if (result==null){ result=new DataDictionary<>(clazz); dataReferences.put(clazz,result); } return result; }
public DataDictionary(Class<?> clazz){ this.clazz=clazz; initAttributeFields(clazz); }
@SuppressWarnings("unchecked") public FactoryTreeBuilderBasedAttributeSetup(FactoryTreeBuilder<R> factoryTreeBuilder) { this.factoryTreeBuilder = factoryTreeBuilder; newValuesProvider = (root, attribute) -> { Class<?> referenceClazz = ((ReferenceBaseAttribute<?,?, ?>) attribute).internal_getReferenceClass(); List<?> newFactories = this.createNewFactory((Class<FactoryBase<Object, ?, R>>) referenceClazz); ArrayList result = new ArrayList(newFactories); if(result.isEmpty()){ Class referenceClazzWorkaround=referenceClazz; result.add(DataDictionary.getDataDictionary(referenceClazzWorkaround).newInstance()); } for (Object o : result) { FactoryBase<?,?,?> factory=(FactoryBase)o; for (Data child : factory.internal().collectChildrenDeepFromNode()) { if (child instanceof FactoryBase<?,?,?>) { child.internal().visitAttributesFlat((attributeVariableName, childAttribute) -> applyToAttribute(childAttribute)); } } } return result; }; }
@SuppressWarnings("unchecked") private DataDictionary<Data> getDataDictionary(){ return (DataDictionary<Data>)DataDictionary.getDataDictionary(getClass()); }
private void addBackReferencesForSubtree(Data root, Data parent, HashSet<Data> visited){ addParent(parent); this.root=root; getDataDictionary().addBackReferencesToAttributes(this,root); if (visited.add(this)) {//use HashSet instead of iteration counter to avoid iterationCounter mix up getDataDictionary().visitDataChildren(this, child -> child.addBackReferencesForSubtree(root,this,visited)); } }
public D newInstance(){ return newCopyInstance(null); } }
void visitAttributesTripleFlat(D data, D other1, D other2, Data.TriAttributeVisitor consumer) { if (this.visitDataChildren != null) { List<AttributeNamePair> attributes = getAttributes(data,10); List<AttributeNamePair> otherAttributes = getAttributes(other1,attributes.size()); List<AttributeNamePair> other2Attributes = getAttributes(other2,attributes.size()); for (int i = 0; i < attributes.size(); i++) { consumer.accept(attributes.get(i).name,attributes.get(i).attribute,otherAttributes.get(i).attribute,other2Attributes.get(i).attribute); } } else { for (Field field : attributeFields) { try { consumer.accept(field.getName(),(Attribute<?,?>) field.get(data), (Attribute<?,?>) field.get(other1), (Attribute<?,?>) field.get(other2)); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } }
private void addBackReferences(final Data root, final Data parent, long dataIterationRun){ addParent(parent); this.root=root; getDataDictionary().addBackReferencesToAttributes(this,root); this.visitDataChildrenFlat(data -> data.addBackReferences(root, Data.this,dataIterationRun),dataIterationRun); }
private Data newCopyInstance(Data data) { return getDataDictionary().newCopyInstance(data); }
void visitAttributesDualFlat(D data, D other, Data.BiAttributeVisitor consumer) { if (this.visitDataChildren != null) { List<AttributeNamePair> attributes = getAttributes(data,10); List<AttributeNamePair> otherAttributes = getAttributes(other,attributes.size()); for (int i = 0; i < attributes.size(); i++) { consumer.accept(attributes.get(i).name,attributes.get(i).attribute,otherAttributes.get(i).attribute); } } else { for (Field field : attributeFields) { try { consumer.accept(field.getName(),(Attribute<?,?>) field.get(data), (Attribute<?,?>) field.get(other)); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } }
private void initAttributeFields(Class<?> clazz) { Class<?> parent = clazz.getSuperclass(); if (parent!=null){// skip Object initAttributeFields(parent); } Stream.of(clazz.getDeclaredFields()). filter(f-> Modifier.isPublic(f.getModifiers())). filter(f->!Modifier.isStatic(f.getModifiers())). filter(f->Attribute.class.isAssignableFrom(f.getType())). forEach(attributeFields::add); }