001    /*
002     * 
003     * $Revision: 15621 $ $Date: 2009-07-25 08:32:01 +0200 (Sat, 25 Jul 2009) $
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.hibernate;
025    
026    import java.io.InputStream;
027    import java.sql.Blob;
028    import java.util.AbstractList;
029    import java.util.ArrayList;
030    import java.util.Date;
031    import java.util.List;
032    
033    import org.apache.log4j.Logger;
034    import org.hibernate.Criteria;
035    import org.hibernate.Session;
036    import org.hibernate.criterion.Projections;
037    import org.hibernate.criterion.Restrictions;
038    import org.mycore.backend.hibernate.tables.MCRXMLTABLE;
039    import org.mycore.backend.hibernate.tables.MCRXMLTABLEPK;
040    import org.mycore.common.MCRConfiguration;
041    import org.mycore.common.MCRPersistenceException;
042    import org.mycore.datamodel.common.MCRObjectIDDate;
043    import org.mycore.datamodel.common.MCRXMLTableInterface;
044    
045    /**
046     * This class implements the MCRXMLInterface.
047     */
048    public class MCRHIBXMLStore implements MCRXMLTableInterface {
049        // logger
050        static Logger logger = Logger.getLogger(MCRHIBXMLStore.class.getName());
051    
052        private String classname = "org.mycore.backend.hibernate.tables.MCRXMLTABLE";
053    
054        private String type;
055    
056        private String project;
057        
058        /**
059         * The constructor for the class MCRHIBXMLStore.
060         */
061        public MCRHIBXMLStore() {
062        }
063    
064        private Session getSession() {
065            return MCRHIBConnection.instance().getSession();
066        }
067    
068        /**
069         * The initializer for the class MCRHIBXMLStore. It reads the configuration
070         * and checks the table names and create the table if they does'n exist..
071         * 
072         * @param type
073         *            the type String of the MCRObjectID
074         * @exception MCRPersistenceException
075         *                if the type is not correct
076         */
077        public final void init(String type) throws MCRPersistenceException {
078            MCRConfiguration config = MCRConfiguration.instance();
079    
080            // Check the parameter
081            if ((type == null) || ((type = type.trim()).length() == 0)) {
082                throw new MCRPersistenceException("The type of the constructor" + " is null or empty.");
083            }
084    
085            boolean test = config.getBoolean("MCR.Metadata.Type." + type, false);
086    
087            if (!test) {
088                throw new MCRPersistenceException("The type " + type + " of the constructor" + " is false.");
089            }
090    
091            this.type = type;
092            this.project = config.getString("MCR.SWF.Project.ID");
093            this.project = config.getString("MCR.SWF.Project.ID." + type, this.project );
094        }
095    
096        /**
097         * The method create a new item in the datastore.
098         * 
099         * @param mcrid
100         *            a MCRObjectID
101         * @param xml
102         *            a byte array with the XML file
103         * @param version
104         *            the version of the XML Blob as integer
105         * @exception MCRPersistenceException
106         *                the method arguments are not correct
107         */
108        public synchronized final void create(String mcrid, byte[] xml, Date lastModified) throws MCRPersistenceException {
109            if (mcrid == null) {
110                throw new MCRPersistenceException("The MCRObjectID is null.");
111            }
112            if ((xml == null) || (xml.length == 0)) {
113                throw new MCRPersistenceException("The XML array is null or empty.");
114            }
115    
116            Session session = getSession();
117            MCRXMLTABLEPK pk = new MCRXMLTABLEPK(mcrid, 1);
118            MCRXMLTABLE tab = (MCRXMLTABLE) session.get(MCRXMLTABLE.class, pk);
119            if (tab == null) {
120                tab = new MCRXMLTABLE();
121                tab.setKey(pk);
122                tab.setType(this.type);
123            }
124            tab.setLastModified(lastModified);
125            tab.setXmlByteArray(xml);
126            logger.debug("Inserting " + mcrid + "/" + this.type + " into database MCRXMLTABLE");
127            session.save(tab);
128        }
129    
130        /**
131         * The method remove a item for the MCRObjectID from the datastore.
132         * 
133         * @param mcrid
134         *            a MCRObjectID
135         * @param version
136         *            the version of the XML Blob as integer
137         * @exception MCRPersistenceException
138         *                the method argument is not correct
139         */
140        public synchronized final void delete(String mcrid) throws MCRPersistenceException {
141            Session session = getSession();
142            logger.debug("Deleting " + mcrid + " from database MCRXMLTABLE");
143            session.delete(session.get(MCRXMLTABLE.class, new MCRXMLTABLEPK(mcrid, 1)));
144        }
145    
146        /**
147         * The method update an item in the datastore.
148         * 
149         * @param mcrid
150         *            a MCRObjectID
151         * @param xml
152         *            a byte array with the XML file
153         * @param version
154         *            the version of the XML Blob as integer
155         * @exception MCRPersistenceException
156         *                the method arguments are not correct
157         */
158        public synchronized final void update(String mcrid, byte[] xml, Date lastModified) throws MCRPersistenceException {
159            Session session = getSession();
160            MCRXMLTABLE xmlEntry = (MCRXMLTABLE) session.load(MCRXMLTABLE.class, new MCRXMLTABLEPK(mcrid, 1));
161            xmlEntry.setVersion(1);
162            xmlEntry.setType(this.type);
163            xmlEntry.setXmlByteArray(xml);
164            xmlEntry.setLastModified(lastModified);
165            logger.debug("Updateing " + mcrid + "/" + this.type + " in database");
166            session.update(xmlEntry);
167        }
168    
169        /**
170         * The method retrieve a dataset for the given MCRObjectID and returns the
171         * corresponding XML file as byte array.
172         * 
173         * @param mcrid
174         *            a MCRObjectID
175         * @param version
176         *            the version of the XML Blob as integer
177         * @return the XML-File as byte array or null
178         * @exception MCRPersistenceException
179         *                the method arguments are not correct
180         */
181        public final InputStream retrieve(String mcrid) throws MCRPersistenceException {
182            Session session = getSession();
183            MCRXMLTABLEPK pk = new MCRXMLTABLEPK(mcrid,1);
184            Blob blob = (Blob) session.createCriteria(MCRXMLTABLE.class).setProjection(Projections.property("xml")).add(Restrictions.eq("key", pk)).uniqueResult();
185            try {
186                return blob.getBinaryStream();
187            } catch (Exception e) {
188                throw new MCRPersistenceException("Cannot get Blob for " + mcrid, e);
189            }
190        }
191    
192        /**
193         * This method returns the highest stored ID number for a given MCRObjectID base, 
194         * or 0 if no object is stored for this type and project.
195         * 
196         * @exception MCRPersistenceException
197         *                if a persistence problem is occured
198         * 
199         * @return the highest stored ID number as a String
200         */
201        public final synchronized int getHighestStoredID() throws MCRPersistenceException {
202    
203            Session session = getSession();
204            List<?> l = session.createQuery("select max(key.id) from " + classname + " where MCRID like '" + project + "_" + type + "%'").list();
205            if (l.size() == 0 || l.get(0) == null)
206                return 0;
207            else {
208                String last = (String) (l.get(0));
209                return Integer.parseInt(last.substring(last.lastIndexOf('_') + 1));
210            }
211        }
212    
213        /**
214         * This method check that the MCRObjectID exist in this store.
215         * 
216         * @param mcrid
217         *            a MCRObjectID
218         * @param version
219         *            the version of the XML Blob as integer
220         * @return true if the MCRObjectID exist, else return false
221         */
222        public final boolean exists(String mcrid) {
223            MCRXMLTABLEPK pk = new MCRXMLTABLEPK(mcrid, 1);
224            if (getSession().get(MCRXMLTABLE.class, pk) != null) {
225                return true;
226            }
227            return false;
228        }
229    
230        /**
231         * The method return a Array list with all stored MCRObjectID's of the XML
232         * table.
233         * 
234         * @param type
235         *            a MCRObjectID type string
236         * @return a ArrayList of MCRObjectID's
237         */
238        public List<String> retrieveAllIDs() {
239            Session session = getSession();
240            List<?> l;
241            ArrayList<String> a = new ArrayList<String>();
242    
243            l = session.createQuery("select distinct(key.id) from MCRXMLTABLE where MCRTYPE = '" + type + "'").list();
244            for (int t = 0; t < l.size(); t++) {
245                a.add((String) l.get(t));
246            }
247    
248            return a;
249        }
250    
251        public static void test() {
252            MCRHIBXMLStore store = new MCRHIBXMLStore();
253            List<String> l = store.retrieveAllIDs();
254            int t;
255    
256            for (t = 0; t < l.size(); t++) {
257                logger.debug(l.get(0));
258            }
259        }
260    
261        public List<MCRObjectIDDate> listObjectDates(String type) {
262            Session session = getSession();
263            Criteria criteria = session.createCriteria(MCRXMLTABLE.class).add(Restrictions.eq("type", type)).setProjection(Projections.projectionList().add(Projections.property("key.id")).add(Projections.property("lastModified")));
264            List<?> result = criteria.list();
265            return new MCRObjectIDDateList(result);
266        }
267    
268        private static class MCRObjectIDDateList extends AbstractList<MCRObjectIDDate> {
269    
270            List<?> result;
271    
272            public MCRObjectIDDateList(List<?> result) {
273                this.result = result;
274            }
275    
276            @Override
277            public MCRObjectIDDate get(final int index) {
278                return new MCRObjectIDDate() {
279    
280                    private Object[] entry = (Object[]) result.get(index);
281    
282                    public String getId() {
283                        return entry[0].toString();
284                    }
285    
286                    public Date getLastModified() {
287                        return (Date) entry[1];
288                    }
289    
290                };
291            }
292    
293            @Override
294            public int size() {
295                return result.size();
296            }
297        }
298    }