/*******************************************************************************
 * Copyright (c) 2004, 2007 Boeing.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Boeing - initial API and implementation
 *******************************************************************************/
package org.eclipse.osee.framework.skynet.core.relation;

import static org.eclipse.osee.framework.core.enums.DeletionFlag.EXCLUDE_DELETED;
import static org.eclipse.osee.framework.core.enums.DeletionFlag.INCLUDE_DELETED;
import static org.eclipse.osee.framework.core.enums.RelationSide.SIDE_A;
import static org.eclipse.osee.framework.core.enums.RelationSide.SIDE_B;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import org.eclipse.osee.framework.core.data.IOseeBranch;
import org.eclipse.osee.framework.core.data.IRelationSorterId;
import org.eclipse.osee.framework.core.data.IRelationType;
import org.eclipse.osee.framework.core.data.IRelationTypeSide;
import org.eclipse.osee.framework.core.enums.DeletionFlag;
import org.eclipse.osee.framework.core.enums.ModificationType;
import org.eclipse.osee.framework.core.enums.RelationOrderBaseTypes;
import org.eclipse.osee.framework.core.enums.RelationSide;
import org.eclipse.osee.framework.core.enums.RelationTypeMultiplicity;
import org.eclipse.osee.framework.core.exception.ArtifactDoesNotExist;
import org.eclipse.osee.framework.core.exception.MultipleArtifactsExist;
import org.eclipse.osee.framework.core.exception.OseeArgumentException;
import org.eclipse.osee.framework.core.exception.OseeCoreException;
import org.eclipse.osee.framework.core.model.type.RelationType;
import org.eclipse.osee.framework.core.util.Conditions;
import org.eclipse.osee.framework.database.core.ConnectionHandler;
import org.eclipse.osee.framework.database.core.IOseeStatement;
import org.eclipse.osee.framework.jdk.core.type.Pair;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
import org.eclipse.osee.framework.skynet.core.artifact.ArtifactCache;
import org.eclipse.osee.framework.skynet.core.artifact.BranchManager;
import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery;
import org.eclipse.osee.framework.skynet.core.internal.Activator;
import org.eclipse.osee.framework.skynet.core.relation.RelationLink.ArtifactLinker;
import org.eclipse.osee.framework.skynet.core.relation.order.RelationOrderData;
import org.eclipse.osee.framework.skynet.core.relation.order.RelationOrderFactory;
import org.eclipse.osee.framework.skynet.core.relation.order.RelationSorterProvider;
import org.eclipse.osee.framework.skynet.core.types.IArtifact;

/**
 * @author Ryan D. Brooks
 */
public class RelationManager {

   private static final String GET_DELETED_ARTIFACT =
      "SELECT DISTINCT %s_art_id, txs.branch_id FROM osee_txs txs, osee_relation_link rel WHERE txs.branch_id = ? AND txs.gamma_id = rel.gamma_id AND rel.rel_link_type_id = ? AND %s_art_id = ? AND txs.tx_current in (2,3)";

   private static final RelationSorterProvider relationSorterProvider = new RelationSorterProvider();
   private static final RelationOrderFactory relationOrderFactory = new RelationOrderFactory();

   private static final RelationCache relationCache = new RelationCache();

   /**
    * Store the newly instantiated relation from the perspective of relationSide in its appropriate order
    * 
    * @throws OseeCoreException
    */
   public static void manageRelation(RelationLink newRelation, RelationSide relationSide) throws OseeCoreException {
      Artifact artifact = ArtifactCache.getActive(newRelation.getArtifactId(relationSide), newRelation.getBranch());
      if (artifact != null) {
         List<RelationLink> artifactsRelations = relationCache.getAll(artifact);
         if (artifactsRelations == null) {
            artifactsRelations = new CopyOnWriteArrayList<RelationLink>();
         }

         // Verify that relation is unique by aArtId, bArtId and relTypeId; Needs to be cleaned up in DB, Only log problem.
         // Need to do this check before to catch the relations that are .equal but not ==
         for (RelationLink relation : artifactsRelations) {
            if (relation.getAArtifactId() == newRelation.getAArtifactId() && //
            relation.getBArtifactId() == newRelation.getBArtifactId() && //
            relation.getRelationType() == newRelation.getRelationType() && //
            relation != newRelation) {
               OseeLog.logf(Activator.class, Level.WARNING,
                  "Duplicate relation objects for same relation for RELATION 1 [%s] RELATION 2 [%s]", relation,
                  newRelation);
            }
         }

         if (artifactsRelations.contains(newRelation)) {
            // Always want to return if relation link is already managed
            return;
         }

         artifactsRelations.add(newRelation);
         relationCache.cache(artifact, newRelation);
      }
   }

   private static List<Artifact> getRelatedArtifactsUnSorted(Artifact artifact, IRelationType relationType, RelationSide relationSide) throws OseeCoreException {
      return getRelatedArtifacts(artifact, relationType, relationSide, false);
   }

   public static List<Artifact> getRelatedArtifacts(Artifact artifact, IRelationType relationType, RelationSide relationSide) throws OseeCoreException {
      return getRelatedArtifacts(artifact, relationType, relationSide, true);
   }

   @SuppressWarnings("unused")
   private static List<Artifact> getRelatedArtifacts(Artifact artifact, IRelationType relationType, RelationSide relationSide, boolean sort) throws OseeCoreException {
      if (relationSide == null) {
         throw new OseeArgumentException("RelationSide cannot be null");
      }
      List<RelationLink> selectedRelations = null;
      if (relationType == null) {
         selectedRelations = relationCache.getAll(artifact);
      } else {
         selectedRelations = relationCache.getAllByType(artifact, RelationTypeManager.getType(relationType));
      }

      List<Artifact> relatedArtifacts;

      if (selectedRelations == null) {
         relatedArtifacts = new ArrayList<Artifact>();
      } else {
         relatedArtifacts = new ArrayList<Artifact>(selectedRelations.size());

         Collection<Artifact> bulkLoadedArtifacts =
            ArtifactQuery.getArtifactListFromIds(
               getRelatedArtifactIds(selectedRelations, relationSide, DeletionFlag.EXCLUDE_DELETED),
               artifact.getBranch());

         for (RelationLink relation : selectedRelations) {
            if (!relation.isDeleted()) {
               try {
                  if (relation.getSide(artifact).isOppositeSide(relationSide)) {
                     relationSide = relation.getOppositeSide(artifact);
                     relatedArtifacts.add(relation.getArtifactOnOtherSide(artifact));
                  }
               } catch (ArtifactDoesNotExist ex) {
                  OseeLog.log(Activator.class, Level.WARNING, ex);
               }
            }
         }
         if (sort) {
            sort(artifact, relationType, relationSide, relatedArtifacts);
         }
      }
      return relatedArtifacts;
   }

   private static Collection<Integer> getRelatedArtifactIds(List<RelationLink> relations, RelationSide side, DeletionFlag allowDeleted) {
      Collection<Integer> ret = new HashSet<Integer>();
      if (relations != null) {
         for (RelationLink rel : relations) {
            if (allowDeleted == INCLUDE_DELETED || allowDeleted == EXCLUDE_DELETED && !rel.isDeleted()) {
               ret.add(rel.getArtifactId(side));
            }
         }
      }
      return ret;
   }

   public static Set<Artifact> getRelatedArtifacts(Collection<? extends Artifact> artifacts, int depth, IRelationTypeSide... relationEnums) throws OseeCoreException {
      return getRelatedArtifacts(artifacts, depth, EXCLUDE_DELETED, relationEnums);
   }

   public static Set<Artifact> getRelatedArtifacts(Collection<? extends Artifact> artifacts, int depth, DeletionFlag allowDeleted, IRelationTypeSide... relationEnums) throws OseeCoreException {
      Set<Artifact> relatedArtifacts = new HashSet<Artifact>(artifacts.size() * 8);
      Collection<Artifact> newArtifactsToSearch = new ArrayList<Artifact>(artifacts);
      Collection<Artifact> newArtifacts = new ArrayList<Artifact>();
      Set<Integer> relatedArtIds = new HashSet<Integer>();
      if (artifacts.isEmpty()) {
         return relatedArtifacts;
      }

      // loop through till either depth is reached or there are no more artifacts to search at this level
      for (int i = 0; i < depth && !newArtifactsToSearch.isEmpty(); i++) {
         relatedArtIds.clear();
         for (Artifact artifact : newArtifactsToSearch) {
            List<RelationLink> selectedRelations = new ArrayList<RelationLink>();
            if (relationEnums.length == 0) {
               /**
                * since getting relations by type will return the link between this artifact and it's parent, make sure
                * not to put it in the list of selected relations
                */
               List<RelationLink> relations = relationCache.getAll(artifact);
               for (RelationLink rel : relations) {
                  if (!rel.getArtifactA().equals(artifact)) {
                     selectedRelations.add(rel);
                  }
               }
               relatedArtIds.addAll(getRelatedArtifactIds(selectedRelations, RelationSide.SIDE_B, allowDeleted));
            } else {
               for (IRelationTypeSide relationEnum : relationEnums) {
                  Collection<RelationLink> links = relationCache.getAllByType(artifact, relationEnum);
                  if (links != null) {
                     for (RelationLink rel : links) {
                        /**
                         * since getting relations by type will return the link between this artifact and it's parent,
                         * make sure not to put it in the list of selected relations
                         */
                        if (rel.getArtifactId(relationEnum.getSide()) != artifact.getArtId()) {
                           selectedRelations.add(rel);
                        }
                     }
                  }
                  relatedArtIds.addAll(getRelatedArtifactIds(selectedRelations, relationEnum.getSide(), allowDeleted));
               }
            }
         }

         if (relatedArtIds.size() > 0) {
            IOseeBranch branch = artifacts.toArray(new Artifact[0])[0].getBranch();
            newArtifacts = ArtifactQuery.getArtifactListFromIds(relatedArtIds, branch, allowDeleted);
         }
         newArtifactsToSearch.clear();
         newArtifactsToSearch.addAll(newArtifacts);
         relatedArtifacts.addAll(newArtifacts);
      }
      return relatedArtifacts;
   }

   public static List<Artifact> getRelatedArtifacts(Artifact artifact, IRelationTypeSide relationType, DeletionFlag deletionFlag) throws OseeCoreException {
      List<Artifact> artifacts = getRelatedArtifacts(artifact, relationType, relationType.getSide());
      Collection<Integer> artIds = new ArrayList<Integer>();

      if (deletionFlag.areDeletedAllowed()) {
         Object[] formatArgs = relationType.getSide().isSideA() ? new Object[] {"a", "b"} : new Object[] {"b", "a"};
         IOseeStatement chStmt = ConnectionHandler.getStatement();
         try {
            String sql = String.format(GET_DELETED_ARTIFACT, formatArgs);
            chStmt.runPreparedQuery(sql, artifact.getFullBranch().getId(),
               Activator.getInstance().getIdentityService().getLocalId(relationType), artifact.getArtId());
            while (chStmt.next()) {
               int artId = chStmt.getInt(formatArgs[0] + "_art_id");
               artIds.add(artId);
            }
         } finally {
            chStmt.close();
         }

         List<Artifact> deletedArtifacts =
            ArtifactQuery.getArtifactListFromIds(artIds, artifact.getBranch(), INCLUDE_DELETED);

         for (Artifact art : deletedArtifacts) {
            if (art.isDeleted()) {
               artifacts.add(art);
            }
         }
      }

      return artifacts;
   }

   public static List<Artifact> getRelatedArtifactsUnSorted(Artifact artifact, IRelationTypeSide relationEnum) throws OseeCoreException {
      return getRelatedArtifactsUnSorted(artifact, relationEnum, relationEnum.getSide());
   }

   public static List<Artifact> getRelatedArtifacts(Artifact artifact, IRelationTypeSide relationEnum) throws OseeCoreException {
      return getRelatedArtifacts(artifact, relationEnum, relationEnum.getSide());
   }

   private static Artifact getRelatedArtifact(Artifact artifact, IRelationType relationType, RelationSide relationSide) throws OseeCoreException {
      List<Artifact> artifacts = getRelatedArtifactsUnSorted(artifact, relationType, relationSide);

      if (artifacts.isEmpty()) {
         throw new ArtifactDoesNotExist("There is no artifact related to [%s] by a relation of type [%s]", artifact,
            relationType);
      }

      if (artifacts.size() > 1) {
         throw new MultipleArtifactsExist(
            "There are %s artifacts related to \"%s\" by a relation of type \"%s\" on side %s instead of the expected 1.",
            artifacts.size(), artifact, relationType, relationSide);
      }
      return artifacts.get(0);
   }

   public static Artifact getRelatedArtifact(Artifact artifact, IRelationTypeSide relationEnum) throws OseeCoreException {
      return getRelatedArtifact(artifact, relationEnum, relationEnum.getSide());
   }

   public static int getRelatedArtifactsCount(Artifact artifact, IRelationTypeSide relationTypeEnum) {
      return getRelatedArtifactsCount(artifact, relationTypeEnum, relationTypeEnum.getSide());
   }

   public static int getRelatedArtifactsCount(Artifact artifact, IRelationType relationType, RelationSide relationSide) {
      List<RelationLink> selectedRelations = relationCache.getAllByType(artifact, relationType);

      int artifactCount = 0;
      if (selectedRelations != null) {
         for (RelationLink relation : selectedRelations) {
            if (!relation.isDeleted()) {
               if (relationSide == null) {
                  artifactCount++;
               } else {
                  // only select relations where the related artifact is on the side specified by relationEnum
                  // (and thus on the side opposite of "artifact")
                  if (relation.getSide(artifact) != relationSide) {
                     artifactCount++;
                  }
               }
            }
         }
      }

      return artifactCount;
   }

   public static void prepareRelationsForReload(Artifact artifact) {
      // weakness:  references held to links by other applications will continue to exist.
      //We do not want to drop relation links for historical artifacts because the relation manager will clobber the current artifacts relations.
      if (!artifact.isHistorical()) {
         relationCache.deCache(artifact);
      }
   }

   public static boolean hasDirtyLinks(Artifact artifact) {
      List<RelationLink> selectedRelations = relationCache.getAll(artifact);
      for (RelationLink relation : selectedRelations) {
         if (relation.isDirty()) {
            return true;
         }
      }
      return false;
   }

   /*
    * Return what relation is dirty otherwise null
    */
   public static String reportHasDirtyLinks(Artifact artifact) {
      List<RelationLink> selectedRelations = relationCache.getAll(artifact);
      if (selectedRelations != null) {
         for (RelationLink relation : selectedRelations) {
            if (relation.isDirty()) {
               try {
                  return String.format("Relation\n\n[%s]\n\naSide [%s]\n\nbSide [%s]", relation,
                     relation.getArtifactA(), relation.getArtifactB());
               } catch (OseeCoreException ex) {
                  OseeLog.log(Activator.class, Level.SEVERE, ex);
               }
            }
         }
      }
      return null;
   }

   public static List<RelationLink> getRelations(Artifact artifact, IRelationType relationType, RelationSide relationSide) throws OseeCoreException {
      List<RelationLink> selectedRelations =
         relationCache.getAllByType(artifact, RelationTypeManager.getType(relationType));
      if (selectedRelations == null) {
         return Collections.emptyList();
      }

      List<RelationLink> relations = new ArrayList<RelationLink>(selectedRelations.size());

      for (RelationLink relation : selectedRelations) {
         if (!relation.isDeleted()) {
            if (relationSide == null) {
               relations.add(relation);
            } else {
               // only select relations where the related artifact is on the side specified by relationEnum
               // (and thus on the side opposite of "artifact")
               if (relation.getSide(artifact) != relationSide) {
                  relations.add(relation);
               }
            }
         }
      }
      return relations;
   }

   public static void ensureRelationCanBeAdded(IRelationType relationType, Artifact artifactA, Artifact artifactB) throws OseeCoreException {
      // For now, relations can not be cross branch.  Ensure that both artifacts are on same branch
      ensureSameBranch(artifactA, artifactB);
      ensureSideWillSupport(artifactA, relationType, RelationSide.SIDE_A, 1);
      ensureSideWillSupport(artifactB, relationType, RelationSide.SIDE_B, 1);
   }

   private static void ensureSameBranch(Artifact a, Artifact b) throws OseeArgumentException {
      if (!a.getBranch().equals(b.getBranch())) {
         throw new OseeArgumentException("Cross branch linking is not yet supported.");
      }
   }

   /**
    * Check whether artifactCount number of additional artifacts of type artifactType can be related to the artifact on
    * side relationSide for relations of type relationType
    */
   private static void ensureSideWillSupport(Artifact artifact, IRelationType relationTypeToken, RelationSide relationSide, int artifactCount) throws OseeCoreException {
      RelationType relationType = RelationTypeManager.getType(relationTypeToken);
      if (!relationType.isArtifactTypeAllowed(relationSide, artifact.getArtifactType())) {
         throw new OseeArgumentException(
            String.format(
               "Artifact [%s] of type [%s] does not belong on side [%s] of relation [%s] - only artifacts of type [%s] are allowed",
               artifact.getName(), artifact.getArtifactTypeName(), relationType.getSideName(relationSide),
               relationType.getName(), relationType.getArtifactType(relationSide)));
      }

      // ensure that we can add artifactCount number or artifacts to the side opposite this artifact
      int nextCount = getRelatedArtifactsCount(artifact, relationType, relationSide.oppositeSide());
      nextCount += artifactCount;
      RelationTypeMultiplicity multiplicity = relationType.getMultiplicity();
      if (!multiplicity.isWithinLimit(relationSide.oppositeSide(), nextCount)) {
         throw new OseeArgumentException(
            String.format(
               "Artifact [%s] of type [%s] cannot be added to [%s] of relation [%s] because doing so would exceed the side maximum of [%s] for this artifact type",
               artifact.getName(), artifact.getArtifactTypeName(), relationSide.toString(), relationType.getName(),
               multiplicity.asLimitLabel(relationSide.oppositeSide())));
      }
   }

   public static void deleteRelation(IRelationType relationType, Artifact artifactA, Artifact artifactB) throws OseeCoreException {
      RelationLink relation =
         relationCache.getLoadedRelation(artifactA, artifactA.getArtId(), artifactB.getArtId(), relationType,
            DeletionFlag.EXCLUDE_DELETED);
      Conditions.checkNotNull(relation, "relationLink",
         "A relation link of type [%s] does exist in the cache between a artifact %d and b artifact %d", relationType,
         artifactA.getArtId(), artifactB.getArtId());
      relation.delete(true);

      updateOrderListOnDelete(artifactA, relationType, RelationSide.SIDE_B,
         getRelatedArtifacts(artifactA, relationType, RelationSide.SIDE_B));
      updateOrderListOnDelete(artifactB, relationType, RelationSide.SIDE_A,
         getRelatedArtifacts(artifactB, relationType, RelationSide.SIDE_A));
   }

   public static void deleteRelationsAll(Artifact artifact, boolean reorderRelations) throws OseeCoreException {
      List<RelationLink> selectedRelations = relationCache.getAll(artifact);
      Set<Pair<IRelationType, RelationSide>> typesToUpdate = new HashSet<Pair<IRelationType, RelationSide>>();
      if (selectedRelations != null) {
         for (RelationLink relation : selectedRelations) {
            typesToUpdate.add(new Pair<IRelationType, RelationSide>(relation.getRelationType(),
               relation.getOppositeSide(artifact)));
            relation.delete(reorderRelations);
         }
      }

      for (Pair<IRelationType, RelationSide> type : typesToUpdate) {
         updateOrderListOnDelete(artifact, type.getFirst(), type.getSecond(),
            getRelatedArtifacts(artifact, type.getFirst(), type.getSecond()));
      }
   }

   public static void deleteRelations(Artifact artifact, IRelationType relationType, RelationSide relationSide) throws OseeCoreException {
      List<RelationLink> selectedRelations = relationCache.getAllByType(artifact, relationType);
      if (selectedRelations != null) {
         for (RelationLink relation : selectedRelations) {
            if (relation.getSide(artifact) != relationSide) {
               relation.delete(true);
            }
         }
      }

      updateOrderListOnDelete(artifact, relationType, relationSide,
         getRelatedArtifacts(artifact, relationType, relationSide));
   }

   /**
    * Remove all relations stored in the list awaiting to be deleted.
    */
   public static void purgeRelationsFor(Artifact artifact) throws OseeCoreException {
      Collection<RelationLink> links = relationCache.getAll(artifact);
      if (!links.isEmpty()) {
         List<Object[]> batchArgs = new ArrayList<Object[]>(links.size());
         String PURGE_RELATION = "delete from osee_relation_link WHERE rel_link_id = ?";
         for (RelationLink link : links) {
            batchArgs.add(new Object[] {link.getId()});
            link.markAsPurged();
         }
         ConnectionHandler.runBatchUpdate(PURGE_RELATION, batchArgs);
      }
   }

   public static void addRelation(IRelationType relationType, Artifact artifactA, Artifact artifactB, String rationale) throws OseeCoreException {
      addRelation(RelationOrderBaseTypes.PREEXISTING, relationType, artifactA, artifactB, rationale);
   }

   public static void addRelation(IRelationSorterId sorterId, IRelationType relationTypeToken, Artifact artifactA, Artifact artifactB, String rationale) throws OseeCoreException {
      Conditions.checkExpressionFailOnTrue(artifactA.equals(artifactB), "Not valid to relate artifact [%s] to itself",
         artifactA);
      RelationLink relation =
         relationCache.getLoadedRelation(artifactA, artifactA.getArtId(), artifactB.getArtId(), relationTypeToken,
            INCLUDE_DELETED);

      RelationType relationType = RelationTypeManager.getType(relationTypeToken);
      if (relation == null) {
         ensureRelationCanBeAdded(relationTypeToken, artifactA, artifactB);
         relation =
            getOrCreate(artifactA.getArtId(), artifactB.getArtId(), artifactA.getBranch(), relationType, 0, 0,
               rationale, ModificationType.NEW);
         relation.setDirty();

         RelationTypeSideSorter sorter = createTypeSideSorter(artifactA, relationTypeToken, RelationSide.SIDE_B);
         sorter.addItem(sorterId, artifactB);

      } else if (relation.isDeleted()) {
         relation.undelete();
         RelationTypeSideSorter sorter = createTypeSideSorter(artifactA, relationTypeToken, RelationSide.SIDE_B);
         sorter.addItem(sorterId, artifactB);
      }
   }

   public static RelationLink getRelationLink(Artifact artifactA, Artifact artifactB, IRelationType relationType) throws OseeCoreException {
      List<RelationLink> relationLinks = relationCache.getAllByType(artifactA, relationType);
      for (RelationLink relation : relationLinks) {
         if (relation.getArtifactB().equals(artifactB)) {
            return relation;
         }
      }
      throw new OseeCoreException("Unable to find a relation link for type[%s] artA[%s] artB[%s]",
         relationType.getName(), artifactA.getName(), artifactB.getName());
   }

   public static RelationSorterProvider getSorterProvider() {
      return relationSorterProvider;
   }

   public static List<IRelationSorterId> getRelationOrderTypes() {
      return relationSorterProvider.getAllRelationOrderIds();
   }

   public static RelationTypeSideSorter createTypeSideSorter(IArtifact artifact, IRelationType relationType, RelationSide side) throws OseeCoreException {
      return relationOrderFactory.createTypeSideSorter(relationSorterProvider, artifact, relationType, side);
   }

   public static RelationOrderData createRelationOrderData(IArtifact artifact) throws OseeCoreException {
      return relationOrderFactory.createRelationOrderData(artifact);
   }

   public static void setRelationOrder(IArtifact artifact, IRelationType relationType, RelationSide side, IRelationSorterId orderId, List<Artifact> relatives) throws OseeCoreException {
      RelationTypeSideSorter sorter = createTypeSideSorter(artifact, relationType, side);
      sorter.setOrder(relatives, orderId);
   }

   private static void sort(IArtifact artifact, IRelationType type, RelationSide side, List<Artifact> listToOrder) throws OseeCoreException {
      if (type == null || side == null || listToOrder.size() <= 1) {
         return;
      }
      RelationTypeSideSorter sorter = createTypeSideSorter(artifact, type, side);
      sorter.sort(listToOrder);
   }

   private static void updateOrderListOnDelete(Artifact artifact, IRelationType relationType, RelationSide relationSide, List<Artifact> relatives) throws OseeCoreException {
      RelationTypeSideSorter sorter = createTypeSideSorter(artifact, relationType, relationSide);
      sorter.setOrder(relatives, sorter.getSorterId());
   }

   public static void deCache(Artifact artifact) {
      relationCache.deCache(artifact);
   }

   /**
    * Return existing RelationLink or create new one. This needs to be synchronized so two threads don't create the same
    * link object twice.
    * 
    * @param relationId 0 or relationId if already created
    * @throws OseeCoreException
    */
   public static synchronized RelationLink getOrCreate(int aArtifactId, int bArtifactId, IOseeBranch branch, RelationType relationType, int relationId, int gammaId, String rationale, ModificationType modificationType) throws OseeCoreException {
      RelationLink relation = null;
      if (relationId != 0) {
         relation = getLoadedRelationById(relationId, aArtifactId, bArtifactId, branch);
      } else {
         relation = getLoadedRelation(relationType, aArtifactId, bArtifactId, branch);
      }
      if (relation == null) {
         relation =
            new RelationLink(new RelationArtifactLinker(), aArtifactId, bArtifactId, branch, relationType, relationId,
               gammaId, rationale, modificationType);
      }
      manageRelation(relation, RelationSide.SIDE_A);
      manageRelation(relation, RelationSide.SIDE_B);

      return relation;
   }

   public static RelationLink getLoadedRelation(IRelationType relationType, int aArtifactId, int bArtifactId, IOseeBranch branch) {
      return relationCache.getLoadedRelation(relationType, aArtifactId, bArtifactId, branch);
   }

   public static RelationLink getLoadedRelationById(int relLinkId, int aArtifactId, int bArtifactId, IOseeBranch branch) {
      return relationCache.getByRelIdOnArtifact(relLinkId, aArtifactId, bArtifactId, branch);
   }

   public static List<RelationLink> getRelationsAll(Artifact artifact, DeletionFlag deletionFlag) {
      return relationCache.getRelations(artifact, deletionFlag);
   }

   private static final class RelationArtifactLinker implements ArtifactLinker {

      @Override
      public Artifact getArtifact(int artifactId, IOseeBranch branch) throws OseeCoreException {
         Artifact relatedArtifact = ArtifactCache.getActive(artifactId, branch);
         if (relatedArtifact == null) {
            return ArtifactQuery.getArtifactFromId(artifactId, branch);
         }
         return relatedArtifact;
      }

      @Override
      public String getLazyArtifactName(int artifactId, IOseeBranch branch) {
         Artifact artifact = null;
         try {
            artifact = ArtifactCache.getActive(artifactId, branch);
         } catch (OseeCoreException ex) {
            OseeLog.log(Activator.class, Level.SEVERE, ex);
         }
         return artifact != null ? artifact.getName() : "Unloaded";
      }

      @Override
      public void deleteFromRelationOrder(Artifact aArtifact, Artifact bArtifact, IRelationType relationType) throws OseeCoreException {
         RelationTypeSideSorter aSorter = RelationManager.createTypeSideSorter(aArtifact, relationType, SIDE_B);
         aSorter.removeItem(null, bArtifact);

         RelationTypeSideSorter bSorter = RelationManager.createTypeSideSorter(bArtifact, relationType, SIDE_A);
         bSorter.removeItem(null, aArtifact);
      }

      @Override
      public void updateCachedArtifact(int artId, IOseeBranch branch) {
         try {
            ArtifactCache.updateCachedArtifact(artId, BranchManager.getBranchId(branch));
         } catch (OseeCoreException ex) {
            OseeLog.log(Activator.class, Level.SEVERE, ex);
         }
      }
   }
}
