001    /*
002     * Copyright 2010 the original author or authors.
003     * 
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package com.hs.mail.imap.mailbox;
017    
018    import java.util.regex.Matcher;
019    import java.util.regex.Pattern;
020    
021    import org.apache.commons.lang.StringUtils;
022    
023    /**
024     * Expresses select criteria for mailboxes.
025     * 
026     * @author Won Chul Doh
027     * @since Mar 9, 2010
028     * 
029     */
030    public class MailboxQuery {
031    
032            private String expression;
033            private Matcher matcher;
034    
035            public MailboxQuery(String referenceName, String mailboxName) {
036                    this.expression = getExpression(referenceName, mailboxName,
037                                    Mailbox.folderSeparator);
038                    if (expression.indexOf('*') >= 0 || expression.indexOf('%') >= 0) {
039                            this.matcher = createMatcher(expression);
040                    }
041            }
042            
043            private static String getExpression(String referenceName,
044                            String mailboxName, String sep) {
045                    StringBuilder sb = new StringBuilder(referenceName);
046                    if (mailboxName.startsWith(sep)) {
047                            sb.append(mailboxName.substring(sep.length()));
048                    } else if (StringUtils.isEmpty(referenceName)) {
049                            sb.append(mailboxName);
050                    } else {
051                            sb.append(sep).append(mailboxName);
052                    }
053                    return sb.toString();
054            }
055            
056            public String getExpression() {
057                    return expression;
058            }
059    
060            public boolean containsWildcard() {
061                    return (matcher != null);
062            }
063            
064            private static Matcher createMatcher(String expression) {
065                    StringBuilder sb = new StringBuilder(expression.length());
066                    boolean quoted = false;
067                    for (int i = 0, n = expression.length(); i < n; i++) {
068                            char c = expression.charAt(i);
069                            if (c == '*' || c == '%') {
070                                    if (quoted) {
071                                            sb.append("\\E");
072                                            quoted = false;
073                                    }
074                                    sb.append((c == '*') ? ".*" : "[^\\.]*");
075                            } else {
076                                    if (!quoted) {
077                                            sb.append("\\Q");
078                                            quoted = true;
079                                    }
080                                    sb.append(c);
081                            }
082                    }
083                    if (quoted) {
084                            sb.append("\\E");
085                    }
086                    Pattern p = Pattern.compile(sb.toString());
087                    return p.matcher("");
088            }
089    
090            /**
091             * Is the given name a match for {@link #expression}
092             * 
093             * @param name
094             *            name to be matched
095             * @return true if the given name matches this expression, false otherwise
096             */
097            public boolean match(String name) {
098                    if (matcher != null) {
099                            matcher.reset(name);
100                            return matcher.matches();
101                    } else {
102                            return expression.equals(name);
103                    }
104            }
105    
106    }