001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 */
017package org.nuxeo.common.utils;
018
019import java.io.File;
020import java.util.Map;
021
022/**
023 * A file reference that can handle file name patterns. A file pattern can use named variable that will be substituted
024 * with the actual value of the file that matched the pattern.
025 * <p>
026 * Example: For a file pattern <code>nuxeo-automation-core-{v:.*}.jar</code> that will match a file named
027 * <code>nuxeo-automation-core-5.3.2.jar</code> the pattern variable will be <code>v=5.3.2</code>.
028 * <p>
029 * Note that only one pattern variable is supported.
030 * 
031 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
032 */
033public abstract class FileRef {
034
035    public static FileRef newFileRef(String path) {
036        return newFileRef(new File(path));
037    }
038
039    public static FileRef newFileRef(File file) {
040        if (file.getName().indexOf('{') > -1) {
041            return new PatternFileRef(file);
042        }
043        return new ExactFileRef(file);
044    }
045
046    /**
047     * Gets the file referenced by this object. If the FileRef could not be resolved then null is returned.
048     * 
049     * @return the referred file or null if none was found.
050     */
051    public abstract File getFile();
052
053    /**
054     * Whether the referred file has a name pattern.
055     */
056    public abstract boolean hasPattern();
057
058    /**
059     * Fill the given map with pattern variables.
060     */
061    public abstract void fillPatternVariables(Map<String, Object> vars);
062
063    public static class ExactFileRef extends FileRef {
064        protected final File file;
065
066        public ExactFileRef(String path) {
067            this(new File(path));
068        }
069
070        public ExactFileRef(File file) {
071            this.file = file;
072        }
073
074        public File getFile() {
075            return file;
076        }
077
078        public boolean hasPattern() {
079            return false;
080        }
081
082        public void fillPatternVariables(Map<String, Object> vars) {
083            // do nothing
084        }
085    }
086
087    public static class PatternFileRef extends FileRef {
088        protected File file;
089
090        protected String key;
091
092        protected String value;
093
094        public PatternFileRef(String path) {
095            this(new File(path));
096        }
097
098        public PatternFileRef(File file) {
099            File dir = file.getParentFile();
100            File[] files = dir.listFiles();
101            if (files != null) {
102                FileMatcher fm = FileMatcher.getMatcher(file);
103                for (File f : files) {
104                    if (fm.match(f.getName())) {
105                        key = fm.getKey();
106                        value = fm.getValue();
107                        this.file = f;
108                        break;
109                    }
110                }
111            }
112        }
113
114        public File getFile() {
115            return file;
116        }
117
118        public String getValue() {
119            return value;
120        }
121
122        public String getKey() {
123            return key;
124        }
125
126        public boolean hasPattern() {
127            return key != null;
128        }
129
130        public void fillPatternVariables(Map<String, Object> vars) {
131            if (key != null) {
132                vars.put(key, value);
133            }
134        }
135    }
136
137}