001/*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software 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 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020package org.crsh.util;
021
022import java.util.ArrayList;
023import java.util.Arrays;
024import java.util.Collections;
025import java.util.HashMap;
026import java.util.HashSet;
027import java.util.Iterator;
028import java.util.LinkedList;
029import java.util.List;
030import java.util.Map;
031import java.util.NoSuchElementException;
032import java.util.Set;
033import java.util.regex.Matcher;
034import java.util.regex.Pattern;
035
036public class Utils {
037
038  /** . */
039  private static final Iterator EMPTY_ITERATOR = Collections.emptyList().iterator();
040
041  public static <E> Iterator<E> iterator() {
042    @SuppressWarnings("unchecked")
043    Iterator<E> iterator = (Iterator<E>)EMPTY_ITERATOR;
044    return iterator;
045  }
046
047  public static <E> Iterator<E> iterator(final E element) {
048    return new BaseIterator<E>() {
049      boolean hasNext = true;
050      @Override
051      public boolean hasNext() {
052        return hasNext;
053      }
054      @Override
055      public E next() {
056        if (hasNext) {
057          hasNext = false;
058          return element;
059        } else {
060          throw new NoSuchElementException();
061        }
062      }
063    };
064  }
065
066  public static <E> ArrayList<E> newArrayList() {
067    return new ArrayList<E>();
068  }
069
070  public static <E> LinkedList<E> newLinkedList() {
071    return new LinkedList<E>();
072  }
073
074  public static <E> HashSet<E> newHashSet() {
075    return new HashSet<E>();
076  }
077
078  public static <K, V> HashMap<K, V> newHashMap() {
079    return new HashMap<K, V>();
080  }
081
082  public static <E> E first(Iterable<E> elements) {
083    Iterator<E> i = elements.iterator();
084    return i.hasNext() ? i.next() : null;
085  }
086
087  public static <K, V, M extends Map<K, V>> M map(M map, K key, V value) {
088    map.put(key, value);
089    return map;
090  }
091
092  public static <K, V> HashMap<K, V> map(K key, V value) {
093    HashMap<K, V> map = new HashMap<K, V>();
094    map.put(key, value);
095    return map;
096  }
097
098  public static <E> HashSet<E> set(E... elements) {
099    HashSet<E> set = new HashSet<E>(elements.length);
100    Collections.addAll(set, elements);
101    return set;
102  }
103
104  public static <E> List<E> list(E... elements) {
105    return Arrays.asList(elements);
106  }
107
108  public static <E> List<E> list(Iterable<E> iterable) {
109    return list(iterable.iterator());
110  }
111
112  public static <E> List<E> list(Iterator<E> iterator) {
113    ArrayList<E> list = new ArrayList<E>();
114    while (iterator.hasNext()) {
115      list.add(iterator.next());
116    }
117    return list;
118  }
119
120  public static int indexOf(CharSequence s, int off, char c) {
121    for (int len = s.length();off < len;off++) {
122      if (s.charAt(off) == c) {
123        return off;
124      }
125    }
126    return -1;
127  }
128
129  public static String trimLeft(String s) {
130    if (s == null) {
131      throw new NullPointerException("No null string accepted");
132    }
133    int index = 0;
134    int len = s.length();
135    while (index < len) {
136      if (s.charAt(index) == ' ') {
137        index++;
138      } else {
139        break;
140      }
141    }
142    if (index > 0) {
143      return s.substring(index);
144    } else {
145      return s;
146    }
147  }
148
149  public static <E> E notNull(E e1, E e2) {
150    if (e1 != null) {
151      return e1;
152    } else {
153      return e2;
154    }
155  }
156
157  private static final Pattern FOO = Pattern.compile("" +
158      "(\\*)" + // Wildcard *
159      "|" +
160      "(\\?)" + // Wildcard ?
161      "|" +
162      "(?:\\[([^)]+)\\])" + // Range
163      "|" +
164      "(\\\\.)" // Escape
165  );
166
167  /**
168   * Create a pattern that transforms a glob expression into a regular expression, the following task are supported
169   * <ul>
170   *   <li>* : Match any number of unknown characters</li>
171   *   <li>? : Match one unknown character</li>
172   *   <li>[characters] : Match a character as part of a group of characters</li>
173   *   <li>\ : Escape character</li>
174   * </ul>
175   *
176   * @param globex the glob expression
177   * @return the regular expression
178   * @throws NullPointerException when the globex argument is null
179   */
180  public static String globexToRegex(String globex) throws NullPointerException {
181    if (globex == null) {
182      throw new NullPointerException("No null globex accepted");
183    }
184    StringBuilder regex = new StringBuilder();
185    int prev = 0;
186    Matcher matcher = FOO.matcher(globex);
187    while (matcher.find()) {
188      int next = matcher.start();
189      if (next > prev) {
190        regex.append(Pattern.quote(globex.substring(prev, next)));
191      }
192      if (matcher.group(1) != null) {
193        regex.append(".*");
194      } else if (matcher.group(2) != null) {
195        regex.append(".");
196      } else if (matcher.group(3) != null) {
197        regex.append("[");
198        regex.append(Pattern.quote(matcher.group(3)));
199        regex.append("]");
200      } else if (matcher.group(4) != null) {
201        regex.append(Pattern.quote(Character.toString(matcher.group(4).charAt(1))));
202      } else {
203        throw new UnsupportedOperationException("Not handled yet");
204      }
205      prev = matcher.end();
206    }
207    if (prev < globex.length()) {
208      regex.append(Pattern.quote(globex.substring(prev)));
209    }
210    return regex.toString();
211  }
212
213}