001    /*
002     * $Revision: 15002 $ 
003     * $Date: 2009-03-25 09:36:28 +0100 (Wed, 25 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.ifs2;
025    
026    import java.util.Date;
027    import java.util.List;
028    import java.util.Map;
029    import java.util.TreeMap;
030    
031    import org.apache.commons.vfs.FileObject;
032    import org.apache.commons.vfs.Selectors;
033    import org.apache.commons.vfs.VFS;
034    import org.jdom.Element;
035    import org.jdom.Namespace;
036    import org.mycore.common.MCRConfiguration;
037    import org.mycore.common.MCRSessionMgr;
038    
039    /**
040     * A file or directory really stored by importing it from outside the system.
041     * Can be modified, updated and deleted, in contrast to virtual nodes.
042     * 
043     * @author Frank Lützenkirchen
044     */
045    public abstract class MCRStoredNode extends MCRNode {
046    
047        /**
048         * Any additional data of this node that is not stored in the file object
049         */
050        protected Element data;
051    
052        /**
053         * Returns a stored node instance that already exists
054         * 
055         * @param parent
056         *            the parent directory containing this node
057         * @param fo
058         *            the file object in local filesystem representing this node
059         * @param data
060         *            the additional data of this node that is not stored in the
061         *            file object
062         */
063        protected MCRStoredNode(MCRDirectory parent, FileObject fo, Element data) throws Exception {
064            super(parent, fo);
065            this.data = data;
066        }
067    
068        /**
069         * Creates a new stored node
070         * 
071         * @param parent
072         *            the parent directory
073         * @param name
074         *            the name of the node
075         * @param type
076         *            the node type, dir or file
077         */
078        protected MCRStoredNode(MCRDirectory parent, String name, String type) throws Exception {
079            super(parent, VFS.getManager().resolveFile(parent.fo, name));
080            data = new Element(type);
081            data.setAttribute("name", name);
082            parent.data.addContent(data);
083        }
084    
085        /**
086         * Deletes this node with all its data and children
087         */
088        public void delete() throws Exception {
089            data.detach();
090            fo.delete(Selectors.SELECT_ALL);
091            getRoot().saveAdditionalData();
092        }
093    
094        /**
095         * Renames this node.
096         * 
097         * @param name
098         *            the new file name
099         */
100        public void renameTo(String name) throws Exception {
101            FileObject fNew = VFS.getManager().resolveFile(fo.getParent(), name);
102            fo.moveTo(fNew);
103            fo = fNew;
104            fo.getContent().setLastModifiedTime(System.currentTimeMillis());
105            data.setAttribute("name", name);
106            getRoot().saveAdditionalData();
107        }
108    
109        /**
110         * Sets last modification time of this file to a custom value.
111         * 
112         * @param time
113         *            the time to be stored as last modification time
114         */
115        public void setLastModified(Date time) throws Exception {
116            fo.getContent().setLastModifiedTime(time.getTime());
117        }
118    
119        /**
120         * Sets a label for this node
121         * 
122         * @param lang
123         *            the xml:lang language ID
124         * @param label
125         *            the label in this language
126         */
127        public void setLabel(String lang, String label) throws Exception {
128            Element found = null;
129            for (Element child : (List<Element>) (data.getChildren("label")))
130                if (lang.equals(child.getAttributeValue("lang", Namespace.XML_NAMESPACE))) {
131                    found = child;
132                    break;
133                }
134    
135            if (found == null) {
136                found = new Element("label").setAttribute("lang", lang, Namespace.XML_NAMESPACE);
137                data.addContent(found);
138            }
139            found.setText(label);
140            getRoot().saveAdditionalData();
141        }
142    
143        /**
144         * Removes all labels set
145         */
146        public void clearLabels() throws Exception {
147            data.removeChildren("label");
148            getRoot().saveAdditionalData();
149        }
150    
151        /**
152         * Returns a map of all labels, sorted by xml:lang, Key is xml:lang, value
153         * is the label for that language.
154         */
155        public Map<String, String> getLabels() {
156            Map<String, String> labels = new TreeMap<String, String>();
157            for (Element label : (List<Element>) (data.getChildren("label")))
158                labels.put(label.getAttributeValue("lang", Namespace.XML_NAMESPACE), label.getText());
159            return labels;
160        }
161    
162        /**
163         * Returns the label in the given language
164         * 
165         * @param lang
166         *            the xml:lang language ID
167         * @return the label, or null if there is no label for that language
168         */
169        public String getLabel(String lang) {
170            for (Element label : (List<Element>) (data.getChildren("label")))
171                if (lang.equals(label.getAttributeValue("lang", Namespace.XML_NAMESPACE)))
172                    return label.getText();
173            return null;
174        }
175    
176        /**
177         * Returns the label in the current language, otherwise in default language,
178         * otherwise the first label defined, if any at all.
179         * 
180         * @return the label
181         */
182        public String getCurrentLabel() {
183            String currentLang = MCRSessionMgr.getCurrentSession().getCurrentLanguage();
184            String label = getLabel(currentLang);
185            if (label != null)
186                return label;
187    
188            String defaultLang = MCRConfiguration.instance().getString("MCR.Metadata.DefaultLang", "en");
189            label = getLabel(defaultLang);
190            if (label != null)
191                return label;
192    
193            return data.getChildText("label");
194        }
195    
196        /**
197         * Repairs additional metadata of this node
198         */
199        abstract void repairMetadata() throws Exception;
200    }