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    
020    package org.crsh.cli.impl.lang;
021    
022    import java.io.IOException;
023    import java.lang.reflect.Array;
024    import java.util.Arrays;
025    import java.util.Iterator;
026    import java.util.NoSuchElementException;
027    import java.util.regex.Matcher;
028    import java.util.regex.Pattern;
029    
030    public class Util {
031    
032      /** . */
033      static final Object[] EMPTY_ARGS = new Object[0];
034    
035      /** . */
036      static final Pattern INDENT_PATTERN = Pattern.compile("(?<=^|\\n)[ \\t\\x0B\\f\\r]*(?=\\S)");
037    
038      /** . */
039      public static final String MAN_TAB = _tab(7);
040    
041      /** . */
042      public static final String MAN_TAB_EXTRA = _tab(7 + 4);
043    
044      /** . */
045      static final String[] tabIndex;
046    
047      static {
048        String[] tmp = new String[20];
049        for (int i = 0;i < tmp.length;i++) {
050          tmp[i] = _tab(i);
051        }
052        tabIndex = tmp;
053      }
054    
055      static String tab(int size) {
056        if (size < 0) {
057          throw new IllegalArgumentException();
058        }
059        if (size < tabIndex.length) {
060          return tabIndex[size];
061        } else {
062          return _tab(size);
063        }
064      }
065    
066      private static String _tab(int size) {
067        char[] tmp = new char[size];
068        Arrays.fill(tmp, ' ');
069        return new String(tmp);
070      }
071    
072      public static <A extends Appendable> A indent(int tab, CharSequence s, A appendable) throws IOException {
073        return indent(tab(tab), s, appendable);
074      }
075    
076      public static <A extends Appendable> A indent(String tab, CharSequence s, A appendable) throws IOException {
077        Matcher matcher = INDENT_PATTERN.matcher(s);
078        int prev = 0;
079        while (matcher.find()) {
080          int start = matcher.start();
081          appendable.append(s, prev, start);
082          appendable.append(tab);
083          prev = matcher.end();
084        }
085        appendable.append(s, prev, s.length());
086        return appendable;
087      }
088    
089      public static <T> Iterable<T[]> tuples(final Class<T> type, final Iterable<? extends T>... iterables) {
090        return new Iterable<T[]>() {
091          public Iterator<T[]> iterator() {
092            return new Iterator<T[]>() {
093              private final Iterator<?>[] iterators = new Iterator<?>[iterables.length];
094              private T[] next;
095              {
096                for (int i = 0;i < iterables.length;i++) {
097                  iterators[i] = iterables[i].iterator();
098                }
099              }
100              public boolean hasNext() {
101                if (next == null) {
102                  T[] tuple = (T[])Array.newInstance(type, 2);
103                  for (int i = 0;i < iterators.length;i++) {
104                    Iterator iterator = iterators[i];
105                    if (iterator.hasNext()) {
106                      tuple[i] = type.cast(iterator.next());
107                    } else {
108                      return false;
109                    }
110                  }
111                  next = tuple;
112                }
113                return true;
114              }
115              public T[] next() {
116                if (!hasNext()) {
117                  throw new NoSuchElementException();
118                }
119                T[] tmp = next;
120                next = null;
121                return tmp;
122              }
123              public void remove() {
124                throw new UnsupportedOperationException();
125              }
126            };
127          }
128        };
129      }
130    
131      public static <T> Iterable<? extends T> join(final Iterable<? extends T>... iterables) {
132        return new Iterable<T>() {
133          public Iterator<T> iterator() {
134            return new Iterator<T>() {
135              int index;
136              Iterator<? extends T> current;
137              T next;
138              public boolean hasNext() {
139                if (next == null) {
140                  while ((current == null || !current.hasNext()) && index < iterables.length) {
141                    current = iterables[index++].iterator();
142                  }
143                  if (current != null && current.hasNext()) {
144                    next = current.next();
145                  }
146                }
147                return next != null;
148              }
149              public T next() {
150                if (!hasNext()) {
151                  throw new NoSuchElementException();
152                }
153                T tmp = next;
154                next = null;
155                return tmp;
156              }
157              public void remove() {
158                throw new UnsupportedOperationException();
159              }
160            };
161          }
162        };
163      }
164    
165      /**
166       * Wrap an object with an {@link org.crsh.cli.impl.lang.Instance}.
167       *
168       * @param object the object to wrap
169       * @param <T> the instance generic type
170       * @return an {@link org.crsh.cli.impl.lang.Instance} wrapping the specified object
171       */
172      public static <T> Instance<T> wrap(final T object) {
173        return new Instance<T>() {
174          @Override
175          public <T1> T1 resolve(Class<T1> type) {
176            return null;
177          }
178          @Override
179          public T get() {
180            return object;
181          }
182        };
183      }
184    }