001    /*
002     * 
003     * $Revision: 14986 $ $Date: 2009-03-20 21:41:45 +0100 (Fri, 20 Mar 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.datamodel.common;
025    
026    import java.util.Collection;
027    import java.util.Collections;
028    import java.util.LinkedList;
029    import java.util.Map;
030    
031    import org.apache.log4j.Logger;
032    import org.mycore.common.MCRConfiguration;
033    import org.mycore.common.MCRException;
034    import org.mycore.datamodel.metadata.MCRObjectID;
035    
036    /**
037     * This class manage all accesses to the link table database. This database
038     * holds all informations about links between MCRObjects/MCRClassifications.
039     * 
040     * @author Jens Kupferschmidt
041     * @version $Revision: 14986 $ $Date: 2009-03-20 21:41:45 +0100 (Fri, 20 Mar 2009) $
042     */
043    public class MCRLinkTableManager {
044        /** The list of entry types */
045        public static final String ENTRY_TYPE_CHILD = "child";
046    
047        public static final String ENTRY_TYPE_DERIVATE = "derivate";
048    
049        public static final String ENTRY_TYPE_PARENT = "parent";
050    
051        public static final String ENTRY_TYPE_REFERENCE = "reference";
052    
053        /** The link table manager singleton */
054        protected static MCRLinkTableManager singleton;
055    
056        // logger
057        static Logger logger = Logger.getLogger(MCRLinkTableManager.class.getName());
058    
059        // the persitence class
060        private String persistclassname = null;
061    
062        private MCRLinkTableInterface persistenceclass = null;
063    
064        /**
065         * Returns the link table manager singleton.
066         * 
067         * @return Returns a MCRLinkTableManager instance.
068         */
069        public static synchronized MCRLinkTableManager instance() {
070            if (singleton == null) {
071                singleton = new MCRLinkTableManager();
072            }
073    
074            return singleton;
075        }
076    
077        /**
078         * The constructor of this class.
079         */
080        protected MCRLinkTableManager() {
081            MCRConfiguration config = MCRConfiguration.instance();
082    
083            // Load the persistence class
084            persistclassname = config.getString("MCR.Persistence.LinkTable.Store.Class");
085    
086            Object obj = new Object();
087            try {
088                obj = Class.forName(persistclassname).newInstance();
089            } catch (ClassNotFoundException e) {
090                throw new MCRException(persistclassname + " ClassNotFoundException");
091            } catch (IllegalAccessException e) {
092                throw new MCRException(persistclassname + " IllegalAccessException");
093            } catch (InstantiationException e) {
094                throw new MCRException(persistclassname + " InstantiationException");
095            }
096    
097            persistenceclass = (MCRLinkTableInterface) obj;
098        }
099    
100        /**
101         * This method check the type of link.
102         * 
103         * @param type
104         * @return true if it is a defined type, else return false and send a
105         *         warning to the logger.
106         */
107        private final boolean checkType(String type) {
108            if (type.equals(ENTRY_TYPE_CHILD) || type.equals(ENTRY_TYPE_DERIVATE) || type.equals(ENTRY_TYPE_PARENT) || type.equals(ENTRY_TYPE_REFERENCE)) {
109                return true;
110            }
111            logger.warn("The value " + type + " is not a defined type for the link table.");
112            return false;
113        }
114    
115        /**
116         * The method add a reference link pair.
117         * 
118         * @param from
119         *            the source of the reference as MCRObjectID
120         * @param to
121         *            the target of the reference as MCRObjectID
122         * @param type
123         *            the type of the reference as String
124         * @param attr
125         *            the optional attribute of the reference as String
126         */
127        public void addReferenceLink(MCRObjectID from, MCRObjectID to, String type, String attr) {
128            addReferenceLink(from.getId(), to.getId(), type, attr);
129        }
130    
131        /**
132         * The method add a reference link pair.
133         * 
134         * @param from
135         *            the source of the reference as String
136         * @param to
137         *            the target of the reference as String
138         * @param type
139         *            the type of the reference as String
140         * @param attr
141         *            the optional attribute of the reference as String
142         */
143        public void addReferenceLink(String from, String to, String type, String attr) {
144            if ((from == null) || ((from = from.trim()).length() == 0)) {
145                logger.warn("The from value of a reference link is false, the link was not added to the link table");
146                return;
147            }
148    
149            if ((to == null) || ((to = to.trim()).length() == 0)) {
150                logger.warn("The to value of a reference link is false, the link was not added to the link table");
151                return;
152            }
153    
154            if ((type == null) || ((type = type.trim()).length() == 0)) {
155                logger.warn("The type value of a reference link is false, the link was not added to the link table");
156                return;
157            }
158    
159            if (attr == null) {
160                attr = "";
161            }
162    
163            StringBuffer sb = new StringBuffer().append("Link in table ").append(type).append(" add for ").append(from).append("<-->").append(to).append(" with ")
164                    .append(type).append(" and ").append(attr);
165            logger.debug(sb.toString());
166    
167            try {
168                persistenceclass.create(from, to, type, attr);
169            } catch (Exception e) {
170                if (logger.isDebugEnabled()) {
171                    e.printStackTrace();
172                }
173                logger.warn("An error occured while adding a dataset from the reference link table, adding not succesful.");
174            }
175        }
176    
177        /**
178         * The method delete a reference link.
179         * 
180         * @param from
181         *            the source of the reference as MCRObjectID
182         */
183        public void deleteReferenceLink(MCRObjectID from) {
184            deleteReferenceLink(from.getId());
185        }
186    
187        /**
188         * The method delete a reference link.
189         * 
190         * @param from
191         *            the source of the reference as String
192         */
193        public void deleteReferenceLink(String from) {
194            if ((from == null) || ((from = from.trim()).length() == 0)) {
195                logger.warn("The from value of a reference link is false, the link was " + "not deleted from the link table");
196                return;
197            }
198    
199            try {
200                persistenceclass.delete(from, null, null);
201            } catch (Exception e) {
202                if (logger.isDebugEnabled()) {
203                    e.printStackTrace();
204                }
205                logger.warn("An error occured while deleting a dataset from the" + from + " reference link table, deleting could be not succesful.");
206            }
207        }
208    
209        /**
210         * The method delete a reference link pair for the given type to the store.
211         * 
212         * @param from
213         *            the source of the reference as String
214         * @param to
215         *            the target of the reference as String
216         * @param type
217         *            the type of the reference as String
218         */
219        public void deleteReferenceLink(String from, String to, String type) {
220            if ((from == null) || ((from = from.trim()).length() == 0)) {
221                logger.warn("The from value of a reference link is false, the link was " + "not deleted from the link table");
222                return;
223            }
224            try {
225                persistenceclass.delete(from, to, type);
226            } catch (Exception e) {
227                e.printStackTrace();
228                logger.warn("An error occured while deleting a dataset from the" + " reference link table, deleting is not succesful.");
229            }
230        }
231    
232        /**
233         * The method count the reference links for a given target MCRobjectID.
234         * 
235         * @param to
236         *            the object ID as MCRObjectID, they was referenced
237         * @return the number of references
238         */
239        public int countReferenceLinkTo(MCRObjectID to) {
240            return countReferenceLinkTo(to.getId());
241        }
242    
243        /**
244         * The method count the reference links for a given target object ID.
245         * 
246         * @param to
247         *            the object ID as String, they was referenced
248         * @return the number of references
249         */
250        public int countReferenceLinkTo(String to) {
251            if ((to == null) || ((to = to.trim()).length() == 0)) {
252                logger.warn("The to value of a reference link is false, the link was " + "not added to the link table");
253    
254                return 0;
255            }
256    
257            try {
258                return persistenceclass.countTo(null, to, null, null);
259            } catch (Exception e) {
260                logger.warn("An error occured while searching for references of " + to + ".");
261            }
262    
263            return 0;
264        }
265    
266        /**
267         * counts the reference links for a given to object ID.
268         * 
269         * @param types
270         *            Array of document type slected by the mcrfrom content
271         * @param restriction
272         *            a first part of the to ID as String, it can be null
273         * @return the number of references
274         */
275        public int countReferenceLinkTo(String to, String[] types, String restriction) {
276            if ((to == null) || ((to = to.trim()).length() == 0)) {
277                logger.warn("The to value of a reference link is false, the link was " + "not added to the link table");
278                return 0;
279            }
280    
281            try {
282                if (((types != null) && (types.length > 0))) {
283                    String mydoctype = "";
284                    int cnt = 0;
285                    int idt = 0;
286    
287                    for (idt = 0; idt < types.length; idt++) {
288                        mydoctype = types[idt];
289                        cnt += persistenceclass.countTo(null, to, mydoctype, restriction);
290                    }
291    
292                    return cnt;
293                }
294                return persistenceclass.countTo(null, to, null, restriction);
295            } catch (Exception e) {
296                logger.warn("An error occured while searching for references of " + to + ".");
297            }
298    
299            return 0;
300        }
301    
302        /**
303         * The method count the number of references to a category of a
304         * classification without sub ID's and returns it as a Map
305         * 
306         * @param classid
307         *            the classification ID as MCRObjectID
308         * 
309         * @return a Map with key=categID and value=counted number of references
310         */
311        public Map<String, Number> countReferenceCategory(String classid) {
312            return persistenceclass.getCountedMapOfMCRTO(classid);
313        }
314    
315        /**
316         * The method count the number of references to a category of a
317         * classification.
318         * 
319         * @param classid
320         *            the classification ID as String
321         * @param categid
322         *            the category ID as String
323         * @return the number of references
324         */
325        public int countReferenceCategory(String classid, String categid) {
326            return countReferenceLinkTo(classid + "##" + categid, null, null);
327        }
328    
329        /**
330         * Returns a List of all link sources of <code>to</code>
331         * 
332         * @param to
333         *            The MCRObjectID to referenced.
334         * @return List of Strings (Source-IDs)
335         */
336        public Collection<String> getSourceOf(MCRObjectID to) {
337            return getSourceOf(to.getId());
338        }
339    
340        /**
341         * Returns a List of all link sources of <code>to</code>
342         * 
343         * @param to
344         *            The ID to referenced.
345         * @return List of Strings (Source-IDs)
346         */
347        public Collection<String> getSourceOf(String to) {
348            if ((to == null) || (to.length() == 0)) {
349                logger.warn("The to value of a reference link is false, the link was not found in the link table");
350                return Collections.emptyList();
351            }
352    
353            try {
354                return persistenceclass.getSourcesOf(to, null);
355            } catch (Exception e) {
356                logger.warn("An error occured while searching for references to " + to + ".");
357                return Collections.emptyList();
358            }
359        }
360    
361        /**
362         * Returns a List of all link sources of <code>to</code> and a special
363         * <code>type</code>
364         * 
365         * @param to
366         *            Destination-ID
367         * @param type
368         *            link reference type
369         * @return List of Strings (Source-IDs)
370         */
371        public Collection<String> getSourceOf(MCRObjectID to, String type) {
372            return getSourceOf(to.getId(), type);
373        }
374    
375        /**
376         * Returns a List of all link sources of <code>to</code> and a special
377         * <code>type</code>
378         * 
379         * @param to
380         *            Destination-ID
381         * @param type
382         *            link reference type
383         * @return List of Strings (Source-IDs)
384         */
385        public Collection<String> getSourceOf(String to, String type) {
386            if ((to == null) || (to.length() == 0)) {
387                logger.warn("The to value of a reference link is false, the link was not found in the link table");
388                return Collections.emptyList();
389            }
390            if ((type == null) || (type.length() == 0)) {
391                logger.warn("The type value of a reference link is false, the link was not found in the link table");
392                return Collections.emptyList();
393            }
394            checkType(type);
395    
396            try {
397                return persistenceclass.getSourcesOf(to, type);
398            } catch (Exception e) {
399                logger.warn("An error occured while searching for references to " + to + " with " + type + ".");
400                return Collections.emptyList();
401            }
402        }
403    
404        /**
405         * The method return a list of all source ID's of the refernce target to
406         * with the given type.
407         * 
408         * @param to
409         *            the refernce target to
410         * @param type
411         *            type of the refernce
412         * @return a list of ID's
413         */
414        public Collection<String> getSourceOf(String[] to, String type) {
415            if ((to == null) || (to.length == 0)) {
416                logger.warn("The to value of a reference link is false, the link was not found in the link table");
417                return Collections.emptyList();
418            }
419            LinkedList<String> ll = new LinkedList<String>();
420            try {
421                for (String singleTo : to) {
422                    ll.addAll(persistenceclass.getSourcesOf(singleTo, type));
423                }
424                return ll;
425            } catch (Exception e) {
426                logger.warn("An error occured while searching for references to " + to + ".");
427                return ll;
428            }
429        }
430    
431        /**
432         * Returns a List of all link destinations of <code>from</code> and a
433         * special <code>type</code>
434         * 
435         * @param from
436         *            Destination-ID
437         * @param type
438         *            link reference type
439         * @return List of Strings (Source-IDs)
440         */
441        public Collection<String> getDestinationOf(MCRObjectID from, String type) {
442            return getDestinationOf(from.getId(), type);
443        }
444    
445        /**
446         * Returns a List of all link destination of <code>from</code> and a
447         * special <code>type</code>
448         * 
449         * @param from
450         *            Source-ID
451         * @param type
452         *            Link reference type, this can be null. Current types are
453         *            classid, child, parent, reference and derivate.
454         * @return List of Strings (Destination-IDs)
455         */
456        public Collection<String> getDestinationOf(String from, String type) {
457            if ((from == null) || (from.length() == 0)) {
458                logger.warn("The to value of a reference link is false, the link was not found in the link table");
459                return Collections.emptyList();
460            }
461            if ((type == null) || (type.length() == 0)) {
462                logger.warn("The type value of a reference link is false, the link was not found in the link table");
463                return Collections.emptyList();
464            }
465            checkType(type);
466    
467            try {
468                return persistenceclass.getDestinationsOf(from, type);
469            } catch (Exception e) {
470                logger.warn("An error occured while searching for references from " + from + ".");
471                return Collections.emptyList();
472            }
473        }
474    
475    }