/*
 * Copyright (c) 2004 - 2012 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:
 *    Victor Roldan Betancort - initial API and implementation
 */
package org.eclipse.emf.cdo.server.internal.db4o;

import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
import org.eclipse.emf.cdo.common.model.EMFUtil;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionCacheAdder;
import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.server.IQueryHandler;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking;
import org.eclipse.emf.cdo.server.IStoreAccessor.Raw;
import org.eclipse.emf.cdo.server.IStoreChunkReader;
import org.eclipse.emf.cdo.server.ITransaction;
import org.eclipse.emf.cdo.server.db4o.IDB4OIdentifiableObject;
import org.eclipse.emf.cdo.server.internal.db4o.bundle.OM;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.LongIDStoreAccessor;

import org.eclipse.net4j.util.HexUtil;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.om.monitor.Monitor;
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.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;

import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Predicate;
import com.db4o.query.Query;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Victor Roldan Betancort
 */
public class DB4OStoreAccessor extends LongIDStoreAccessor implements Raw, DurableLocking
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, DB4OStoreAccessor.class);

  private ObjectContainer objectContainer;

  public DB4OStoreAccessor(DB4OStore store, ISession session)
  {
    super(store, session);
  }

  public DB4OStoreAccessor(DB4OStore store, ITransaction transaction)
  {
    super(store, transaction);
  }

  @Override
  public DB4OStore getStore()
  {
    return (DB4OStore)super.getStore();
  }

  public ObjectContainer getObjectContainer()
  {
    return objectContainer;
  }

  public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit)
  {
    DB4OPackageUnit db4OPackageUnit = getPrimitivePackageUnitMap().get(
        packageUnit.getTopLevelPackageInfo().getPackageURI());
    return EMFUtil.getAllPackages(db4OPackageUnit.getEPackage());
  }

  public void writePackageUnits(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
  {
    monitor.begin(packageUnits.length);

    try
    {
      DB4OStore store = getStore();
      ObjectContainer objectContainer = getObjectContainer();

      for (InternalCDOPackageUnit packageUnit : packageUnits)
      {
        DB4OPackageUnit primitivePackageUnit = DB4OPackageUnit.getPrimitivePackageUnit(store, packageUnit);
        objectContainer.store(primitivePackageUnit);
        monitor.worked(1);
      }
    }
    catch (Exception ex)
    {
      OM.LOG.error(ex);
    }
    finally
    {
      monitor.done();
    }
  }

  public Collection<InternalCDOPackageUnit> readPackageUnits()
  {
    Map<InternalCDOPackageUnit, DB4OPackageUnit> map = getPackageUnitMap();
    return map.keySet();
  }

  private Map<InternalCDOPackageUnit, DB4OPackageUnit> getPackageUnitMap()
  {
    Map<InternalCDOPackageUnit, DB4OPackageUnit> map = new HashMap<InternalCDOPackageUnit, DB4OPackageUnit>();
    Collection<DB4OPackageUnit> primitivePackageUnits = getObjectContainer().query(DB4OPackageUnit.class);

    for (DB4OPackageUnit primitivePackageUnit : primitivePackageUnits)
    {
      InternalCDOPackageUnit packageUnit = DB4OPackageUnit.getPackageUnit(primitivePackageUnit);
      map.put(packageUnit, primitivePackageUnit);
    }
    return map;
  }

  private Map<String, DB4OPackageUnit> getPrimitivePackageUnitMap()
  {
    Map<String, DB4OPackageUnit> map = new HashMap<String, DB4OPackageUnit>();
    Collection<DB4OPackageUnit> primitivePackageUnits = getObjectContainer().query(DB4OPackageUnit.class);

    for (DB4OPackageUnit primitivePackageUnit : primitivePackageUnits)
    {
      InternalCDOPackageUnit packageUnit = DB4OPackageUnit.getPackageUnit(primitivePackageUnit);
      map.put(packageUnit.getTopLevelPackageInfo().getPackageURI(), primitivePackageUnit);
    }
    return map;
  }

  public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint, int listChunk,
      CDORevisionCacheAdder cache)
  {
    DB4ORevision lastRevision = DB4OStore.getRevision(getObjectContainer(), id);
    if (lastRevision == null)
    {
      // Revision does not exist. Return null to signal inexistent Revision
      return null;
    }

    return DB4ORevision.getCDORevision(getStore(), lastRevision);
  }

  public void queryResources(QueryResourcesContext context)
  {
    final long folderID = CDOIDUtil.getLong(context.getFolderID());
    final String name = context.getName();
    final boolean exactMatch = context.exactMatch();
    // RootResource may not be initialized, as there may be queries during IStore activation
    CDOID rootResourceID = getStore().getRepository().getRootResourceID();
    final Object rootResourceLongID = rootResourceID != null ? DB4ORevision.getDB4OID(getStore().getRepository()
        .getRootResourceID()) : null;

    ObjectSet<DB4ORevision> revisionObjectSet = getObjectContainer().query(new Predicate<DB4ORevision>()
    {
      private static final long serialVersionUID = 1L;

      @Override
      public boolean match(DB4ORevision revision)
      {
        if (!revision.isResourceNode())
        {
          return false;
        }

        if (ObjectUtil.equals(rootResourceLongID, revision.getID()))
        {
          // is Root resource
          return false;
        }

        if (ObjectUtil.equals(revision.getContainerID(), folderID))
        {
          String candidateName = (String)revision.getValues().get(EresourcePackage.CDO_RESOURCE__NAME);
          if (exactMatch)
          {
            if (ObjectUtil.equals(candidateName, name))
            {
              return true;
            }
          }
          else
          {
            // provided name is prefix of the resource name
            if (candidateName != null && candidateName.startsWith(name))
            {
              return true;
            }
          }
        }

        return false;
      }
    });

    for (DB4ORevision revision : revisionObjectSet)
    {
      CDOID id = DB4ORevision.getCDOID(revision.getID());
      if (!context.addResource(id))
      {
        // No more results allowed
        break;
      }
    }

  }

  public IStoreChunkReader createChunkReader(InternalCDORevision revision, EStructuralFeature feature)
  {
    // TODO: implement DB4OStoreAccessor.createChunkReader(revision, feature)
    throw new UnsupportedOperationException();
  }

  public IQueryHandler getQueryHandler(CDOQueryInfo info)
  {
    return null;
  }

  @Override
  protected void doActivate() throws Exception
  {
    objectContainer = getStore().openClient();
  }

  @Override
  protected void doDeactivate() throws Exception
  {
    if (objectContainer != null)
    {
      objectContainer.close();
      objectContainer = null;
    }
  }

  @Override
  protected void doPassivate() throws Exception
  {
    if (objectContainer != null)
    {
      objectContainer.rollback();
    }
  }

  @Override
  protected void doUnpassivate() throws Exception
  {
  }

  @Override
  protected void doRollback(CommitContext commitContext)
  {
    getObjectContainer().rollback();
  }

  public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk,
      CDORevisionCacheAdder cache)
  {
    DB4ORevision revision = DB4OStore.getRevision(getObjectContainer(), id);
    if (revision == null || revision.getVersion() != branchVersion.getVersion())
    {
      return null;
    }

    return DB4ORevision.getCDORevision(getStore(), revision);
  }

  public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime,
      CDORevisionHandler handler)
  {
    Query query = getObjectContainer().query();
    query.constrain(DB4ORevision.class);
    if (eClass != null)
    {
      query.descend(DB4ORevision.ATTRIBUTE_PACKAGE_NS_URI).constrain(eClass.getEPackage().getNsURI());
      query.descend(DB4ORevision.ATTRIBUTE_CLASS_NAME).constrain(eClass.getName());
    }

    ObjectSet<?> revisions = query.execute();
    if (revisions.isEmpty())
    {
      return;
    }

    for (Object revision : revisions.toArray())
    {
      CDORevision cdoRevision = DB4ORevision.getCDORevision(getStore(), (DB4ORevision)revision);
      handler.handleRevision(cdoRevision);
    }
  }

  public Set<CDOID> readChangeSet(OMMonitor monitor, CDOChangeSetSegment... segments)
  {
    // TODO: implement DB4OStoreAccessor.readChangeSet(segments)
    throw new UnsupportedOperationException();
  }

  public void queryXRefs(final QueryXRefsContext context)
  {
    final int branchID = context.getBranch().getID();

    for (final CDOID target : context.getTargetObjects().keySet())
    {
      for (final EClass eClass : context.getSourceCandidates().keySet())
      {
        final String eClassName = eClass.getName();
        final String nsURI = eClass.getEPackage().getNsURI();
        final List<EReference> eReferences = context.getSourceCandidates().get(eClass);
        getObjectContainer().query(new Predicate<DB4ORevision>()
        {
          private static final long serialVersionUID = 1L;

          private boolean moreResults = true;

          @Override
          public boolean match(DB4ORevision revision)
          {
            if (!moreResults)
            {
              return false;
            }

            if (!revision.getClassName().equals(eClassName))
            {
              return false;
            }

            if (!revision.getPackageURI().equals(nsURI))
            {
              return false;
            }

            if (!(revision.getBranchID() == branchID))
            {
              return false;
            }

            CDOID id = DB4ORevision.getCDOID(revision.getID());
            for (EReference eReference : eReferences)
            {
              Object obj = revision.getValues().get(eReference.getFeatureID());
              if (obj instanceof List)
              {
                List<?> list = (List<?>)obj;
                int index = 0;
                for (Object element : list)
                {
                  CDOID ref = DB4ORevision.getCDOID(element);
                  if (ObjectUtil.equals(ref, target))
                  {
                    moreResults = context.addXRef(target, id, eReference, index);
                  }

                  ++index;
                }
              }
              else
              {
                CDOID ref = DB4ORevision.getCDOID(obj);
                if (ObjectUtil.equals(ref, target))
                {
                  moreResults = context.addXRef(target, id, eReference, 0);
                }
              }
            }

            return false;
          }
        });
      }
    }
  }

  public void queryLobs(List<byte[]> ids)
  {
    for (Iterator<byte[]> it = ids.iterator(); it.hasNext();)
    {
      byte[] id = it.next();
      String key = HexUtil.bytesToHex(id);
      if (DB4OStore.getIdentifiableObject(getObjectContainer(), key) == null)
      {
        it.remove();
      }
    }
  }

  public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException
  {
    for (DB4OBlob db4oBlob : DB4OStore.getElementsOfType(getObjectContainer(), DB4OBlob.class))
    {
      byte[] id = HexUtil.hexToBytes(db4oBlob.getId());
      byte[] blob = db4oBlob.getValue();
      ByteArrayInputStream in = new ByteArrayInputStream(blob);
      OutputStream out = handler.handleBlob(id, blob.length);
      if (out != null)
      {
        try
        {
          IOUtil.copyBinary(in, out, blob.length);
        }
        finally
        {
          IOUtil.close(out);
        }
      }
    }
    for (DB4OClob db4oClob : DB4OStore.getElementsOfType(getObjectContainer(), DB4OClob.class))
    {
      byte[] id = HexUtil.hexToBytes(db4oClob.getId());
      char[] clob = db4oClob.getValue();
      CharArrayReader in = new CharArrayReader(clob);
      Writer out = handler.handleClob(id, clob.length);
      if (out != null)
      {
        try
        {
          IOUtil.copyCharacter(in, out, clob.length);
        }
        finally
        {
          IOUtil.close(out);
        }
      }
    }
  }

  public void loadLob(byte[] id, OutputStream out) throws IOException
  {
    String key = HexUtil.bytesToHex(id);
    IDB4OIdentifiableObject identifiableObject = DB4OStore.getIdentifiableObject(getObjectContainer(), key);
    if (identifiableObject == null)
    {
      throw new IOException("Lob not found: " + key);
    }

    if (identifiableObject instanceof DB4OBlob)
    {
      DB4OBlob blob = (DB4OBlob)identifiableObject;
      byte[] byteArray = blob.getValue();
      ByteArrayInputStream in = new ByteArrayInputStream(byteArray);
      IOUtil.copyBinary(in, out, byteArray.length);
    }
    else
    {
      DB4OClob clob = (DB4OClob)identifiableObject;
      char[] charArray = clob.getValue();
      CharArrayReader in = new CharArrayReader(charArray);
      IOUtil.copyCharacter(in, new OutputStreamWriter(out), charArray.length);
    }
  }

  @Override
  protected void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException
  {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    IOUtil.copyBinary(inputStream, out, size);
    writeObject(new DB4OBlob(HexUtil.bytesToHex(id), out.toByteArray()), new Monitor());
  }

  @Override
  protected void writeClob(byte[] id, long size, Reader reader) throws IOException
  {
    CharArrayWriter out = new CharArrayWriter();
    IOUtil.copyCharacter(reader, out, size);
    writeObject(new DB4OClob(HexUtil.bytesToHex(id), out.toCharArray()), new Monitor());
  }

  public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
  {
    // TODO: implement DB4OStoreAccessor.createBranch(branchID, branchInfo)
    throw new UnsupportedOperationException();
  }

  public BranchInfo loadBranch(int branchID)
  {
    // TODO: implement DB4OStoreAccessor.loadBranch(branchID)
    throw new UnsupportedOperationException();
  }

  public SubBranchInfo[] loadSubBranches(int branchID)
  {
    // TODO: implement DB4OStoreAccessor.loadSubBranches(branchID)
    throw new UnsupportedOperationException();
  }

  public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler)
  {
    // TODO: implement DB4OStoreAccessor.loadBranches(startID, endID, branchHandler)
    throw new UnsupportedOperationException();
  }

  public void loadCommitInfos(final CDOBranch branch, final long startTime, final long endTime,
      CDOCommitInfoHandler handler)
  {
    ObjectSet<DB4OCommitInfo> resultSet = getObjectContainer().query(new Predicate<DB4OCommitInfo>()
    {
      private static final long serialVersionUID = 1L;

      @Override
      public boolean match(DB4OCommitInfo info)
      {
        if (startTime != CDOBranchPoint.UNSPECIFIED_DATE && info.getTimeStamp() < startTime)
        {
          return false;
        }

        if (endTime != CDOBranchPoint.UNSPECIFIED_DATE && info.getTimeStamp() > endTime)
        {
          return false;
        }

        if (branch != null && !(info.getBranchID() == branch.getID()))
        {
          return false;
        }

        return true;
      }
    });

    InternalRepository repository = getStore().getRepository();
    InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
    InternalCDOBranchManager branchManager = repository.getBranchManager();

    // Although not specified in the API, the test suite
    // suggests CommitInfos should be returned ordered by timeStamp
    // TODO Specify this in the API!

    List<DB4OCommitInfo> infos = new ArrayList<DB4OCommitInfo>(resultSet);
    Collections.sort(infos, new Comparator<DB4OCommitInfo>()
    {
      public int compare(DB4OCommitInfo arg0, DB4OCommitInfo arg1)
      {
        return CDOCommonUtil.compareTimeStamps(arg0.getTimeStamp(), arg1.getTimeStamp());
      }
    });

    for (DB4OCommitInfo info : infos)
    {
      info.handle(branchManager, commitInfoManager, handler);
    }
  }

  @Override
  protected void doCommit(OMMonitor monitor)
  {
    monitor.begin();
    Async async = monitor.forkAsync();

    try
    {
      long start = 0;
      if (TRACER.isEnabled())
      {
        start = System.currentTimeMillis();
      }
      getObjectContainer().commit();

      if (TRACER.isEnabled())
      {
        long end = System.currentTimeMillis();
        TRACER.format("Commit took: {0} milliseconds.", end - start);
      }
    }
    catch (Exception e)
    {
      OM.LOG.error(e);
    }
    finally
    {
      async.stop();
      monitor.done();
    }
  }

  @Override
  protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID,
      String comment, OMMonitor monitor)
  {
    DB4OCommitInfo commitInfo = new DB4OCommitInfo(branch.getID(), timeStamp, previousTimeStamp, userID, comment);
    writeObject(commitInfo, monitor);
  }

  @Override
  protected void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor)
  {
    monitor.begin(revisions.length);

    try
    {
      long start = 0;
      if (TRACER.isEnabled())
      {
        start = System.currentTimeMillis();
      }

      for (InternalCDORevision revision : revisions)
      {
        writeRevision(revision, monitor.fork());
      }

      if (TRACER.isEnabled())
      {
        long end = System.currentTimeMillis();
        TRACER.format("Storage of {0} revisions took: {1} milliseconds.", revisions.length, end - start);
      }
    }
    finally
    {
      monitor.done();
    }
  }

  protected void writeRevision(InternalCDORevision revision, OMMonitor monitor)
  {
    Async async = null;
    monitor.begin(10);

    try
    {
      try
      {
        async = monitor.forkAsync();
        if (revision.isResourceNode())
        {
          checkDuplicateResources(revision);
        }
      }
      finally
      {
        if (async != null)
        {
          async.stop();
        }
      }

      // TODO removal of previous version implies query, this should be optimized

      long start = 0;
      if (TRACER.isEnabled())
      {
        start = System.currentTimeMillis();
      }
      CDOID id = revision.getID();
      DB4OStore.removeRevision(getObjectContainer(), id);
      DB4ORevision primitiveRevision = DB4ORevision.getDB4ORevision(revision);
      writeObject(primitiveRevision, monitor);
      if (TRACER.isEnabled())
      {
        long end = System.currentTimeMillis();
        TRACER.format("Writing revision {0} took: {1} milliseconds.", id, end - start);
      }
    }
    finally
    {
      monitor.done();
    }
  }

  protected void writeObject(Object object, OMMonitor monitor)
  {
    monitor.begin();
    Async async = monitor.forkAsync();

    try
    {
      getObjectContainer().store(object);
    }
    catch (Throwable t)
    {
      OM.LOG.error(t);
    }
    finally
    {
      async.stop();
      monitor.done();
    }
  }

  @Override
  protected void writeRevisionDeltas(InternalCDORevisionDelta[] revisionDeltas, CDOBranch branch, long created,
      OMMonitor monitor)
  {
    for (InternalCDORevisionDelta revisionDelta : revisionDeltas)
    {
      writeRevisionDelta(revisionDelta, branch, created);
    }
  }

  protected void writeRevisionDelta(InternalCDORevisionDelta revisionDelta, CDOBranch branch, long created)
  {
    CDOID id = revisionDelta.getID();
    InternalCDORevision revision = DB4ORevision.getCDORevision(getStore(),
        DB4OStore.getRevision(getObjectContainer(), id));
    InternalCDORevision newRevision = revision.copy();
    newRevision.adjustForCommit(branch, created);

    revisionDelta.apply(newRevision);
    writeRevision(newRevision, new Monitor());
  }

  @Override
  protected void detachObjects(CDOID[] detachedObjects, CDOBranch branch, long timeStamp, OMMonitor monitor)
  {
    monitor.begin(detachedObjects.length);

    try
    {
      for (CDOID id : detachedObjects)
      {
        DB4OStore.removeRevision(getObjectContainer(), id);
        monitor.worked();
      }
    }
    finally
    {
      monitor.done();
    }
  }

  protected void checkDuplicateResources(CDORevision revision) throws IllegalStateException
  {
    final long folderID = CDOIDUtil.getLong((CDOID)revision.data().getContainerID());
    final long revisionID = CDOIDUtil.getLong(revision.getID());
    final String name = (String)revision.data().get(EresourcePackage.eINSTANCE.getCDOResourceNode_Name(), 0);

    ObjectSet<DB4ORevision> resultSet = getObjectContainer().query(new Predicate<DB4ORevision>()
    {
      private static final long serialVersionUID = 1L;

      @Override
      public boolean match(DB4ORevision revision)
      {
        if (revision.isResourceNode() && ObjectUtil.equals(revision.getContainerID(), folderID))
        {
          String candidateName = (String)revision.getValues().get(EresourcePackage.CDO_RESOURCE__NAME);
          if (StringUtil.compare(name, candidateName) == 0)
          {
            if (!ObjectUtil.equals(revision.getID(), revisionID))
            {
              return true;
            }
          }
        }

        return false;
      }
    });

    if (!resultSet.isEmpty())
    {
      throw new IllegalStateException("Duplicate resource or folder: " + name + " in folder " + folderID); //$NON-NLS-1$ //$NON-NLS-2$
    }
  }

  public void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime)
      throws IOException
  {
    // TODO: Implement DB4OStoreAccessor.rawExport(CDODataOutput, int, int, long, long)
    throw new UnsupportedOperationException();
  }

  public void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime,
      OMMonitor monitor) throws IOException
  {
    // TODO: Implement DB4OStoreAccessor.rawImport(CDODataInput, int, int, long, long, OMMonitor)
    throw new UnsupportedOperationException();
  }

  public void rawStore(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
  {
    writePackageUnits(packageUnits, monitor);
  }

  public void rawStore(InternalCDORevision revision, OMMonitor monitor)
  {
    writeRevision(revision, monitor);
  }

  public void rawStore(byte[] id, long size, InputStream inputStream) throws IOException
  {
    // TODO: Implement DB4OStoreAccessor.rawExport(CDODataOutput, int, int, long, long)
    throw new UnsupportedOperationException();
  }

  public void rawStore(byte[] id, long size, Reader reader) throws IOException
  {
    // TODO: Implement DB4OStoreAccessor.rawStore(byte[], long, Reader)
    throw new UnsupportedOperationException();
  }

  public void rawStore(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment,
      OMMonitor monitor)
  {
    writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, monitor);
  }

  @Deprecated
  public void rawDelete(CDOID id, int version, CDOBranch branch, EClass eClass, OMMonitor monitor)
  {
    throw new UnsupportedOperationException();
  }

  public void rawCommit(double commitWork, OMMonitor monitor)
  {
    doCommit(monitor);
  }

  public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
      Map<CDOID, LockGrade> locks)
  {
    DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
    return manager.createLockArea(this, userID, branchPoint, readOnly, locks);
  }

  public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException
  {
    DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
    return manager.getLockArea(this, durableLockingID);
  }

  public void getLockAreas(String userIDPrefix, Handler handler)
  {
    DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
    manager.getLockAreas(this, userIDPrefix, handler);
  }

  public void deleteLockArea(String durableLockingID)
  {
    DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
    manager.deleteLockArea(this, durableLockingID);
  }

  public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock)
  {
    DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
    manager.lock(this, durableLockingID, type, objectsToLock);
  }

  public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock)
  {
    DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
    manager.unlock(this, durableLockingID, type, objectsToUnlock);
  }

  public void unlock(String durableLockingID)
  {
    DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
    manager.unlock(this, durableLockingID);
  }
}
