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

tools.dynamia.zk.crud.SubcrudController Maven / Gradle / Ivy

There is a newer version: 5.2.1
Show newest version
/*
 * Copyright (C) 2023 Dynamia Soluciones IT S.A.S - NIT 900302344-1
 * Colombia / South America
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package tools.dynamia.zk.crud;

import tools.dynamia.commons.BeanUtils;
import tools.dynamia.commons.ValueWrapper;
import tools.dynamia.commons.reflect.ReflectionException;
import tools.dynamia.crud.CrudControllerException;
import tools.dynamia.crud.SubcrudControllerAPI;
import tools.dynamia.domain.query.DataSet;
import tools.dynamia.domain.query.ListDataSet;
import tools.dynamia.domain.query.QueryParameters;
import tools.dynamia.domain.services.ValidatorService;
import tools.dynamia.domain.util.CrudServiceListener;
import tools.dynamia.domain.util.DomainUtils;
import tools.dynamia.integration.Containers;
import tools.dynamia.zk.viewers.table.TableView;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class SubcrudController extends CrudController implements SubcrudControllerAPI {

    /**
     *
     */
    private static final long serialVersionUID = 2791457285184056200L;
    private final String parentName;
    private Object parent;
    private final List toBeUpdatedEntities = new ArrayList<>();
    private final List toBeCreatedEntities = new ArrayList<>();
    private final List toBeDeletedEntities = new ArrayList<>();
    private final String childrenName;

    public SubcrudController(Object parent, String parentName, String childrenName) {
        this(null, parent, parentName, childrenName);
    }

    public SubcrudController(Class entityClass, Object parent, String parentName, String childrenName) {
        super(entityClass);
        this.parentName = parentName;
        this.parent = parent;
        this.childrenName = childrenName;
        inspectParentChildrens();
        setSaveWithNewTransaction(false);
    }

    @Override
    public void newEntity() {
        super.newEntity();
        if (parent != null) {
            relateChildParent(getEntity(), parent);
        }
    }

    private void inspectParentChildrens() {
        if (parent != null && DomainUtils.findEntityId(parent) == null && childrenName != null) {
            @SuppressWarnings("unchecked") Collection children = (Collection) BeanUtils.invokeGetMethod(parent, childrenName);
            if (children != null) {
                for (E child : children) {
                    if (DomainUtils.findEntityId(child) == null) {
                        toBeCreatedEntities.add(child);
                    }
                }
                children.clear();
            }
        }
    }

    @Override
    protected void beforeQuery() {
        setParemeter(parentName, parent);
    }

    @Override
    public void query() {
        if (DomainUtils.findEntityId(parent) != null) {
            super.query();
        } else {
            //noinspection unchecked
            setQueryResult(new ListDataSet(Collections.emptyList()));
        }
    }

    @Override
    public void save() {
        ValidatorService validatorService = Containers.get().findObject(ValidatorService.class);
        validatorService.validate(getEntity());

        if (DomainUtils.findEntityId(parent) == null) {
            fireCrudListener();

            //add child to parent after validated
            createRelationship(getEntity(), parent);

            if (DomainUtils.findEntityId(getEntity()) == null) {
                if (!toBeCreatedEntities.contains(getEntity())) {
                    toBeCreatedEntities.add(getEntity());
                }
            } else if (!toBeUpdatedEntities.contains(getEntity())) {
                toBeUpdatedEntities.add(getEntity());
            }
        } else {
            if (DomainUtils.findEntityId(getEntity()) == null) {
                createRelationship(getEntity(), parent);
            }
            super.save();
        }

    }

    @Override
    public void delete() {
        Serializable parentId = DomainUtils.findEntityId(parent);
        if (parentId == null) {
            if (DomainUtils.findEntityId(getSelected()) != null) {
                toBeUpdatedEntities.remove(getSelected());
                toBeDeletedEntities.add(getSelected());
            } else {
                toBeCreatedEntities.remove(getSelected());
            }

            if (dataSetView instanceof TableView tableView) {
                tableView.getSelectedItem().detach();
            }

        } else {
            super.delete();
        }

    }

    protected void setParentEntity(Object parentEntity) {
        this.parent = parentEntity;
        if (getEntity() != null) {
            relateChildParent(getEntity(), parent);
        }
    }

    private void createRelationship(E newChild, Object parent) {
        relateChildParent(newChild, parent);
        relateParentChild(newChild, parent);
    }

    /**
     * This is like: parent.getChildren().add(child);
     *
     */
    protected void relateParentChild(E newChild, Object parent) {
        try {

            Object object = BeanUtils.invokeGetMethod(parent, childrenName);
            if (object != null && object instanceof Collection children) {
                //noinspection unchecked
                children.add(newChild);

            }

        } catch (Exception e) {
            logger.error("Cannot create relationship parent <-> child in SubcrudController " + getEntityClass() + ". Check children name ["
                    + childrenName + "]", e);

        }

    }

    /**
     * This is like: child.setParent(value)
     *
     */
    protected void relateChildParent(E newChild, Object parent) {
        try {
            BeanUtils.invokeSetMethod(newChild, parentName, parent);
        } catch (ReflectionException e) {
            if (e.getCause().getClass() == NoSuchMethodException.class) {
                if (parent instanceof ValueWrapper) {
                    parent = ((ValueWrapper) parent).value();
                }

                if (parent.getClass().getSuperclass() != Object.class) {
                    createRelationship(newChild, new ValueWrapper(parent, parent.getClass().getSuperclass()));
                } else {
                    throw new CrudControllerException("Cannot create relationship parent <-> child in SubcrudController "
                            + getEntityClass() + ". Check parent name [" + parentName + "]", e);
                }
            }
        }
    }

    @Override
    public void setQueryResult(DataSet queryResult) {
        addInMemoryResults();
        super.setQueryResult(queryResult);
    }

    private void addInMemoryResults() {
        if (dataSetView instanceof TableView tableView) {
            List defaultValues = new ArrayList<>();
            defaultValues.addAll(toBeCreatedEntities);
            defaultValues.addAll(toBeUpdatedEntities);

            //noinspection unchecked
            tableView.setDefaultValue(defaultValues);
        }

    }

    public void doCreates() {
        for (E entity : toBeCreatedEntities) {
            if (DomainUtils.findEntityId(entity) == null) {
                crudService.create(entity);
            }
        }
        toBeCreatedEntities.clear();

        for (SubcrudController subCrud : getSubcontrollers()) {
            subCrud.doCreates();
        }
    }

    public void doUpdates() {
        for (E entity : toBeUpdatedEntities) {
            crudService.update(entity);
        }
        toBeUpdatedEntities.clear();
        for (SubcrudController subCrud : getSubcontrollers()) {
            subCrud.doUpdates();
        }
    }

    public void doDeletes() {
        for (SubcrudController subCrud : getSubcontrollers()) {
            subCrud.doDeletes();
        }

        for (E entity : toBeDeletedEntities) {
            crudService.delete(entity.getClass(), DomainUtils.findEntityId(entity));
        }
        toBeDeletedEntities.clear();

    }

    private List createIdList(List objects) {
        List ids = new ArrayList<>();

        for (E entity : objects) {
            ids.add(DomainUtils.findEntityId(entity));
        }
        return ids;
    }

    @Override
    public QueryParameters getParams() {
        beforeQuery();
        return super.getParams();
    }

    @Override
    public Object getParentEntity() {
        return parent;
    }

    private void fireCrudListener() {
        for (CrudServiceListener listener : Containers.get().findObjects(CrudServiceListener.class)) {
            try {
                //noinspection unchecked
                listener.beforeCreate(getEntity());
            } catch (ClassCastException ignored) {
            }
        }
    }

    @Override
    public List getToBeUpdatedEntities() {
        return toBeUpdatedEntities;
    }

    @Override
    public List getToBeCreatedEntities() {
        return toBeCreatedEntities;
    }

    @Override
    public List getToBeDeletedEntities() {
        return toBeDeletedEntities;
    }

    @Override
    public String getParentName() {
        return parentName;
    }

    @Override
    public String getChildrenName() {
        return childrenName;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy