001/* 
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 */
012package org.nuxeo.ecm.webengine.jaxrs.servlet.mapping;
013
014/**
015 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
016 */
017public class WildcardSegmentMatcher extends SegmentMatcher {
018
019    protected final char[] pattern;
020
021    public WildcardSegmentMatcher(String pattern) {
022        this.pattern = pattern.replace("**", "*").toCharArray();
023    }
024
025    public WildcardSegmentMatcher(char[] pattern) {
026        this.pattern = pattern;
027    }
028
029    @Override
030    public boolean matches(String segment) {
031        if (pattern.length == 0) {
032            return true;
033        }
034        return matches(segment.toCharArray(), 0, 0);
035    }
036
037    public boolean matches(char[] segment, int soff, int poff) {
038        if (poff == pattern.length) {
039            // pattern consumed
040            if (soff == segment.length) {
041                // segment consumed too
042                return true;
043            }
044            // segment is not yet consumed
045            if (pattern[pattern.length - 1] == '*') {
046                // last char is a wildcard => matched
047                return true;
048            }
049            return false;
050        }
051        if (soff == segment.length) {
052            // segment consumed but pattern is not yet consumed
053            if (poff + 1 == pattern.length && pattern[poff] == '*') {
054                // there is only one char remaining and it is a wildcard => matched
055                return true;
056            }
057            return false;
058        }
059
060        if (pattern[poff] == '*') {
061            // current pattern char is a wildcard - try all substrings
062            for (int i = soff; i < segment.length; i++) {
063                if (matches(segment, i, poff + 1)) {
064                    return true;
065                }
066            }
067            return false;
068        }
069
070        // test is the current char is matching
071        if (pattern[poff] != '?' && pattern[poff] != segment[soff]) {
072            return false; // not matching
073        }
074
075        // continue iteration on segments and matchers
076        return matches(segment, soff + 1, poff + 1);
077
078    }
079
080    @Override
081    public String toString() {
082        return new String(pattern);
083    }
084}