001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (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, jcarsique
016 */
017package org.nuxeo.common.utils;
018
019import java.io.File;
020import java.util.Map;
021import java.util.regex.Matcher;
022import java.util.regex.Pattern;
023
024/**
025 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
026 */
027public class FileMatcher {
028
029    private static final Pattern VAR = Pattern.compile("(.*)?\\{(.+):(.+)\\}(.*)?");
030
031    public static FileMatcher getMatcher(String path) {
032        Matcher m = VAR.matcher(path);
033        if (m.matches()) {
034            String prefix = m.group(1);
035            String key = m.group(2).trim();
036            String value = m.group(3).trim();
037            String suffix = m.group(4);
038            Pattern pattern = null;
039            if (prefix.length() == 0) {
040                if (suffix.length() == 0) {
041                    pattern = Pattern.compile("(" + value + ")");
042                } else {
043                    pattern = Pattern.compile("(" + value + ")" + suffix);
044                }
045            } else if (suffix.length() == 0) {
046                pattern = Pattern.compile(prefix + "(" + value + ")");
047            } else {
048                pattern = Pattern.compile(prefix + "(" + value + ")" + suffix);
049            }
050            return new FileMatcher(pattern, key);
051        }
052        return new FileMatcher(null, path);
053    }
054
055    public static FileMatcher getMatcher(File file) {
056        return getMatcher(file.getName());
057    }
058
059    /**
060     * Look for a matching file for the given path.
061     *
062     * @param path Searched file path, optionally including the pattern.
063     * @param map The pattern variable will be put in the given map if any. Since 5.5, map can be null.
064     * @return File found. Null if none.
065     */
066    public static File getMatchingFile(String path, Map<String, Object> map) {
067        File file = new File(path);
068        FileMatcher matcher = getMatcher(path);
069        if (matcher.getPattern() == null) {
070            return file;
071        }
072        // a pattern -> find the first file that match that pattern
073        File dir = file.getParentFile();
074        File[] list = dir.listFiles();
075        if (list != null) {
076            for (File f : list) {
077                if (matcher.match(f.getName())) {
078                    if (map != null) {
079                        map.put(matcher.getKey(), matcher.getValue());
080                    }
081                    return f;
082                }
083            }
084        }
085        return null;
086    }
087
088    protected final Pattern pattern;
089
090    protected final String key;
091
092    protected String value;
093
094    public FileMatcher(Pattern pattern, String key) {
095        this.pattern = pattern;
096        this.key = key;
097    }
098
099    public String getKey() {
100        return pattern != null ? key : null;
101    }
102
103    public Pattern getPattern() {
104        return pattern;
105    }
106
107    public String getValue() {
108        return value;
109    }
110
111    public boolean match(String name) {
112        value = null;
113        if (pattern != null) {
114            Matcher m = pattern.matcher(name);
115            if (m.matches()) {
116                value = m.group(1);
117                return true;
118            }
119            return false;
120        } else if (name.equals(key)) {
121            return true;
122        }
123        return false;
124    }
125
126}