Package org.apache.activemq.apollo.util.path

Source Code of org.apache.activemq.apollo.util.path.PathParser$LitteralPathFilter

/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.apollo.util.path;

import org.fusesource.hawtbuf.AsciiBuffer;
import org.fusesource.hawtbuf.ByteArrayOutputStream;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.regex.*;

import static org.apache.activemq.apollo.util.path.Part.*;

/**
* Holds the delimiters used to parse paths.
*
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
*/
public class PathParser {

    public static class PathException extends RuntimeException {
        public PathException(String message) {
            super(message);
        }
    }

    public static final PathParser DEFAULT = new PathParser();

    public AsciiBuffer any_descendant_wildcard = new AsciiBuffer("**");
    public AsciiBuffer any_child_wildcard = new AsciiBuffer("*");
    public AsciiBuffer path_seperator = new AsciiBuffer(".");
    public Pattern part_pattern = Pattern.compile("[a-zA-Z0-9\\_\\-\\%\\~]+");

    public Path parsePath(AsciiBuffer subject) {
      ArrayList<Part> list = new ArrayList<Part>(10);
        int previous = 0;
        int lastIndex = subject.getLength() - 1;
        while (true) {
            int idx = subject.indexOf(path_seperator, previous);
            if (idx < 0) {
              AsciiBuffer buffer = subject.slice(previous, lastIndex + 1).ascii();
                list.add(parsePart(buffer));
                break;
            }
          AsciiBuffer buffer = subject.slice(previous, idx).ascii();
            list.add(parsePart(buffer));
            previous = idx + 1;
        }
        return new Path(new ArrayList(list));
    }

    private Part parsePart(AsciiBuffer value) {
        if( value.equals(any_child_wildcard) ) {
            return ANY_CHILD;
        } else if( value.equals(any_descendant_wildcard) ) {
            return ANY_DESCENDANT;
        } else {
            if( part_pattern==null || part_pattern.matcher(value.toString()).matches() ) {
                return new LiteralPart(value);
            } else {
                throw new PathException(String.format("Invalid destination path part: '%s', it does not match regex: %s", value, part_pattern));
            }
        }
    }

    /**
     * Converts the path back to the string representation.
     * @return
     */
    public String toString(Path path) {
        StringBuffer buffer = new StringBuffer();
        boolean first=true;
        for(Part p : path.parts) {
            if( !first ) {
                buffer.append(path_seperator);
            }
            buffer.append(p.toString(this));
            first = false;
        }
        return buffer.toString();
    }


    public void write(Path path, ByteArrayOutputStream os) throws IOException {
        boolean first=true;
        for(Part p : path.parts) {
            if( !first ) {
                path_seperator.writeTo(os);
            }
            new AsciiBuffer(p.toString(this)).writeTo(os);
            first = false;
        }
    }

    static interface PartFilter {
        public boolean matches(LinkedList<Part> remaining);
    }

    class LitteralPathFilter implements PartFilter {

        private final PartFilter next;
        private final LiteralPart path;

        public LitteralPathFilter(PartFilter next, LiteralPart path) {
            this.next = next;

            this.path = path;
        }
        public boolean matches(LinkedList<Part> remaining) {
            if( !remaining.isEmpty() ) {
                Part p = remaining.removeFirst();
                if( !path.matches(p) ) {
                    return false;
                }
                if( next!=null ) {
                    return next.matches(remaining);
                } else {
                    return remaining.isEmpty();
                }
            } else {
                return false;
            }
        }
    }

    static class AnyChildPathFilter implements PartFilter {
        private final PartFilter next;

        public AnyChildPathFilter(PartFilter next) {
            this.next = next;
        }
        public boolean matches(LinkedList<Part> remaining) {
            if( !remaining.isEmpty() ) {
                Part p = remaining.removeFirst();
                if( next!=null ) {
                    return next.matches(remaining);
                } else {
                    return remaining.isEmpty();
                }
            } else {
                return false;
            }
        }
    }

    static class AnyDecendentPathFilter implements PartFilter {
        private final PartFilter next;

        public AnyDecendentPathFilter(PartFilter next) {
            this.next = next;
        }
        public boolean matches(LinkedList<Part> remaining) {
            if( !remaining.isEmpty() ) {
                remaining.clear();
                return true;
            } else {
                return false;
            }
        }
    }

    public PathFilter parseFilter(AsciiBuffer path) {
        ArrayList<Part> parts = new ArrayList<Part>(parsePath(path).parts);
        Collections.reverse(parts);
        PartFilter last = null;
        for( Part p: parts) {
            if( p.isLiteral() ) {
                last = new LitteralPathFilter(last, (LiteralPart)p);
            } else if( p == ANY_CHILD ) {
                last = new AnyChildPathFilter(last);
            } else if( p == ANY_DESCENDANT ) {
                last = new AnyDecendentPathFilter(last);
            }
        }
        final PartFilter filter = last;
        return new PathFilter() {
            public boolean matches(Path path) {
                return filter.matches(new LinkedList(path.parts));
            }
        };
    }

    static public boolean containsWildCards(Path path) {
        for(Part p: path.parts) {
            if( p==ANY_DESCENDANT || p==ANY_CHILD) {
                return true;
            }
        }
        return false;
    }

}
TOP

Related Classes of org.apache.activemq.apollo.util.path.PathParser$LitteralPathFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.