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

com.jetbrains.teamsys.dnq.database.EntityOperations Maven / Gradle / Ivy

/**
 * Copyright 2006 - 2017 JetBrains s.r.o.
 *
 * 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 com.jetbrains.teamsys.dnq.database;

import jetbrains.exodus.core.dataStructures.hash.HashSet;
import jetbrains.exodus.database.TransientEntity;
import jetbrains.exodus.database.TransientEntityStore;
import jetbrains.exodus.database.TransientStoreSession;
import jetbrains.exodus.entitystore.Entity;
import jetbrains.exodus.query.metadata.EntityMetaData;
import jetbrains.exodus.query.metadata.ModelMetaData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;

// TODO: move this class to the associations semantics package

public class EntityOperations {

    private static final Logger logger = LoggerFactory.getLogger(EntityOperations.class);

    private EntityOperations() {
    }

    public static void remove(final Entity e) {
        /* two-phase remove:
           1. call destructors
           2. remove links and entities
        */

        remove(e, true, new HashSet());
        remove(e, false, new HashSet());
    }

    static void remove(final Entity e, boolean callDestructorPhase, Set processed) {
        if (e == null || ((TransientEntity) e).isRemoved()) return;
        TransientEntity reattached = TransientStoreUtil.reattach((TransientEntity) e);

        if (processed.contains(reattached)) return;

        TransientEntityStore store = (TransientEntityStore) reattached.getStore();

        ModelMetaData md = store.getModelMetaData();
        if (md != null) {
            // cascade delete
            EntityMetaData emd = md.getEntityMetaData(reattached.getType());
            if (emd != null) {
                if (callDestructorPhase) {
                    TransientStoreUtil.getPersistentClassInstance(reattached).destructor(reattached);
                }
                processed.add(reattached);
                // remove associations and cascade delete
                TransientStoreSession storeSession = (TransientStoreSession) store.getThreadSession();
                if (storeSession == null) {
                    throw new IllegalStateException("No current transient session!");
                }
                ConstraintsUtil.processOnDeleteConstraints(storeSession, reattached, emd, md, callDestructorPhase, processed);
            }
        }

        if (!callDestructorPhase) {
            // delete itself; the check is performed, because onDelete constraints could already delete entity 'e'
            if (!reattached.isRemoved()) reattached.delete();
        }
    }

    /**
     * Checks if entity e was removed
     *
     * @param e entity to check
     * @return true if e was removed, false if it wasn't removed at all
     */
    @SuppressWarnings({"ConstantConditions"})
    public static boolean isRemoved(@Nullable final Entity e) {
        if (e == null) {
            return true;
        }
        return TransientStoreUtil.isRemoved(e);
    }

    public static boolean isNew(@Nullable Entity e) {
        if (e == null) return false;
        e = TransientStoreUtil.reattach((TransientEntity) e);
        return e != null && ((TransientEntity) e).isNew();
    }

    public static boolean equals(Entity e1, Object e2) {
        if (e1 == e2) {
            return true;
        }

        return e1 != null && e1 instanceof TransientEntity && e1.equals(e2);
    }

    /**
     * Slow method! Use with care.
     *
     * @param entities iterable to index
     * @param i        queried element index
     * @return element at position i in entities iterable
     * @deprecated slow method. for testcases only.
     */
    public static Entity getElement(@NotNull Iterable entities, int i) {
        if (logger.isWarnEnabled()) {
            logger.warn("Slow method getElementOfMultiple() was called!");
        }

        int j = 0;
        for (Entity e : entities) {
            if (i == j++) {
                return e;
            }
        }

        throw new IllegalArgumentException("Out of bounds: " + i);
    }

    public static boolean hasChanges(@NotNull TransientEntity e) {
        final TransientEntity entity = TransientStoreUtil.reattach(e);

        return entity != null && entity.hasChanges();
    }

    public static boolean hasChanges(@NotNull TransientEntity e, String property) {
        final TransientEntity entity = TransientStoreUtil.reattach(e);

        return entity != null && entity.hasChanges(property);
    }

    public static boolean hasChanges(@NotNull TransientEntity e, String[] properties) {
        final TransientEntity entity = TransientStoreUtil.reattach(e);

        if (entity != null) {
            for (String property : properties) {
                if (entity.hasChanges(property)) return true;
            }
        }
        return false;
    }

    public static boolean hasChangesExcepting(@NotNull TransientEntity e, String[] properties) {
        final TransientEntity entity = TransientStoreUtil.reattach(e);

        return entity != null && entity.hasChangesExcepting(properties);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy