/*
 * 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.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.openjpa.meta.ClassMetaData;

/**
 * Represents a store of object data encoded in XML. This store only allows
 * one datastore transaction to proceed at a time. File I/O errors can put
 * this store into an invalid state.
 */
public class XMLStore {

    private final XMLConfiguration _conf;

    // each key in the map is a least-derived class metadata object, and each
    // value is a map of oids to object datas representing the instances of
    // that class, including subclasses
    private final Map _metaOidMaps = new HashMap();

    // store gets locked during transactions
    private boolean _locked;

    /**
     * Constructor; supply configuration.
     */
    public XMLStore(XMLConfiguration conf) {
        _conf = conf;
    }

    /**
     * Return the data for the given oid, or null if it does not exist.
     */
    public synchronized ObjectData getData(ClassMetaData meta, Object oid) {
        meta = getLeastDerived(meta);
        return (ObjectData) getMap(meta).get(oid);
    }

    /**
     * Return all datas for the base class of the given type.
     */
    public synchronized ObjectData[] getData(ClassMetaData meta) {
        meta = getLeastDerived(meta);
        Collection vals = getMap(meta).values();
        return (ObjectData[]) vals.toArray(new ObjectData[vals.size()]);
    }

    /**
     * Returns the map of oids to object datas for the given least-derived type.
     */
    private Map getMap(ClassMetaData meta) {
        Map m = (Map) _metaOidMaps.get(meta);
        if (m != null)
            return m;

        // load datas from file and cache them
        Collection datas = _conf.getFileHandler().load(meta);
        m = new HashMap(datas.size());
        for (Iterator itr = datas.iterator(); itr.hasNext();) {
            ObjectData data = (ObjectData) itr.next();
            m.put(data.getId(), data);
        }
        _metaOidMaps.put(meta, m);
        return m;
    }

    /**
     * Return the least-derived metadata in the inheritance chain
     * above <code>meta</code>, or <code>meta</code> if it is a
     * least-derived metadata.
     */
    private static ClassMetaData getLeastDerived(ClassMetaData meta) {
        while (meta.getPCSuperclass() != null)
            meta = meta.getPCSuperclassMetaData();
        return meta;
    }

    /**
     * Begin a datastore transaction. Obtains an exclusive write lock on the
     * store.
     */
    public synchronized void beginTransaction() {
        // lock store
        while (_locked)
            try {
                wait();
            } catch (InterruptedException ie) {
            }
        _locked = true;
    }

    /**
     * End the datastore transaction.
     *
     * @param updates {@link ObjectData} instances to insert or update
     * @param deletes {@link ObjectData} instances to delete
     */
    public synchronized void endTransaction(Collection<ObjectData> updates,
                                            Collection<ObjectData> deletes) {
        // track dirty types
        Set dirty = new HashSet();
        try {
            // commit updates
            if (updates != null) {
                for (Iterator itr = updates.iterator(); itr.hasNext();) {
                    ObjectData data = (ObjectData) itr.next();
                    ClassMetaData meta = getLeastDerived(data.getMetaData());
                    getMap(meta).put(data.getId(), data);
                    dirty.add(meta);
                }
            }

            // commit deletes
            if (deletes != null) {
                for (Iterator itr = deletes.iterator(); itr.hasNext();) {
                    ObjectData data = (ObjectData) itr.next();
                    ClassMetaData meta = getLeastDerived(data.getMetaData());
                    getMap(meta).remove(data.getId());
                    dirty.add(meta);
                }
            }

            // write changes to dirty extents back to file
            XMLFileHandler fh = _conf.getFileHandler();
            for (Iterator itr = dirty.iterator(); itr.hasNext();) {
                ClassMetaData meta = (ClassMetaData) itr.next();
                fh.store(meta, getMap(meta).values());
            }
        }
        finally {
            // unlock store
            notify();
            _locked = false;
        }
    }
}
