001    /*
002     * 
003     * $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb 2008) $
004     *
005     * This file is part of ***  M y C o R e  ***
006     * See http://www.mycore.de/ for details.
007     *
008     * This program is free software; you can use it, redistribute it
009     * and / or modify it under the terms of the GNU General Public License
010     * (GPL) as published by the Free Software Foundation; either version 2
011     * of the License or (at your option) any later version.
012     *
013     * This program is distributed in the hope that it will be useful, but
014     * WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program, in a file called gpl.txt or license.txt.
020     * If not, write to the Free Software Foundation Inc.,
021     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
022     */
023    
024    package org.mycore.backend.jdom;
025    
026    import java.util.Enumeration;
027    import java.util.Hashtable;
028    import java.util.List;
029    
030    import org.apache.log4j.Logger;
031    import org.jdom.Document;
032    
033    import org.mycore.common.MCRConfiguration;
034    import org.mycore.common.MCRPersistenceException;
035    import org.mycore.datamodel.metadata.MCRNormalizeText;
036    import org.mycore.datamodel.metadata.MCRObjectID;
037    import org.mycore.datamodel.common.MCRXMLTableManager;
038    
039    /**
040     * This class implements the memory store based on JDOM documents.
041     * 
042     * @author Jens Kupferschmidt
043     * @author Frank L�tzenkirchen
044     * 
045     * @version $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb 2008) $
046     */
047    public class MCRJDOMMemoryStore {
048        /** The connection pool singleton */
049        private static MCRJDOMMemoryStore singleton;
050    
051        /** The logger */
052        private static Logger logger = Logger.getLogger("org.mycore.backend.jdom");
053    
054        /** A hashtable of the JDOM trees */
055        private Hashtable trees = new Hashtable();
056    
057        /** Timestamp of the last SQL read and the default reload time in seconds */
058        private long tslast = 0;
059    
060        private long tsdiff = 0;
061    
062        private static final long tsdiffdefault = 3600; // 1
063    
064        // hour
065    
066        /**
067         * Returns the singleton.
068         */
069        public static synchronized MCRJDOMMemoryStore instance() {
070            if (singleton == null) {
071                singleton = new MCRJDOMMemoryStore();
072            }
073    
074            return singleton;
075        }
076    
077        /**
078         * Creates a new JDOM memory store
079         */
080        private MCRJDOMMemoryStore() {
081            // set the start time and the diff from the config
082            MCRConfiguration config = MCRConfiguration.instance();
083            tslast = System.currentTimeMillis();
084            tsdiff = (config.getLong("MCR.persistence_jdom_reload", tsdiffdefault)) * 1000;
085        }
086    
087        /**
088         * Returns a list of all object metadata for a given object type
089         */
090        Hashtable getObjects(String type) {
091            // return the JDOM tree if it is in the store
092            if ((type == null) || ((type = type.trim()).length() == 0)) {
093                throw new MCRPersistenceException("The type is null or empty.");
094            }
095    
096            // check the reload
097            Hashtable store = null;
098    
099            if (System.currentTimeMillis() <= (tslast + tsdiff)) {
100                store = (Hashtable) trees.get(type);
101            }
102    
103            if (store != null) {
104                return store;
105            }
106    
107            tslast = System.currentTimeMillis();
108    
109            // fill the store form the SQL store of the type
110            store = readObjectsFromPersistentStore(type);
111            trees.put(type, store);
112    
113            return store;
114        }
115    
116        /**
117         * Reads all objects metadata from the persistent store into memory
118         */
119        private Hashtable readObjectsFromPersistentStore(String type) {
120            long startdate = System.currentTimeMillis();
121            MCRXMLTableManager mcr_xml = MCRXMLTableManager.instance();
122            List<String> ar = mcr_xml.retrieveAllIDs(type);
123            Hashtable objects = new Hashtable();
124            int size = ar.size();
125            
126            for (int i = 0; i < size; i++) {
127                String stid = (String) ar.get(i);
128                MCRObjectID mid = new MCRObjectID(stid);
129                Document jdom_document = (Document)( mcr_xml.readDocument(mid).clone() );
130                MCRNormalizeText.normalizeJDOM(jdom_document);
131                objects.put(mid, jdom_document.detachRootElement());
132                logger.debug("Load to JDOM tree " + stid);
133            }
134    
135            long stopdate = System.currentTimeMillis();
136            double diff = (stopdate - startdate) / 1000.0;
137            logger.debug("Read " + Integer.toString(ar.size()) + " SQL data sets for type " + type + " in " + diff + " seconds");
138    
139            return objects;
140        }
141    
142        /**
143         * Adds an objects xml metadata to the memory store.
144         */
145        void addElement(MCRObjectID id, Document doc) {
146            Document jdom_document = (Document)doc.clone();
147            MCRNormalizeText.normalizeJDOM(jdom_document);
148            getObjects(id.getTypeId()).put(id, jdom_document.detachRootElement());
149            logger.debug("MRJDOMMemoryStore addElement " + id.getTypeId());
150            debug(id.getTypeId());
151        }
152    
153        /**
154         * Removes an object from the memory store.
155         */
156        void removeElement(MCRObjectID id) {
157            getObjects(id.getTypeId()).remove(id);
158            logger.debug("MRJDOMMemoryStore removeElement " + id.getTypeId());
159            debug(id.getTypeId());
160        }
161    
162        /**
163         * Debug the content of the Hashtable.
164         */
165        void debug(String type) {
166            Hashtable h = getObjects(type);
167    
168            for (Enumeration e = h.keys(); e.hasMoreElements();) {
169                logger.info(e.nextElement().toString());
170            }
171        }
172    }