/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.openjpa.xmlstore;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.openjpa.abstractstore.AbstractStoreManager;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.PCState;
import org.apache.openjpa.lib.rop.ListResultObjectProvider;
import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.util.OptimisticException;
import org.apache.openjpa.util.StoreException;

/**
 * Store manager to a back-end consisting of XML files. This
 * implementation accesses data through the {@link XMLStore} associated with
 * its {@link XMLConfiguration}. Configuration instances are shared by all
 * store managers owned by all brokers created with the same factory.
 *
 * @see AbstractStoreManager
 */
public class XMLStoreManager
    extends AbstractStoreManager {

    private XMLConfiguration _conf;
    private XMLStore _store;

    // changed data within the current transaction
    private Collection<ObjectData> _updates;
    private Collection<ObjectData> _deletes;

    @Override
    protected Collection getUnsupportedOptions() {
        Collection c = super.getUnsupportedOptions();

        // remove options we do support but the abstract store doesn't
        c.remove(OpenJPAConfiguration.OPTION_ID_DATASTORE);
        c.remove(OpenJPAConfiguration.OPTION_OPTIMISTIC);

        // and add some that we don't support but the abstract store does
        c.add(OpenJPAConfiguration.OPTION_EMBEDDED_RELATION);
        c.add(OpenJPAConfiguration.OPTION_EMBEDDED_COLLECTION_RELATION);
        c.add(OpenJPAConfiguration.OPTION_EMBEDDED_MAP_RELATION);
        return c;
    }

    @Override
    protected OpenJPAConfiguration newConfiguration() {
        // override to use our configuration type
        return new XMLConfiguration();
    }

    @Override
    protected void open() {
        // cache operational state
        _conf = (XMLConfiguration) ctx.getConfiguration();
        _store = _conf.getStore();
    }

    @Override
    public boolean exists(OpenJPAStateManager sm, Object context) {
        // see if the given object exists in the store
        return _store.getData(sm.getMetaData(), sm.getObjectId()) != null;
    }

    /**
     * Increment the version indicator in the given state manager.
     */
    private static void incrementVersion(OpenJPAStateManager sm) {
        long version = 0;
        if (sm.getVersion() != null)
            version = ((Long) sm.getVersion()).longValue() + 1;
        sm.setNextVersion(version);
    }

    @Override
    public boolean initialize(OpenJPAStateManager sm, PCState state,
        FetchConfiguration fetch, Object context) {
        // we may already have looked up the backing ObjectData (see our extent
        // implementation below), and passed it through as the context; if
        // not, then look it up in the store
        ObjectData data;
        if (context != null)
            data = (ObjectData) context;
        else
            data = _store.getData(sm.getMetaData(), sm.getObjectId());

        // no matching record?
        if (data == null)
            return false;

        // initialize the state manager with a new instance of the right
        // type and lifecycle state
        sm.initialize(data.getMetaData().getDescribedType(), state);

        // load the data from the ObjectData into the state mgr; note that
        // this store manager doesn't do any locking -- it relies on the
        // system's lock manager to lock after the load is complete
        data.load(sm, fetch);
        return true;
    }

    @Override
    public boolean load(OpenJPAStateManager sm, BitSet fields,
        FetchConfiguration fetch, int lockLevel, Object context) {
        // we may already have looked up the backing ObjectData (see our extent
        // implementation below), and passed it through as the context; if
        // not, then look it up in the store
        ObjectData data;
        if (context != null)
            data = (ObjectData) context;
        else
            data = _store.getData(sm.getMetaData(), sm.getObjectId());

        // no matching record?
        if (data == null)
            return false;

        // load the data from the ObjectData into the state mgr; note that
        // this store manager doesn't do any locking -- it relies on the
        // system's lock manager to lock after the load is complete
        data.load(sm, fields, fetch);
        return true;
    }

    @Override
    public boolean syncVersion(OpenJPAStateManager sm, Object context) {
        if (sm.getVersion() == null)
            return false;

        // we may already have looked up the backing ObjectData (see our extent
        // implementation below), and passed it through as the context; if
        // not, then look it up in the store
        ObjectData data;
        if (context != null)
            data = (ObjectData) context;
        else
            data = _store.getData(sm.getMetaData(), sm.getObjectId());

        // no record?
        if (data == null)
            return false;

        // if the version of data held by the state mgr is the same as the
        // version in the datastore, return true, letting the broker know that
        // it doesn't need to load any more data
        if (sm.getVersion().equals(data.getVersion()))
            return true;

        // set the version to be up-to-date, and return false letting
        // the broker know that it needs to load up-to-date data
        sm.setVersion(data.getVersion());
        return false;
    }

    @Override
    public void begin() {
        _store.beginTransaction();
    }

    @Override
    public void commit() {
        try {
            _store.endTransaction(_updates, _deletes);
        } finally {
            _updates = null;
            _deletes = null;
        }
    }

    @Override
    public void rollback() {
        _updates = null;
        _deletes = null;
        _store.endTransaction(null, null);
    }

    @Override
    protected Collection flush(Collection<OpenJPAStateManager> pNew, Collection<OpenJPAStateManager> pNewUpdated,
        Collection<OpenJPAStateManager> pNewFlushedDeleted, Collection<OpenJPAStateManager> pDirty, Collection<OpenJPAStateManager> pDeleted) {
        // we don't support incremental flushing, so pNewUpdated and
        // pNewFlushedDeleted should be empty; we ignore them here

        // track optimistic violations
        Collection exceps = new LinkedList();

        // convert instances to ObjectDatas
        _updates = new ArrayList<>(pNew.size() + pDirty.size());
        _deletes = new ArrayList<>(pDeleted.size());

        // convert additions
        for (Iterator itr = pNew.iterator(); itr.hasNext();) {
            // create new object data for instance
            OpenJPAStateManager sm = (OpenJPAStateManager) itr.next();
            Object oid = sm.getObjectId();
            ObjectData data = _store.getData(sm.getMetaData(), oid);
            if (data != null)
                throw new StoreException("Attempt to insert "
                    + "new object " + sm.getManagedInstance()
                    + "with the same oid as an existing instance: " + oid).
                    setFatal(true);

            data = new ObjectData(oid, sm.getMetaData());
            incrementVersion(sm);
            data.store(sm);
            _updates.add(data);
        }

        // convert updates
        for (Iterator itr = pDirty.iterator(); itr.hasNext();) {
            OpenJPAStateManager sm = (OpenJPAStateManager) itr.next();
            ObjectData data = _store.getData(sm.getMetaData(),
                sm.getObjectId());

            // if data has been deleted or has the wrong version, record
            // opt lock violation
            if (data == null || !data.getVersion().equals(sm.getVersion())) {
                exceps.add(new OptimisticException
                    (sm.getManagedInstance()));
                continue;
            }

            // store changes
            incrementVersion(sm);
            data = (ObjectData) data.clone();
            data.store(sm);
            _updates.add(data);
        }

        // convert deletes
        for (Iterator itr = pDeleted.iterator(); itr.hasNext();) {
            OpenJPAStateManager sm = (OpenJPAStateManager) itr.next();
            ObjectData data = _store.getData(sm.getMetaData(),
                sm.getObjectId());

            // record delete
            if (data != null)
                _deletes.add(data);
        }

        return exceps;
    }

    @Override
    public ResultObjectProvider executeExtent(ClassMetaData meta,
        boolean subclasses, FetchConfiguration fetch) {
        // ask the store for all ObjectDatas for the given type; this
        // actually gives us all instances of the base class of the type
        ObjectData[] datas = _store.getData(meta);
        Class candidate = meta.getDescribedType();

        // create a list of the corresponding persistent objects that
        // match the type and subclasses criteria
        List pcs = new ArrayList(datas.length);
        for (int i = 0; i < datas.length; i++) {
            // does this instance belong in the extent?
            Class c = datas[i].getMetaData().getDescribedType();
            if (c != candidate && (!subclasses
                || !candidate.isAssignableFrom(c)))
                continue;

            // look up the pc instance for the data, passing in the data
            // as well so that we can take advantage of the fact that we've
            // already looked it up.  note that in the store manager's
            // initialize(), load(), etc methods we check for this data
            // being passed through and save ourselves a trip to the store
            // if it is present; this is particularly important in systems
            // where a trip to the store can be expensive.
            pcs.add(ctx.find(datas[i].getId(), fetch, null, datas[i], 0));
        }
        return new ListResultObjectProvider(pcs);
    }
    @Override
    public boolean isCached(List<Object> oids, BitSet edata) {
        // XMLStoreManager does not cache oids.
        return false;
    }
}
