/*
Copyright (c) 2005 Leo SimonsPermission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import java.util.Map;
import java.util.Collection;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.HashMap;

public class Kernel {
  public static interface Pair {
    Object getKey();
    Object getValue();
  }
  
  public static interface Iterable {
    boolean hasNext();
    Object next();
  }
  
  public static interface IfClause {
    boolean skip(Object o);
  }
  
  public static interface ResultDescription {
    void accumulateResult(Object result);
    Object returnResult();
  }
  
  public static interface IterationBuilder {
    IterationBuilder skipIf(Kernel.IfClause clause);
    IterationBuilder skipUnless(Kernel.IfClause clause);
    IterationBuilder failIf(Kernel.IfClause clause);
    IterationBuilder failUnless(Kernel.IfClause clause);
    IterationBuilder returning(Kernel.ResultDescription resultDescription);
    Object exec(Object codeBlock);
  }
  
  public static IterationBuilder iterate(final Kernel.Iterable it) {
    return new IterationBuilderImpl(it);
  }
  
  public static Iterable over(final Collection o) {
    return new IterableImpl(o);
  }
  
  public static Iterable over(final Iterable o) {
    return new IterableImpl(o);
  }
  
  public static Iterable over(final Iterator o) {
    return new IterableImpl(o);
  }
  
  public static Iterable over(final Enumeration o) {
    return new IterableImpl(o);
  }
  
  public static Iterable pairs(final Map o) {
    return new PairedIterable(o);
  }
  
  public static IfClause keyIsInstanceOf(final Class c) {
    return new KeyIfClause(new InstanceOfIfClause(c));
  }
  
  public static IfClause keyIsNull() {
    return new KeyIfClause(new NullIfClause());
  }
  
  public static ResultDescription arrayOf(final Class c) {
    return new ArrayResultDescription(c);
  }
  
  public static void print(final String string, final Object o1) {
    print(string, new Object[] { o1 });
  }

  public static void print(final String string, final Object o1, final Object o2) {
    print(string, new Object[] { o1, o2 });
  }

  public static void print(final String string, final Object o1, final Object o2, final Object o3) {
    print(string, new Object[] { o1, o2, o3 });
  }

  public static void print(final String string, final Object o1, final Object o2, final Object o3,
        final Object o4) {
    print(string, new Object[] { o1, o2, o3, o4 });
  }
  
  public static void print(final String string, final Object o1, final Object o2, final Object o3,
        final Object o4, final Object o5) {
    print(string, new Object[] { o1, o2, o3, o4, o5 });
  }
  
  public static void print(final String string, final Object o1, final Object o2, final Object o3,
        final Object o4, final Object o5, final Object o6) {
    print(string, new Object[] { o1, o2, o3, o4, o5, o6 });
  }
  
  public static void print(final String string, final Object o1, final Object o2, final Object o3,
        final Object o4, final Object o5, final Object o6, final Object o7) {
    print(string, new Object[] { o1, o2, o3, o4, o5, o6, o7 });
  }
  
  public static void print(final String string, final Object o1, final Object o2, final Object o3,
        final Object o4, final Object o5, final Object o6, final Object o7, final Object o8) {
    print(string, new Object[] { o1, o2, o3, o4, o5, o6, o7, o8 });
  }
  
  public static void print(final String string, final Object o1, final Object o2, final Object o3,
        final Object o4, final Object o5, final Object o6, final Object o7, final Object o8, final Object o9) {
    print(string, new Object[] { o1, o2, o3, o4, o5, o6, o7, o8, o9 });
  }
  
  public static void print(String string, Object[] os) {
    throw new UnsupportedOperationException("Not implemented!"); // TODO
  }
  
  public static void main(String[] args) {
    KernelTest.main(args);
  }
}

class IterationBuilderImpl implements Kernel.IterationBuilder {
    public IterationBuilderImpl(Kernel.Iterable it)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }

    public Kernel.IterationBuilder skipIf(Kernel.IfClause clause)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }

    public Kernel.IterationBuilder skipUnless(Kernel.IfClause clause)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
    
    public Kernel.IterationBuilder failIf(Kernel.IfClause clause)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
    
    public Kernel.IterationBuilder failUnless(Kernel.IfClause clause)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
    
    public Kernel.IterationBuilder returning(Kernel.ResultDescription resultDescription)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
    
    public Object exec(Object codeBlock)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
}

class IterableImpl implements Kernel.Iterable {
    public IterableImpl(Collection c)
    {
    }
    
    public IterableImpl(Kernel.Iterable i)
    {
    }
    
    public IterableImpl(Iterator i)
    {
    }
    
    public IterableImpl(Enumeration e)
    {
    }

    public boolean hasNext()
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
    
    public Object next()
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
}

class PairedIterable implements Kernel.Iterable {
    public PairedIterable(Map m)
    {
    }

    public boolean hasNext()
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
    
    public Object next()
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
}

class NullIfClause implements Kernel.IfClause {
    public boolean skip(Object o)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
}

class InstanceOfIfClause implements Kernel.IfClause {
    public InstanceOfIfClause(Class c)
    {
    }

    public boolean skip(Object o)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
}

class KeyIfClause implements Kernel.IfClause {
    public KeyIfClause(Kernel.IfClause ic)
    {
    }
    
    public boolean skip(Object o)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
}

class ArrayResultDescription implements Kernel.ResultDescription {
    public ArrayResultDescription(Class c)
    {
    }

    public void accumulateResult(Object result)
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
    
    public Object returnResult()
    {
        throw new UnsupportedOperationException("Not implemented!"); // TODO
    }
}
  
class KernelTest extends Kernel {
  public static void main(final String[] args) {
    final Map coll = new HashMap();

    final Kernel.Pair[] pairs = (Kernel.Pair[])iterate(
      over(pairs(   coll   )))
        .skipIf(keyIsInstanceOf(   UnprocessableObject.class   ))
        .skipIf(keyIsNull())
        .failIf(keyIsInstanceOf(   ProcessableObject.class   ))
        .returning(arrayOf(   Pair.class   ))
        .exec(
          new Object(){Object process(   Kernel.Pair pair   ){
            print("%s -> %s", pair.getKey(), pair.getValue());
            return pair;
          }});
  }
  
  static class UnprocessableObject {}
  static class ProcessableObject {}
}
