001    /*
002     * 
003     * $Revision: 14335 $ $Date: 2008-11-06 07:40:09 +0100 (Do, 06 Nov 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.datamodel.metadata;
025    
026    import java.util.ArrayList;
027    import java.util.Iterator;
028    
029    import org.apache.log4j.Logger;
030    import org.jdom.Element;
031    
032    import com.ibm.icu.util.Calendar;
033    import com.ibm.icu.util.GregorianCalendar;
034    
035    import org.mycore.common.MCRCalendar;
036    import org.mycore.common.MCRException;
037    
038    /**
039     * This class implements all methods for handling with the MCRMetaHistoryDate
040     * part of a metadata object. It use the GPL licensed ICU library of IBM.
041     * 
042     * @author Juergen Vogler
043     * @author Jens Kupferschmidt
044     * @author Thomas Junge
045     * @version $Revision: 14335 $ $Date: 2008-11-06 07:40:09 +0100 (Do, 06 Nov 2008) $
046     * @see <a href="http://www.icu-project.org/">http://www.icu-project.org/</a>
047     */
048    public class MCRMetaHistoryDate extends MCRMetaDefault {
049    
050        /** Logger */
051        protected static Logger LOGGER = Logger.getLogger(MCRMetaHistoryDate.class.getName());
052    
053        /** The maximal length of 'text' */
054        public static final int MCRHISTORYDATE_MAX_TEXT = 256;
055    
056        // Data of this class
057        private ArrayList<MCRMetaHistoryDateText> texts;
058    
059        private Calendar von;
060    
061        private Calendar bis;
062    
063        private int ivon;
064    
065        private int ibis;
066    
067        private String calendar;
068    
069        /**
070         * This is the constructor. <br>
071         * The language element was set to configured default. The text element is
072         * set to an empty string. The calendar is set to 'Gregorian Calendar'. The
073         * von value is set to MIN_JULIAN_DAY_NUMBER, the bis value is set to
074         * MAX_JULIAN_DAY_NUMBER;
075         */
076        public MCRMetaHistoryDate() {
077            super();
078            texts = new ArrayList<MCRMetaHistoryDateText>();
079            calendar = MCRCalendar.CALENDARS_INPUT[0];
080            setDefaultVon();
081            setDefaultBis();
082        }
083    
084        /**
085         * This is the constructor. <br>
086         * The language element was set. If the value of <em>default_lang</em> is
087         * null, empty or false <b>en </b> was set. The subtag element was set to
088         * the value of <em>set_subtag<em>. If the value of <em>set_subtag</em>
089         * is null or empty an exception was throwed. The type element was set to
090         * the value of <em>set_type<em>, if it is null, an empty string was set
091         * to the type element.<br />
092         * The text element is set to an empty string. The calendar is set to 'Gregorian Calendar'. The von value 
093         * is set to MIN_JULIAN_DAY_NUMBER, the bis value is set to MAX_JULIAN_DAY_NUMBER;
094         *
095         * @param set_datapart     the global part of the elements like 'metadata'
096         *                         or 'service'
097         * @param set_subtag      the name of the subtag
098         * @param default_lang    the default language
099         * @param set_type        the optional type string
100         * @param set_inherted    a value >= 0
101         * @exception MCRException if the parameter values are invalid
102         */
103        public MCRMetaHistoryDate(String set_datapart, String set_subtag, String default_lang, String set_type, int set_inherted) throws MCRException {
104            super(set_datapart, set_subtag, default_lang, set_type, set_inherted);
105            texts = new ArrayList<MCRMetaHistoryDateText>();
106            calendar = MCRCalendar.CALENDARS_INPUT[0];
107            setDefaultVon();
108            setDefaultBis();
109        }
110    
111        /**
112         * This method set the text field for the default language. If data exists,
113         * it overwrites the value of text.
114         * 
115         * @param set_text
116         *            the text string for a date or range
117         */
118        public final void setText(String set_text) {
119            setText(set_text, lang);
120        }
121    
122        /**
123         * This method set the text field for the given language. If data exists, it
124         * overwrites the value of text.
125         * 
126         * @param set_text
127         *            the text string for a date or range
128         * @param set_lang
129         *            the language of the text in the ISO format
130         */
131        public final void setText(String set_text, String set_lang) {
132            if (set_text == null) {
133                LOGGER.warn("The text field of MCRMeataHistoryDate is empty.");
134                return;
135            }
136            if (set_text.length() <= MCRHISTORYDATE_MAX_TEXT) {
137                set_text = set_text.trim();
138            } else {
139                set_text = set_text.substring(0, MCRHISTORYDATE_MAX_TEXT);
140            }
141            if (set_lang == null || set_lang.length() == 0) {
142                addText(set_text, lang);
143            } else {
144                addText(set_text, set_lang);
145            }
146        }
147    
148        /**
149         * This method add a MCRMetaHistoryDateTexts instance to the ArrayList of
150         * texts.
151         * 
152         * @param set_text
153         *            the text- String
154         * @param set_lang
155         *            the lang- String
156         */
157    
158        public final void addText(String set_text, String set_lang) {
159            if (set_text == null) {
160                LOGGER.warn("The text field of MCRMeataHistoryDate is empty.");
161                return;
162            }
163            if (set_lang == null || set_lang.length() == 0) {
164                LOGGER.warn("The lang field of MCRMeataHistoryDate is empty.");
165                return;
166            }
167            for (int i = 0; i < texts.size(); i++) {
168                if (texts.get(i).getLang().equals(set_lang)) {
169                    texts.remove(i);
170                    break;
171                }
172            }
173            texts.add(new MCRMetaHistoryDateText(set_text, set_lang));
174        }
175    
176        /**
177         * This method return the MCRMetaHistoryDateTexts instance with the
178         * corresponding language.
179         * 
180         * @param set_lang
181         *            the language String in ISO format
182         * @return an instance of MCRMetaHistoryDateTexts or null
183         */
184        public final MCRMetaHistoryDateText getText(String set_lang) {
185            if (set_lang == null)
186                return null;
187            for (int i = 0; i < texts.size(); i++) {
188                if (texts.get(i).getLang().equals(set_lang)) {
189                    return texts.get(i);
190                }
191            }
192            return null;
193        }
194    
195        /**
196         * This method return the MCRMetaHistoryDateTexts instance of the indexed
197         * element of the ArrayList.
198         * 
199         * @param index
200         *            the index of ArryList texts
201         * @return an instance of MCRMetaHistoryDateTexts or null
202         */
203        public final MCRMetaHistoryDateText getText(int index) {
204            if ((index >= 0) && (index < texts.size())) {
205                return texts.get(index);
206            }
207            return null;
208        }
209    
210        /**
211         * This method read the ArryList texts
212         * 
213         * @return an ArrayList of MCRMetaHistoryDateTexts instances
214         */
215        public final ArrayList<MCRMetaHistoryDateText> getTexts() {
216            return this.texts;
217        }
218    
219        /**
220         * This method read the size of texts
221         * 
222         * @return the size of the ArrayList of language dependence texts
223         */
224        public final int TextSize() {
225            return texts.size();
226        }
227    
228        /**
229         * The method set the calendar String value.
230         * 
231         * @param calstr
232         *            the calendar as String, one of CALENDARS.
233         */
234        public final void setCalendar(String calstr) {
235            if (calstr == null) {
236                calendar = MCRCalendar.TAG_GREGORIAN;
237                LOGGER.warn("The calendar field of MCRMeataHistoryDate is set to default " + MCRCalendar.TAG_GREGORIAN + ".");
238                return;
239            }
240            for (int i = 0; i < MCRCalendar.CALENDARS_INPUT.length; i++) {
241                if (MCRCalendar.CALENDARS_INPUT[i].equals(calstr)) {
242                    calendar = calstr;
243                    return;
244                }
245            }
246            calendar = MCRCalendar.TAG_GREGORIAN;
247            LOGGER.warn("The calendar field of MCRMeataHistoryDate is set to default " + MCRCalendar.TAG_GREGORIAN + ".");
248        }
249    
250        /**
251         * The method set the calendar String value.
252         * 
253         * @param cal
254         *            the date of the calendar.
255         */
256        public final void setCalendar(Calendar cal) {
257            if (cal instanceof GregorianCalendar) {
258                calendar = MCRCalendar.TAG_GREGORIAN;
259                return;
260            }
261            calendar = MCRCalendar.TAG_GREGORIAN;
262        }
263    
264        /**
265         * The method set the von values to the default.
266         */
267        public final void setDefaultVon() {
268            ivon = MCRCalendar.MIN_JULIAN_DAY_NUMBER;
269            von = (Calendar) new GregorianCalendar();
270            von.set(GregorianCalendar.JULIAN_DAY, MCRCalendar.MIN_JULIAN_DAY_NUMBER);
271        }
272    
273        /**
274         * The method set the bis values to the default.
275         */
276        public final void setDefaultBis() {
277            ibis = MCRCalendar.MAX_JULIAN_DAY_NUMBER;
278            bis = (Calendar) new GregorianCalendar();
279            bis.set(GregorianCalendar.JULIAN_DAY, MCRCalendar.MAX_JULIAN_DAY_NUMBER);
280        }
281    
282        /**
283         * This method set the von to the given date of a supported calendar.
284         * 
285         * @param set_date
286         *            the date of a ICU supported calendar.
287         */
288        public final void setVonDate(Calendar set_date) {
289            if (set_date == null) {
290                setDefaultVon();
291                LOGGER.warn("The calendar to set 'von' is null, default is set.");
292                return;
293            }
294            ivon = set_date.get(GregorianCalendar.JULIAN_DAY);
295            von = set_date;
296    
297        }
298    
299        /**
300         * This method set the von to the given date.
301         * 
302         * @param set_date
303         *            a date string
304         * @param calstr
305         *            the calendar as String, one of CALENDARS.
306         */
307        public final void setVonDate(String set_date, String calstr) {
308            Calendar c = von;
309            try {
310                c = MCRCalendar.getGregorianHistoryDate(set_date, false, calstr);
311            } catch (Exception e) {
312                LOGGER.warn("The von date " + set_date + " for calendar " + calstr + " is false.");
313                c = null;
314            }
315            setVonDate(c);
316        }
317    
318        /**
319         * This method set the bis to the given date of a supported calendar.
320         * 
321         * @param set_date
322         *            the date of a ICU supported calendar
323         */
324        public final void setBisDate(Calendar set_date) {
325            if (set_date == null) {
326                setDefaultBis();
327                LOGGER.warn("The calendar to set 'bis' is null, default is set.");
328                return;
329            }
330            ibis = set_date.get(GregorianCalendar.JULIAN_DAY);
331            bis = set_date;
332        }
333    
334        /**
335         * This method set the bis to the given date.
336         * 
337         * @param set_date
338         *            a date string
339         * @param calstr
340         *            the calendar as String, one of CALENDARS.
341         */
342        public final void setBisDate(String set_date, String calstr) {
343            Calendar c = bis;
344            try {
345                c = MCRCalendar.getGregorianHistoryDate(set_date, true, calstr);
346            } catch (Exception e) {
347                LOGGER.warn("The bis date " + set_date + " for calendar " + calstr + " is false.");
348                c = null;
349            }
350            setBisDate(c);
351        }
352    
353        /**
354         * This method get the 'text' text element.
355         * 
356         * @return the text String of the default language or an empty String
357         * @deprecated
358         */
359        public final String getText() {
360            if (texts.size() > 0) {
361                MCRMetaHistoryDateText h = getText(lang);
362                if (h != null)
363                    return h.getText();
364                else
365                    return "";
366            }
367            return "";
368        }
369    
370        /**
371         * This method get the 'calendar' text element.
372         * 
373         * @return the calendar string
374         */
375        public final String getCalendar() {
376            return calendar;
377        }
378    
379        /**
380         * This method get the von element as ICU-Calendar.
381         * 
382         * @return the date
383         */
384        public final Calendar getVon() {
385            return von;
386        }
387    
388        /**
389         * This method return the von as string.
390         * 
391         * @return the date
392         */
393        public final String getVonToGregorianString() {
394            return MCRCalendar.getDateToFormattedString(von);
395        }
396    
397        /**
398         * This method get the ivon element as Julian Day integer.
399         * 
400         * @return the date
401         */
402        public final int getIvon() {
403            return ivon;
404        }
405    
406        /**
407         * This method get the bis element as ICU-Calendar.
408         * 
409         * @return the date
410         */
411        public final Calendar getBis() {
412            return bis;
413        }
414    
415        /**
416         * This method return the bis as string.
417         * 
418         * @return the date
419         */
420        public final String getBisToGregorianString() {
421            return MCRCalendar.getDateToFormattedString(bis);
422        }
423    
424        /**
425         * This method get the ibis element as Julian Day integer.
426         * 
427         * @return the date
428         */
429        public final int getIbis() {
430            return ibis;
431        }
432    
433        /**
434         * This method reads the XML input stream part from a DOM part for the
435         * metadata of the document.
436         * 
437         * @param element
438         *            a relevant JDOM element for the metadata
439         */
440        public void setFromDOM(org.jdom.Element element) {
441            super.setFromDOM(element);
442            texts.clear(); // clear
443    
444            String langn = "";
445            String textn;
446            Iterator<org.jdom.Element> textchild = element.getChildren("text").iterator();
447            while (textchild.hasNext()) {
448                Element elmt = (Element) textchild.next();
449                textn = elmt.getText();
450                langn = elmt.getAttributeValue("lang", org.jdom.Namespace.XML_NAMESPACE);
451                if (langn != null) {
452                    setText(textn, langn);
453                } else {
454                    setText(textn);
455                }
456            }
457            setCalendar(element.getChildTextTrim("calendar"));
458            setVonDate(element.getChildTextTrim("von"), calendar);
459            setBisDate(element.getChildTextTrim("bis"), calendar);
460        }
461    
462        /**
463         * This method creates a XML stream for all data in this class, defined by
464         * the MyCoRe XML MCRMetaHistoryDate definition for the given subtag.
465         * 
466         * @exception MCRException
467         *                if the content of this class is not valid
468         * @return a JDOM Element with the XML MCRMetaHistoryDate part
469         */
470        public org.jdom.Element createXML() throws MCRException {
471            if (!isValid()) {
472                debug();
473                throw new MCRException("The content of MCRMetaHistoryDate is not valid.");
474            }
475    
476            org.jdom.Element elm = new org.jdom.Element(subtag);
477            elm.setAttribute("lang", lang, org.jdom.Namespace.XML_NAMESPACE);
478            elm.setAttribute("inherited", Integer.toString(inherited));
479            for (int i = 0; i < texts.size(); i++) {
480                org.jdom.Element elmt = new org.jdom.Element("text");
481                elmt.addContent((String) texts.get(i).getText());
482                elmt.setAttribute("lang", texts.get(i).getLang(), org.jdom.Namespace.XML_NAMESPACE);
483                elm.addContent(elmt);
484            }
485            if ((type != null) && ((type = type.trim()).length() != 0)) {
486                elm.setAttribute("type", type);
487            }
488            if ((calendar = calendar.trim()).length() != 0) {
489                elm.addContent(new org.jdom.Element("calendar").addContent(calendar));
490            }
491    
492            if (von != null) {
493                elm.addContent(new org.jdom.Element("ivon").addContent(Integer.toString(ivon)));
494                elm.addContent(new org.jdom.Element("von").addContent(getVonToGregorianString()));
495            }
496    
497            if (bis != null) {
498                elm.addContent(new org.jdom.Element("ibis").addContent(Integer.toString(ibis)));
499                elm.addContent(new org.jdom.Element("bis").addContent(getBisToGregorianString()));
500            }
501            return elm;
502        }
503    
504        /**
505         * This method checks the validation of the content of this class. The
506         * method returns <em>false</em> if
507         * <ul>
508         * <li>the number of texts is 0 (empty texts are delete)
509         * <li>von is null or bis is null or calendar is null
510         * </ul>
511         * otherwise the method returns <em>true</em>.
512         * 
513         * @return a boolean value
514         */
515        public boolean isValid() {
516            for (int i = 0; i < texts.size(); i++) {
517                MCRMetaHistoryDateText textitem = texts.get(i);
518                if (!textitem.isValid()) {
519                    texts.remove(i);
520                    i--;
521                }
522            }
523            if (texts.size() == 0)
524                return false;
525            if ((von == null) || (bis == null) || (calendar == null)) {
526                return false;
527            }
528            if (ibis < ivon) {
529                Calendar swp = (Calendar) von.clone();
530                setVonDate((Calendar) bis.clone());
531                setBisDate(swp);
532            }
533    
534            return true;
535        }
536    
537        /**
538         * This method make a clone of this class.
539         */
540        public Object clone() {
541            MCRMetaHistoryDate out = new MCRMetaHistoryDate(datapart, subtag, lang, type, inherited);
542            for (int i = 0; i < texts.size(); i++) {
543                MCRMetaHistoryDateText h = texts.get(i);
544                out.setText(h.getText(), h.getLang());
545            }
546            out.setVonDate(von);
547            out.setBisDate(bis);
548            out.setCalendar(calendar);
549            return out;
550        }
551    
552        /**
553         * This method put debug data to the logger (for the debug mode).
554         */
555        public void debug() {
556            super.debugDefault();
557            for (int i = 0; i < texts.size(); i++) {
558                LOGGER.debug("Text / lang         = " + texts.get(i).getText() + " / " + texts.get(i).getLang());
559            }
560            LOGGER.debug("Calendar           = " + calendar);
561            if (calendar.equals(MCRCalendar.TAG_GREGORIAN)) {
562                LOGGER.debug("Von (String)       = " + getVonToGregorianString());
563            }
564            LOGGER.debug("Von (JulianDay)    = " + ivon);
565            if (calendar.equals(MCRCalendar.TAG_GREGORIAN)) {
566                LOGGER.debug("Bis (String)       = " + getBisToGregorianString());
567            }
568            LOGGER.debug("Bis (JulianDay)    = " + ibis);
569            LOGGER.debug("Stop");
570            LOGGER.debug("");
571        }
572    
573        /**
574         * This class describes the structure of pair of language an text. The
575         * language notation is in the ISO format.
576         * 
577         */
578        protected class MCRMetaHistoryDateText {
579            private String datetext;
580    
581            private String lang;
582    
583            public MCRMetaHistoryDateText() {
584                this.datetext = "";
585                this.lang = DEFAULT_LANGUAGE;
586            }
587    
588            public MCRMetaHistoryDateText(String datetext, String lang) {
589                setText(datetext);
590                setLang(lang);
591            }
592    
593            /**
594             * This method get the datetext element as field text (String) .
595             * 
596             * @return the datetext
597             */
598    
599            public String getText() {
600                return this.datetext;
601            }
602    
603            /**
604             * This method set the datetext element as field text (String) .
605             * 
606             * @param datetext
607             *            the text String of a date value
608             */
609            public void setText(String datetext) {
610                if (datetext == null) {
611                    this.datetext = "";
612                } else {
613                    this.datetext = datetext;
614                }
615            }
616    
617            /**
618             * This method get the lang element as language field (String) .
619             * 
620             * @return the lang
621             */
622            public String getLang() {
623                return this.lang;
624            }
625    
626            /**
627             * This method set the lang element as language field (String) .
628             * 
629             * @param set_lang
630             *            the language String of a date value
631             */
632            public void setLang(String set_lang) {
633                if (set_lang == null) {
634                    this.lang = DEFAULT_LANGUAGE;
635                } else {
636                    this.lang = set_lang;
637                }
638            }
639            
640            /**
641             * This mehtod validate the content. If lang and text are not empty, it return true otherwise it return false.
642             * 
643             * @return true if the content is valid.
644             */
645            public boolean isValid() {
646                if ((this.lang.length() == 0) || (this.datetext.length() == 0)) return false;
647                return true;
648            }
649    
650        }
651    }