Newer
Older
wicketspringdata / src / main / java / ru / simplex_software / wicket_springdata / HibernateModel.java
package ru.simplex_software.wicket_springdata;

import org.apache.wicket.injection.Injector;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.hibernate.Hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Persistable;
import org.springframework.data.repository.CrudRepository;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Модель содержит:
 * Persistable сущность в прикреплённом состоянии,
 * id и класс Persistable сущности в откреплённом состоянии.
 */
public class HibernateModel<T extends Persistable<Serializable>> extends LoadableDetachableModel<T> {
    private static final Logger LOG = LoggerFactory.getLogger(HibernateModel.class);

    @SpringBean
    private RepositoryFinder repositoryFinder;

    /**
     * Первичный кдюч хранимой сущности
     */
    private Serializable id;

    /**
     * Класс хранимой сущности
     */
    private Class<T> tClass;

    public HibernateModel() {
        init();
    }

    /**
     * Конструктор.
     *
     * @param entity может быть NULL.
     */
    public HibernateModel(T entity) {
        super(entity);
        init();
        setObject(entity);
    }

    public void setObject(T entity) {
        if (entity != null && entity.isNew()) {
            throw new IllegalArgumentException("primary key can't be null");
        }
        super.setObject(entity);
    }

    /**
     * Открепление сущности.
     */
    public void onDetach() {
        LOG.debug("onDetach start");

        // Получаем Persistable сущность.
        T entity = getObject();
        if (entity == null) {
            return;
        }

        // Получаем Id и класс Persistable сущности.
        id = entity.getId();
        tClass = (Class<T>) Hibernate.getClass(entity);
        LOG.debug("onDetach end");
    }

    private void init() {
        Injector.get().inject(this);
    }

    @Override
    protected T load() {
        LOG.debug("load start");

        if (isAttached()) {
            return getObject();
        }
        if (tClass == null) {
            return null;
        }
        final CrudRepository repository = repositoryFinder.findRepository(tClass);
        LOG.trace("repository={}", repository);
        return (T) repository.findById(id).get();
    }

    /**
     * Оборачивает в модели элементы списка.
     */
    public static <E extends Persistable<Serializable>> List<HibernateModel<E>> wrapElements(List<E> list) {
        final ArrayList<HibernateModel<E>> models = new ArrayList<>(list.size());
        for (E e : list) {
            models.add(new HibernateModel<>(e));
        }
        return models;
    }

    /**
     * Оборачивает в модели элементы списка и возвращает итератор.
     */
    public static <E extends Persistable<Serializable>> Iterator<HibernateModel<E>> wrapAndIterateElements(List<E> list) {
        final ArrayList<HibernateModel<E>> models = new ArrayList<>(list.size());
        for (E e : list) {
            models.add(new HibernateModel<>(e));
        }
        return models.iterator();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (id == null) {
            onDetach();
        }
        if (id == null) {//if no object set
            if (o instanceof HibernateModel) {
                Object obj = ((HibernateModel) o).getObject();
                return obj == null;
            }
            return false;
        }

        if (o == null || getClass() != o.getClass()) return false;

        HibernateModel<?> that = (HibernateModel<?>) o;

        if (!id.equals(that.id)) return false;
        return tClass.equals(that.tClass);
    }

    @Override
    public int hashCode() {
        if (id == null) {
            onDetach(); // Для установки Id
        }
        if (id == null) { // if no object set
            return -1;
        } else {
            return id.hashCode();
        }
    }

    public RepositoryFinder getRepositoryFinder() {
        return repositoryFinder;
    }

    public void setRepositoryFinder(RepositoryFinder repositoryFinder) {
        this.repositoryFinder = repositoryFinder;
    }
}