/*
 * Copyright (c) 2009-2013 Eike Stepper (Berlin, Germany) and others.
 * 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:
 *    Eike Stepper - initial API and implementation
 *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
 *    Stefan Winkler - 249610: [DB] Support external references (Implementation)
 *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
 */
package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;

import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.model.CDOModelUtil;
import org.eclipse.emf.cdo.common.revision.CDOList;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;

import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBDatabase;
import org.eclipse.net4j.db.IDBPreparedStatement;
import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability;
import org.eclipse.net4j.db.IDBSchemaTransaction;
import org.eclipse.net4j.db.ddl.IDBField;
import org.eclipse.net4j.db.ddl.IDBIndex;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
import org.eclipse.net4j.util.om.trace.ContextTracer;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.FeatureMapUtil;

import org.eclipse.core.runtime.Assert;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Eike Stepper
 * @since 2.0
 */
public abstract class AbstractHorizontalClassMapping implements IClassMapping, IMappingConstants
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractHorizontalClassMapping.class);

  private EClass eClass;

  private IDBTable table;

  private AbstractHorizontalMappingStrategy mappingStrategy;

  private List<ITypeMapping> valueMappings;

  private List<IListMapping> listMappings;

  private Map<EStructuralFeature, IDBField> listSizeFields;

  private Map<EStructuralFeature, IDBField> unsettableFields;

  private String sqlSelectForHandle;

  private String sqlSelectForChangeSet;

  public AbstractHorizontalClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass)
  {
    this.mappingStrategy = mappingStrategy;
    this.eClass = eClass;

    initTable();
    initFields();
    initSQLStrings();
  }

  private void initTable()
  {
    final String tableName = mappingStrategy.getTableName(eClass);
    final DBType idType = mappingStrategy.getStore().getIDHandler().getDBType();
    final int idLength = mappingStrategy.getStore().getIDColumnLength();

    IDBDatabase database = mappingStrategy.getStore().getDatabase();
    table = database.getSchema().getTable(tableName);
    if (table == null)
    {
      IDBSchemaTransaction schemaTransaction = database.getSchemaTransaction();
      IDBSchema workingCopy = schemaTransaction.getWorkingCopy();

      table = workingCopy.addTable(tableName);
      table.addField(ATTRIBUTES_ID, idType, idLength, true);
      table.addField(ATTRIBUTES_VERSION, DBType.INTEGER, true);

      IDBField branchField = addBranchField(table);

      table.addField(ATTRIBUTES_CREATED, DBType.BIGINT, true);
      table.addField(ATTRIBUTES_REVISED, DBType.BIGINT, true);
      table.addField(ATTRIBUTES_RESOURCE, idType, idLength, true);
      table.addField(ATTRIBUTES_CONTAINER, idType, idLength, true);
      table.addField(ATTRIBUTES_FEATURE, DBType.INTEGER, true);

      IDBIndex primaryKey = table.addIndex(IDBIndex.Type.PRIMARY_KEY, ATTRIBUTES_ID, ATTRIBUTES_VERSION);
      if (branchField != null)
      {
        primaryKey.addIndexField(branchField);
      }

      table.addIndex(IDBIndex.Type.NON_UNIQUE, ATTRIBUTES_ID, ATTRIBUTES_REVISED);
    }
  }

  private void initFields()
  {
    final EStructuralFeature[] allPersistentFeatures = CDOModelUtil.getClassInfo(eClass).getAllPersistentFeatures();
    if (allPersistentFeatures == null)
    {
      valueMappings = Collections.emptyList();
      listMappings = Collections.emptyList();
    }
    else
    {
      valueMappings = new ArrayList<ITypeMapping>();
      listMappings = new ArrayList<IListMapping>();

      boolean hasUnsettableFeatures = false;
      for (EStructuralFeature feature : allPersistentFeatures)
      {
        String fieldName = mappingStrategy.getFieldName(feature);
        if (feature.isMany())
        {
          IListMapping mapping = null;
          if (FeatureMapUtil.isFeatureMap(feature))
          {
            mapping = mappingStrategy.createFeatureMapMapping(eClass, feature);
          }
          else
          {
            mapping = mappingStrategy.createListMapping(eClass, feature);
          }

          listMappings.add(mapping);

          // Add field for list sizes
          if (listSizeFields == null)
          {
            listSizeFields = new LinkedHashMap<EStructuralFeature, IDBField>();
          }

          IDBField field = table.getField(fieldName);
          if (field == null)
          {
            field = table.addField(fieldName, DBType.INTEGER);
          }

          listSizeFields.put(feature, field);
        }
        else
        {
          ITypeMapping mapping = mappingStrategy.createValueMapping(feature);
          IDBField field = table.getField(fieldName);
          if (field == null)
          {
            mapping.createDBField(table, fieldName);
          }
          else
          {
            mapping.setDBField(table, fieldName);
          }

          valueMappings.add(mapping);

          if (feature.isUnsettable())
          {
            hasUnsettableFeatures = true;
          }
        }
      }

      // Add unsettable fields to end of table
      if (hasUnsettableFeatures)
      {
        unsettableFields = new LinkedHashMap<EStructuralFeature, IDBField>();
        for (EStructuralFeature feature : allPersistentFeatures)
        {
          if (!feature.isMany() && feature.isUnsettable())
          {
            String fieldName = mappingStrategy.getUnsettableFieldName(feature);
            IDBField field = table.getField(fieldName);
            if (field == null)
            {
              field = table.addField(fieldName, DBType.BOOLEAN);
            }

            unsettableFields.put(feature, field);
          }
        }
      }
    }
  }

  private void initSQLStrings()
  {
    // ----------- Select all revisions (for handleRevisions) ---
    StringBuilder builder = new StringBuilder("SELECT "); //$NON-NLS-1$
    builder.append(ATTRIBUTES_ID);
    builder.append(", "); //$NON-NLS-1$
    builder.append(ATTRIBUTES_VERSION);
    builder.append(" FROM "); //$NON-NLS-1$
    builder.append(table);
    sqlSelectForHandle = builder.toString();

    // ----------- Select all revisions (for readChangeSet) ---
    builder = new StringBuilder("SELECT DISTINCT "); //$NON-NLS-1$
    builder.append(ATTRIBUTES_ID);
    builder.append(" FROM "); //$NON-NLS-1$
    builder.append(table);
    builder.append(" WHERE "); //$NON-NLS-1$
    sqlSelectForChangeSet = builder.toString();
  }

  protected IDBField addBranchField(IDBTable table)
  {
    return null;
  }

  /**
   * Read the revision's values from the DB.
   *
   * @return <code>true</code> if the revision has been read successfully.<br>
   *         <code>false</code> if the revision does not exist in the DB.
   */
  protected final boolean readValuesFromStatement(PreparedStatement stmt, InternalCDORevision revision,
      IDBStoreAccessor accessor)
  {
    ResultSet resultSet = null;

    try
    {
      if (TRACER.isEnabled())
      {
        TRACER.format("Executing Query: {0}", stmt.toString()); //$NON-NLS-1$
      }

      stmt.setMaxRows(1); // Optimization: only 1 row

      resultSet = stmt.executeQuery();
      if (!resultSet.next())
      {
        if (TRACER.isEnabled())
        {
          TRACER.format("Resultset was empty"); //$NON-NLS-1$
        }

        return false;
      }

      revision.setVersion(resultSet.getInt(ATTRIBUTES_VERSION));

      long timeStamp = resultSet.getLong(ATTRIBUTES_CREATED);

      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
      CDOBranchPoint branchPoint = revision.getBranch().getPoint(timeStamp);

      revision.setBranchPoint(branchPoint);
      revision.setRevised(resultSet.getLong(ATTRIBUTES_REVISED));
      revision.setResourceID(idHandler.getCDOID(resultSet, ATTRIBUTES_RESOURCE));
      revision.setContainerID(idHandler.getCDOID(resultSet, ATTRIBUTES_CONTAINER));
      revision.setContainingFeatureID(resultSet.getInt(ATTRIBUTES_FEATURE));

      for (ITypeMapping mapping : valueMappings)
      {
        EStructuralFeature feature = mapping.getFeature();
        if (feature.isUnsettable())
        {
          IDBField field = unsettableFields.get(feature);
          if (!resultSet.getBoolean(field.getName()))
          {
            // isSet==false -- setValue: null
            revision.setValue(feature, null);
            continue;
          }
        }

        mapping.readValueToRevision(resultSet, revision);
      }

      if (listSizeFields != null)
      {
        for (Map.Entry<EStructuralFeature, IDBField> listSizeEntry : listSizeFields.entrySet())
        {
          EStructuralFeature feature = listSizeEntry.getKey();
          IDBField field = listSizeEntry.getValue();
          int size = resultSet.getInt(field.getName());

          // ensure the listSize (TODO: remove assertion)
          CDOList list = revision.getList(feature, size);

          for (int i = 0; i < size; i++)
          {
            list.add(InternalCDOList.UNINITIALIZED);
          }

          if (list.size() != size)
          {
            Assert.isTrue(false);
          }
        }
      }

      return true;
    }
    catch (SQLException ex)
    {
      throw new DBException(ex);
    }
    finally
    {
      DBUtil.close(resultSet);
    }
  }

  protected final void readLists(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
  {
    for (IListMapping listMapping : listMappings)
    {
      listMapping.readValues(accessor, revision, listChunk);
    }
  }

  protected final IMappingStrategy getMappingStrategy()
  {
    return mappingStrategy;
  }

  public final EClass getEClass()
  {
    return eClass;
  }

  protected final Map<EStructuralFeature, IDBField> getUnsettableFields()
  {
    return unsettableFields;
  }

  protected final Map<EStructuralFeature, IDBField> getListSizeFields()
  {
    return listSizeFields;
  }

  public final List<ITypeMapping> getValueMappings()
  {
    return valueMappings;
  }

  public final ITypeMapping getValueMapping(EStructuralFeature feature)
  {
    for (ITypeMapping mapping : valueMappings)
    {
      if (mapping.getFeature() == feature)
      {
        return mapping;
      }
    }

    return null;
  }

  public final List<IListMapping> getListMappings()
  {
    return listMappings;
  }

  public final IListMapping getListMapping(EStructuralFeature feature)
  {
    for (IListMapping mapping : listMappings)
    {
      if (mapping.getFeature() == feature)
      {
        return mapping;
      }
    }

    throw new IllegalArgumentException("List mapping for feature " + feature + " does not exist"); //$NON-NLS-1$ //$NON-NLS-2$
  }

  protected final IDBTable getTable()
  {
    return table;
  }

  public List<IDBTable> getDBTables()
  {
    List<IDBTable> tables = new ArrayList<IDBTable>();
    tables.add(table);

    for (IListMapping listMapping : listMappings)
    {
      tables.addAll(listMapping.getDBTables());
    }

    return tables;
  }

  @Override
  public String toString()
  {
    return MessageFormat.format("{0}[{1} -> {2}]", getClass().getSimpleName(), eClass, table);
  }

  protected void checkDuplicateResources(IDBStoreAccessor accessor, CDORevision revision) throws IllegalStateException
  {
    CDOID folderID = (CDOID)revision.data().getContainerID();
    String name = (String)revision.data().get(EresourcePackage.eINSTANCE.getCDOResourceNode_Name(), 0);

    CDOID existingID = accessor.readResourceID(folderID, name, revision.getBranch().getHead());
    if (existingID != null && !existingID.equals(revision.getID()))
    {
      throw new IllegalStateException("Duplicate resource node in folder " + folderID + ": " + name); //$NON-NLS-1$ //$NON-NLS-2$
    }
  }

  protected void writeLists(IDBStoreAccessor accessor, InternalCDORevision revision)
  {
    for (IListMapping listMapping : listMappings)
    {
      listMapping.writeValues(accessor, revision);
    }
  }

  public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise,
      OMMonitor monitor)
  {
    Async async = null;
    monitor.begin(10);

    try
    {
      try
      {
        async = monitor.forkAsync();
        CDOID id = revision.getID();
        if (mapType)
        {
          long timeStamp = revision.getTimeStamp();
          mappingStrategy.putObjectType(accessor, timeStamp, id, eClass);
        }
        else if (revise)
        {
          long revised = revision.getTimeStamp() - 1;
          reviseOldRevision(accessor, id, revision.getBranch(), revised);
          for (IListMapping mapping : getListMappings())
          {
            mapping.objectDetached(accessor, id, revised);
          }
        }
      }
      finally
      {
        if (async != null)
        {
          async.stop();
        }
      }

      try
      {
        async = monitor.forkAsync();
        if (revision.isResourceNode())
        {
          checkDuplicateResources(accessor, revision);
        }
      }
      finally
      {
        if (async != null)
        {
          async.stop();
        }
      }

      try
      {
        // Write attribute table always (even without modeled attributes!)
        async = monitor.forkAsync();
        writeValues(accessor, revision);
      }
      finally
      {
        if (async != null)
        {
          async.stop();
        }
      }

      try
      {
        // Write list tables only if they exist
        if (listMappings != null)
        {
          async = monitor.forkAsync(7);
          writeLists(accessor, revision);
        }
        else
        {
          monitor.worked(7);
        }
      }
      finally
      {
        if (async != null)
        {
          async.stop();
        }
      }
    }
    finally
    {
      monitor.done();
    }
  }

  public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime,
      CDORevisionHandler handler)
  {
    // branch parameter is ignored, because either it is null or main branch.
    // this does not make any difference for non-branching store.
    // see #handleRevisions() implementation in HorizontalBranchingClassMapping
    // for branch handling.

    IRepository repository = accessor.getStore().getRepository();
    CDORevisionManager revisionManager = repository.getRevisionManager();
    CDOBranchManager branchManager = repository.getBranchManager();

    // TODO: test for timeStamp == INVALID_TIME and encode revision.isValid() as WHERE instead of fetching all revisions
    // in order to increase performance

    StringBuilder builder = new StringBuilder(sqlSelectForHandle);

    int timeParameters = 0;
    if (timeStamp != CDOBranchPoint.INVALID_DATE)
    {
      if (exactTime)
      {
        if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
        {
          builder.append(" WHERE "); //$NON-NLS-1$
          builder.append(ATTRIBUTES_CREATED);
          builder.append("=?"); //$NON-NLS-1$
          timeParameters = 1;
        }
      }
      else
      {
        builder.append(" WHERE "); //$NON-NLS-1$
        if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
        {
          builder.append(ATTRIBUTES_CREATED);
          builder.append(">=?"); //$NON-NLS-1$
          builder.append(" AND ("); //$NON-NLS-1$
          builder.append(ATTRIBUTES_REVISED);
          builder.append("<=? OR "); //$NON-NLS-1$
          builder.append(ATTRIBUTES_REVISED);
          builder.append("="); //$NON-NLS-1$
          builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
          builder.append(")"); //$NON-NLS-1$
          timeParameters = 2;
        }
        else
        {
          builder.append(ATTRIBUTES_REVISED);
          builder.append("="); //$NON-NLS-1$
          builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
        }
      }
    }

    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(builder.toString(), ReuseProbability.LOW);
    ResultSet resultSet = null;

    try
    {
      for (int i = 0; i < timeParameters; i++)
      {
        stmt.setLong(i + 1, timeStamp);
      }

      resultSet = stmt.executeQuery();
      while (resultSet.next())
      {
        CDOID id = idHandler.getCDOID(resultSet, 1);
        int version = resultSet.getInt(2);

        if (version >= CDOBranchVersion.FIRST_VERSION)
        {
          InternalCDORevision revision = (InternalCDORevision)revisionManager.getRevisionByVersion(id,
              branchManager.getMainBranch().getVersion(version), CDORevision.UNCHUNKED, true);

          if (!handler.handleRevision(revision))
          {
            break;
          }
        }
      }
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(resultSet);
      DBUtil.close(stmt);
    }
  }

  public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments)
  {
    StringBuilder builder = new StringBuilder(sqlSelectForChangeSet);
    boolean isFirst = true;

    for (int i = 0; i < segments.length; i++)
    {
      if (isFirst)
      {
        isFirst = false;
      }
      else
      {
        builder.append(" OR "); //$NON-NLS-1$
      }

      builder.append(ATTRIBUTES_CREATED);
      builder.append(">=?"); //$NON-NLS-1$
      builder.append(" AND ("); //$NON-NLS-1$
      builder.append(ATTRIBUTES_REVISED);
      builder.append("<=? OR "); //$NON-NLS-1$
      builder.append(ATTRIBUTES_REVISED);
      builder.append("="); //$NON-NLS-1$
      builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
      builder.append(")"); //$NON-NLS-1$
    }

    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(builder.toString(), ReuseProbability.LOW);
    ResultSet resultSet = null;

    Set<CDOID> result = new HashSet<CDOID>();

    try
    {
      int column = 1;
      for (CDOChangeSetSegment segment : segments)
      {
        stmt.setLong(column++, segment.getTimeStamp());
        stmt.setLong(column++, segment.getEndTime());
      }

      resultSet = stmt.executeQuery();
      while (resultSet.next())
      {
        CDOID id = idHandler.getCDOID(resultSet, 1);
        result.add(id);
      }

      return result;
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(resultSet);
      DBUtil.close(stmt);
    }
  }

  public void detachObject(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp,
      OMMonitor monitor)
  {
    Async async = null;
    monitor.begin(1 + listMappings.size());

    try
    {
      if (version >= CDOBranchVersion.FIRST_VERSION)
      {
        reviseOldRevision(accessor, id, branch, timeStamp - 1);
      }

      detachAttributes(accessor, id, version, branch, timeStamp, monitor.fork());

      // notify list mappings so they can clean up
      for (IListMapping mapping : getListMappings())
      {
        try
        {
          async = monitor.forkAsync();
          mapping.objectDetached(accessor, id, timeStamp);
        }
        finally
        {
          if (async != null)
          {
            async.stop();
          }
        }
      }
    }
    finally
    {
      monitor.done();
    }
  }

  public void rawDelete(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, OMMonitor monitor)
  {
    Async async = null;
    monitor.begin(1 + listMappings.size());

    try
    {
      rawDeleteAttributes(accessor, id, branch, version, monitor.fork());

      // notify list mappings so they can clean up
      for (IListMapping mapping : getListMappings())
      {
        if (mapping instanceof AbstractBasicListTableMapping)
        {
          try
          {
            async = monitor.forkAsync();

            AbstractBasicListTableMapping m = (AbstractBasicListTableMapping)mapping;
            m.rawDeleted(accessor, id, branch, version);
          }
          finally
          {
            if (async != null)
            {
              async.stop();
            }
          }
        }
        else
        {
          throw new UnsupportedOperationException("rawDeleted() is not supported by " + mapping.getClass().getName());
        }
      }
    }
    finally
    {
      monitor.done();
    }
  }

  protected abstract void rawDeleteAttributes(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, int version,
      OMMonitor fork);

  public final boolean queryXRefs(IDBStoreAccessor accessor, QueryXRefsContext context, String idString)
  {
    String tableName = table.getName();
    List<EReference> refs = context.getSourceCandidates().get(eClass);
    List<EReference> scalarRefs = new ArrayList<EReference>();

    for (EReference ref : refs)
    {
      if (ref.isMany())
      {
        IListMapping listMapping = getListMapping(ref);
        String where = getListXRefsWhere(context);

        boolean more = listMapping.queryXRefs(accessor, tableName, where, context, idString);
        if (!more)
        {
          return false;
        }
      }
      else
      {
        scalarRefs.add(ref);
      }
    }

    if (!scalarRefs.isEmpty())
    {
      boolean more = queryScalarXRefs(accessor, scalarRefs, context, idString);
      if (!more)
      {
        return false;
      }
    }

    return true;
  }

  protected final boolean queryScalarXRefs(IDBStoreAccessor accessor, List<EReference> scalarRefs,
      QueryXRefsContext context, String idString)
  {
    String tableName = table.getName();
    String where = getListXRefsWhere(context);

    for (EReference ref : scalarRefs)
    {
      ITypeMapping valueMapping = getValueMapping(ref);
      String valueField = valueMapping.getField().getName();

      StringBuilder builder = new StringBuilder();
      builder.append("SELECT ");
      builder.append(ATTRIBUTES_ID);
      builder.append(", ");
      builder.append(valueField);
      builder.append(" FROM ");
      builder.append(tableName);
      builder.append(" WHERE ");
      builder.append(ATTRIBUTES_VERSION);
      builder.append(">0 AND ");
      builder.append(where);
      builder.append(" AND ");
      builder.append(valueField);
      builder.append(" IN ");
      builder.append(idString);
      String sql = builder.toString();
      if (TRACER.isEnabled())
      {
        TRACER.format("Query XRefs (attributes): {0}", sql);
      }

      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
      IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sql, ReuseProbability.MEDIUM);
      ResultSet resultSet = null;

      try
      {
        resultSet = stmt.executeQuery();
        while (resultSet.next())
        {
          CDOID sourceID = idHandler.getCDOID(resultSet, 1);
          CDOID targetID = idHandler.getCDOID(resultSet, 2);

          boolean more = context.addXRef(targetID, sourceID, ref, 0);
          if (TRACER.isEnabled())
          {
            TRACER.format("  add XRef to context: src={0}, tgt={1}, idx=0", sourceID, targetID);
          }

          if (!more)
          {
            if (TRACER.isEnabled())
            {
              TRACER.format("  result limit reached. Ignoring further results.");
            }

            return false;
          }
        }
      }
      catch (SQLException ex)
      {
        throw new DBException(ex);
      }
      finally
      {
        DBUtil.close(resultSet);
        DBUtil.close(stmt);
      }
    }

    return true;
  }

  protected abstract String getListXRefsWhere(QueryXRefsContext context);

  protected abstract void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch,
      long timeStamp, OMMonitor fork);

  protected abstract void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long timeStamp);

  protected abstract void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision);

  protected static void appendTypeMappingNames(StringBuilder builder, Collection<ITypeMapping> typeMappings)
  {
    if (typeMappings != null)
    {
      for (ITypeMapping typeMapping : typeMappings)
      {
        builder.append(", "); //$NON-NLS-1$
        builder.append(typeMapping.getField());
      }
    }
  }

  protected static void appendFieldNames(StringBuilder builder, Map<EStructuralFeature, IDBField> fields)
  {
    if (fields != null)
    {
      for (IDBField field : fields.values())
      {
        builder.append(", "); //$NON-NLS-1$
        builder.append(field);
      }
    }
  }

  protected static void appendTypeMappingParameters(StringBuilder builder, Collection<ITypeMapping> typeMappings)
  {
    if (typeMappings != null)
    {
      for (int i = 0; i < typeMappings.size(); i++)
      {
        builder.append(", ?"); //$NON-NLS-1$
      }
    }
  }

  protected static void appendFieldParameters(StringBuilder builder, Map<EStructuralFeature, IDBField> fields)
  {
    if (fields != null)
    {
      for (int i = 0; i < fields.size(); i++)
      {
        builder.append(", ?"); //$NON-NLS-1$
      }
    }
  }
}
