All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.fhframework.model.forms.Include Maven / Gradle / Ivy

There is a newer version: 4.10.401
Show newest version
package pl.fhframework.model.forms;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreType;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ReflectionUtils;
import pl.fhframework.binding.AdHocModelBinding;
import pl.fhframework.binding.StaticBinding;
import pl.fhframework.core.FhException;
import pl.fhframework.core.FhFormException;
import pl.fhframework.core.dynamic.DynamicClassName;
import pl.fhframework.core.events.OnEvent;
import pl.fhframework.core.logging.FhLogger;
import pl.fhframework.annotations.*;
import pl.fhframework.annotations.composite.Composite;
import pl.fhframework.binding.ModelBinding;
import pl.fhframework.core.util.StringUtils;
import pl.fhframework.forms.IFormsUtils;
import pl.fhframework.helper.AutowireHelper;
import pl.fhframework.model.dto.ElementChanges;
import pl.fhframework.tools.loading.FormReader;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Created by krzysztof.kobylarek on 2016-12-20.
 */

@Control(canBeDesigned = true)
@DesignerControl
@DocumentedComponent(category = DocumentedComponent.Category.ARRANGEMENT, documentationExample = true, value = "Component used to include xml templates into main form view", icon = "fa fa-cubes")
@JsonIgnoreType
@JsonSerialize(using = Include.Serializer.class)
public class Include extends GroupingComponent implements Includeable {

    private static final String ATTR_REF = "ref";
    private static final String ATTR_MODEL = "model";
    private static final String ATTR_MODEL_VALUE = "modelValue";
    private static final String ATTR_VARIANT = "variant";

    @Autowired
    private IFormsUtils formsManager;

    private static AtomicLong incId = new AtomicLong(0);

    @JsonIgnore
    @Getter
    @Setter
    @XMLProperty(value = ATTR_REF, required = true)
    @DocumentedComponentAttribute(value = "Reference to composite type")
    private ModelBinding refBinding;

    @Getter
    protected String ref = "";

    @JsonIgnore
    @Getter
    @Setter
    @XMLProperty(value = ATTR_MODEL, aliases = "model", required = false)
    @DocumentedComponentAttribute(value = "Reference to model instance (property path) as a String. It is recommended to use " + ATTR_MODEL_VALUE + " attribute instead.")
    private ModelBinding modelRefBinding;

    @Getter
    protected String modelRef = "";

    @JsonIgnore
    @Getter
    @Setter
    @XMLProperty(value = ATTR_MODEL_VALUE, required = false)
    @DocumentedComponentAttribute(value = "Model instance")
    private ModelBinding modelValueBinding;

    @JsonIgnore
    @Getter
    @Setter
    @XMLProperty(value = ATTR_VARIANT, aliases = "variant", required = false)
    @DocumentedComponentAttribute(value = "Reference to variant as a String.")
    private ModelBinding variantBinding;

    @Getter
    protected String variant;

    protected Form includedComposite = null;

    @Getter
    @Setter
    @XMLMetadataSubelements
    private List registeredEvents = new LinkedList<>();

    public Include(Form form) {
        super(form);
    }

    @Override
    public void init() {
        super.init();

        if (refBinding == null) {
            throw new FhException("No composite reference");
        }

        // autowire forms manager
        AutowireHelper.autowire(this, formsManager);

        this.resolveBinding();

        if (ref == null) {
            return;
        }

        readComposite();

        includedComposite.setId(getForm().getId());
        includedComposite.setGroupingParentComponent(this);
        includedComposite.setUseCase(getForm().getAbstractUseCase());

        includedComposite.setModelProvider(resolveModelProvider());

        if (includedComposite instanceof CompositeForm) {
            ((CompositeForm)includedComposite).addRegisteredEvents(registeredEvents);
        }

        if (!includedComposite.isInitDone()) {
            includedComposite.init();
        }

        if (!getForm().getIncluded().contains(this)) {
            getForm().getIncluded().add(this);
        }

        doActionForEverySubcomponent(component -> {
            if (!component.isInitDone()) {
                component.init();
            }
        });

        includedComposite.setVariant(variant != null ? variant : getForm().getVariant());
        includedComposite.setAvailabilityRules(includedComposite.getVariant());

        doActionForEverySubcomponent(
                (Component c) -> {
                    if (c.getId() == null) {
                        c.generateId();
                    }
                    if (!c.isGeneratedId()) {
                        c.setRawId(c.getId());
                        c.setId(c.getId() + "_" + incId.getAndIncrement());
                    }
                });

        this.doActionForEverySubcomponent(c -> {
            if (c instanceof FormElement) {
                getForm().addToElementIdToFormElement((FormElement) c);
            }
        });
    }

    protected Supplier resolveModelProvider() {
        if (getForm().getModel() != null && getForm().getViewMode() == Form.ViewMode.NORMAL) {
            if (modelValueBinding != null) {
                return () -> modelValueBinding.getBindingResult().getValue();
            } else if (modelRef != null) {
                return () -> {
                    final String[] splittedModel = modelRef.split("\\.");
                    Object compositeModel = getForm().getModel();
                    Class modelClass = getForm().getModel().getClass();
                    for (int i = 0; i < splittedModel.length; i++) {
                        if (i == 0 && splittedModel[i].equals("THIS")) {
                            modelClass = compositeModel.getClass();
                        } else {
                            Method modelGetter = ReflectionUtils.findMethod(modelClass, toGetter(splittedModel[i]));
                            if (modelGetter != null && Modifier.isPublic(modelGetter.getModifiers())) {
                                compositeModel = ReflectionUtils.invokeMethod(modelGetter, compositeModel);
                                modelClass = compositeModel.getClass();
                            } else {
                                throw new FhFormException(
                                        String.format("Composite model %s in %s not found or not accessible",
                                                modelRef, getForm().getModel().getClass().getSimpleName())
                                );
                            }
                        }
                    }
                    return compositeModel;
                };
            }
        }
        return () -> null;
    }

    protected void readComposite() {
        FormReader formReader = FormReader.getInstance();
        Class compositeComponentClass = formReader.getCompositesClasses().get(ref);
        if (compositeComponentClass != null) {
            includedComposite = formsManager.createFormInstance(compositeComponentClass, getForm().getComponentBindingCreator(), getForm().getBindingMethodsCreator());
        }
        else {
            Class formClass = formsManager.getFormById(ref);
            if (formClass != null) {
                includedComposite = formsManager.createFormInstance(formClass, getForm().getComponentBindingCreator(), getForm().getBindingMethodsCreator());
            }
            else {
                FhLogger.error(ref + " is not a valid included form.");
                return;
            }
        }
    }

    private void resolveBinding() {
        if(this.modelRefBinding != null) {
            modelRef = (String) this.modelRefBinding.resolveValue(modelRef);
        }
        if(this.refBinding != null) {
            ref = (String) this.refBinding.resolveValue(ref);
        }
        if(this.variantBinding != null) {
            variant = (String) this.variantBinding.resolveValue(variant);
        }
    }

    @Override
    public void doActionForEverySubcomponent(Consumer action) {
        getSubcomponents().stream().forEachOrdered((Component c) -> {
            action.accept(c);
            if (c instanceof IGroupingComponent) {
                ((IGroupingComponent) c).doActionForEverySubcomponent(action);
            }
        });
    }

    @Override
    public void activateBindings() {
        if (includedComposite != null) {
            includedComposite.activateBindings();
        }
    }

    @Override
    public void deactivateBindings() {
        if (includedComposite != null) {
            includedComposite.deactivateBindings();
        }
    }

    @Override
    public void afterNestedComponentsProcess() {

        getForm().refreshElementIdToFormElement(); // for now
//

//        doActionForEverySubcomponent(formElement -> {
//            if(formElement instanceof FormElement) {
//                getForm().refreshElementView((FormElement) formElement);
//            }
//        });
//        }
    }

    @Override
    public void refreshView(Set changeSet) {
        super.refreshView(changeSet);
        if(includedComposite != null) {
            includedComposite.getSubcomponents().forEach((c) -> ((Component) c).refreshView(changeSet)); // to jakas glupota, kompilator wnioskuje brak typu ale powinien byc Component!
        }
    }

    @Override
    public void addSubcomponent(Component component) {
        if(includedComposite != null) {
            includedComposite.addSubcomponent(component);
        }
    }

    @Override
    public void removeSubcomponent(Component removedComponent) {
        if(includedComposite != null) {
            includedComposite.removeSubcomponent(removedComponent);
        }
    }

    @Override
    public IGroupingComponent getGroupingComponent(Component component) {
        if(includedComposite != null) {
            return includedComposite.getGroupingParentComponent();
        } else {
            return getGroupingParentComponent();
        }
    }

    @Override
    public List getSubcomponents() {
        if (includedComposite != null) {
            return includedComposite.getSubcomponents();
        } else {
            return new LinkedList<>();
        }
    }

    @Override
    public List getNonVisualSubcomponents() {
        return Collections.emptyList();
    }

    @Override
    public List getIncludedComponents() {
        return getSubcomponents();
    }

    public void addRegisteredEvent(OnEvent onEvent){
        registeredEvents.add(onEvent);
    }

    static class Serializer extends JsonSerializer {


        @Override
        public void serialize(Include tag, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            if (tag != null && tag.getSubcomponents() != null) {
                Group group = new Group(tag.getForm());
                group.setStyleClasses(tag.getClass().getSimpleName());
                group.setId(tag.getId());
                group.getSubcomponents().addAll(tag.getSubcomponents());
                gen.writeObject(group);
            }
        }
    }

    private static String toGetter(String fieldName) {
        StringBuilder sb = new StringBuilder();
        return sb.append("get").append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1, fieldName.length())).toString();
    }

    @Override
    public void preConfigureClear() {
        super.preConfigureClear();
        includedComposite = null;
        resetInitDone();
    }

    @Override
    public String getStaticRef() {
        if (!StringUtils.isNullOrEmpty(ref)) {
            return ref;
        }
        String staticRefForm = null;
        if (refBinding instanceof StaticBinding) {
            staticRefForm =  ((StaticBinding) refBinding).getStaticValue();
        }
        else if (refBinding instanceof AdHocModelBinding && ((AdHocModelBinding) refBinding).isStaticValue()) {
            staticRefForm = ((AdHocModelBinding) refBinding).getStaticValueText();
        }
        if (!StringUtils.isNullOrEmpty(staticRefForm)) {
            Class compositeForm = FormReader.getInstance().getCompositesClasses().get(((AdHocModelBinding) refBinding).getStaticValueText());
            if (compositeForm != null) {
                return DynamicClassName.forClassName(compositeForm.getName()).toFullClassName();
            }
            return staticRefForm;
        }
        return null;
    }

    @Override
    public void calculateAvailability() {
        super.calculateAvailability();
        if (includedComposite != null) {
            includedComposite.calculateAvailability();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy