All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.altova.functions.Core Maven / Gradle / Ivy

There is a newer version: 2.0.4
Show newest version
/**
 * Core.java
 *
 * This file was generated by MapForce 2017sp2.
 *
 * YOU SHOULD NOT MODIFY THIS FILE, BECAUSE IT WILL BE
 * OVERWRITTEN WHEN YOU RE-RUN CODE GENERATION.
 *
 * Refer to the MapForce Documentation for further details.
 * http://www.altova.com/mapforce
 */

package com.altova.functions;

import java.io.*;
import java.math.BigInteger;
import java.math.BigDecimal;
import java.lang.String;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.regex.*;
import com.altova.types.*;
import com.altova.CoreTypes;
import com.altova.mapforce.IEnumerable;
import com.altova.mapforce.IEnumerator;
import com.altova.mapforce.MFEmptySequence;
import com.altova.mapforce.MFSingletonSequence;
import com.altova.mapforce.SequenceFactory;

public class Core
{
	public static com.altova.mapforce.IMFNode shallowCopy(com.altova.mapforce.IMFNode source, IEnumerable content)
	{
		if (source.getNodeKind() == com.altova.mapforce.IMFNode.MFNodeKind_Attribute || source.getNodeKind() == com.altova.mapforce.IMFNode.MFNodeKind_Field)
			return new com.altova.mapforce.MFAttribute(source.getLocalName(), source.getNamespaceURI(), source.getPrefix(), content);
		return new com.altova.mapforce.MFElement(source.getLocalName(), source.getNamespaceURI(), source.getPrefix(), content);
	}

	public static class Group
	{
		Object key;
		IEnumerable items;
		
		public Group (Object k, IEnumerable i)
		{
			key = k;
			items = i;
		}
		
		public IEnumerable getItems() {return items;}
		public Object getKey() {return key;}
	}
	
	public static class SequenceCache implements IEnumerable
	{
		ArrayList elements;
		IEnumerable sourceSequence = null;
		
		class Enumerator implements IEnumerator
		{
			SequenceCache cache;
			int pos = 0;
			
			public Enumerator(SequenceCache sc)
			{
				cache = sc;
			}
			
			public Object current() 
			{
				return cache.elements.get(pos-1);
			}

			public boolean moveNext() throws Exception 
			{
				if (cache.sourceSequence != null)
					SequenceCache.fillCache(cache);
				
				return ++pos <= cache.elements.size();
			}

			public int position() 
			{
				return pos;
			}
			
			public void close() {}
		}
		
		public SequenceCache(IEnumerable source) 
		{
			sourceSequence = source;
			elements = new ArrayList();
		}

		public IEnumerator enumerator() throws Exception 
		{
			return new Enumerator(this);			
		}
		
		public void append(Object o)
		{
			elements.add(o);
		}
		
		static public void fillCache(SequenceCache sc) throws Exception
		{
			IEnumerator en = sc.sourceSequence.enumerator();
			while (en.moveNext())
				sc.append(en.current());
			
			en.close();
			sc.sourceSequence = null;
		}
	}
	
	public static IEnumerable distinctValues(IEnumerable x)
	{
		class DistinctEnumerable implements IEnumerable
		{
			IEnumerable x;
			
			class Enumerator implements IEnumerator 
			{
				IEnumerator x;
				HashSet v;
				int pos = 0;
				
				public Enumerator(IEnumerator x)
				{
					this.x = x; 
					v = new HashSet();
				}
				
				public boolean moveNext() throws Exception
				{
					while (x.moveNext())
					{
						if (v.add(x.current()))
						{
							pos++;
							return true;
						}
					}
					return false;
				}
				
				public Object current()
				{
					return x.current();
				}
				
				public int position() {return pos;}
				
				public void close() {x.close();}
			}
			
			public DistinctEnumerable(IEnumerable x)
			{
				this.x = x;
			}
			
			public IEnumerator enumerator() throws Exception { return new Enumerator(x.enumerator()); }
		}
		
		return new DistinctEnumerable(x);
	}
	
	public static String groupingKey(Group g)
	{
		return (String) g.getKey();
	}
		
	static IEnumerable concatMaps(IEnumerable x, SequenceFactory y)
	{
		class ConcatMaps implements IEnumerable
		{	
			IEnumerable x;
			SequenceFactory y;
			
			class Enumerator implements IEnumerator
			{
				IEnumerator x;
				SequenceFactory y;
				IEnumerator results = null;
				int pos = 0;
				
				public Enumerator(IEnumerator source, SequenceFactory lambda)
				{
					x = source;
					y = lambda;
				}
				
				public Object current()
				{
					return results.current();
				}

				public boolean moveNext() throws Exception 
				{
					while (true)
					{
						if (results == null)
						{
							if (!x.moveNext())
								return false;
							
							IEnumerable res = (IEnumerable) y.invoke(x.current());
							
							results = res.enumerator();
						}
						
						if (results.moveNext())
						{
							pos++;
							return true;
						}
						
						results.close();
						results = null;
					}
				}

				public int position() 
				{
					return pos;
				}
				
				public void close() {x.close();}
			}
			
			public ConcatMaps(IEnumerable source, SequenceFactory lambda)
			{
				x = source;
				y = lambda;
			}
			
			public IEnumerator enumerator() throws Exception 
			{
				return new Enumerator(x.enumerator(), y);
			}
			
		}
		
		return new ConcatMaps(x, y); 
	}
	
	static IEnumerable map(IEnumerable x, SequenceFactory y)
	{
		class Map implements IEnumerable
		{
			IEnumerable x;
			SequenceFactory y;
			
			class Enumerator implements IEnumerator
			{
				int pos = 0;
				IEnumerator x;
				SequenceFactory y;
				
				public Enumerator(IEnumerator source, SequenceFactory lambda)
				{
					x = source;
					y = lambda;
				}
				
				public Object current()
				{
					return y.invoke(x.current());
				}

				public boolean moveNext() throws Exception 
				{
					if(!x.moveNext())
						return false;
					pos++;
					return true;
				}

				public int position() 
				{
					return pos;
				}
				
				public void close() {x.close();}
			}
			
			public Map(IEnumerable source, SequenceFactory lambda)
			{
				x = source;
				y = lambda;
			}
			public IEnumerator enumerator() throws Exception {return new Enumerator(x.enumerator(), y);}
		}
		
		return new Map(x, y);
	}
	
	static IEnumerable filter(IEnumerable x, SequenceFactory y)
	{
		class FilterEnumerable implements IEnumerable
		{
			IEnumerable x;
			SequenceFactory y;
			
			class Enumerator implements IEnumerator
			{
				IEnumerator x;
				SequenceFactory y;
				int pos = 0;
				
				public Enumerator (IEnumerator source, SequenceFactory lambda)
				{
					x = source;
					y = lambda;
				}
				
				public Object current()
				{
					return x.current();
				}

				public boolean moveNext() throws Exception 
				{
					while (true)
					{
						if (!x.moveNext())
							return false;
						
						Object result = y.invoke(x.current());
						if (result instanceof Boolean && ((Boolean) result).booleanValue())
						{
							++pos;
							return true;
						}
					}
				}

				public int position() 
				{
					return pos;
				}
				
				public void close() {x.close();}
			}

			public FilterEnumerable(IEnumerable source, SequenceFactory lambda)
			{
				x = source;
				y = lambda;
			}
			
			public IEnumerator enumerator() throws Exception 
			{
				return new Enumerator(x.enumerator(), y);
			}
		}
		
		return new FilterEnumerable(x, y);
	}
	
	static Object elem(Object x, Object c)
	{
		try 
		{
			for (IEnumerator e = ((IEnumerable)c).enumerator(); e.moveNext();)
			{
				if (x.toString().equals(e.current().toString()))
					return true;
			}
		} 
		catch (Exception e) 
		{
			throw new UnsupportedOperationException(e.getMessage());
		}
		
		return false;
	}
	
	public static IEnumerable groupItems(Group g)
	{
		return g.getItems();
	}
	
	public static IEnumerable groupBy(IEnumerable x, SequenceFactory y)
	{
		class BuildGroup implements SequenceFactory
		{
			class CheckKey implements SequenceFactory
			{
				Object x;
				SequenceFactory y;
				
				public CheckKey(Object source, SequenceFactory lambda)
				{
					x = source;
					y = lambda;
				}
				
				public Object invoke(Object o)
				{
					return elem(x, y.invoke(o));
				}
			}
			IEnumerable x;
			SequenceFactory y;
			
			public BuildGroup (IEnumerable source, SequenceFactory lambda)
			{
				x = source;
				y = lambda;
			}
			
			public Object invoke(Object source)
			{
				return new Group(source, filter(x, new CheckKey(source, y)));
			}
		}
		
		return map(distinctValues(concatMaps(x, y)), new BuildGroup(x, y));
	}
	
	public static IEnumerable groupAdjacent(IEnumerable x, SequenceFactory y)
	{
		class GroupAdjacent implements IEnumerable
		{
			IEnumerable x;
			SequenceFactory y;
			
			class Enumerator implements IEnumerator
			{
				IEnumerator base;
				Object head;
				Object cur;
				SequenceFactory y;
				
				int pos = 0;
				
				public Enumerator(IEnumerator source, SequenceFactory lambda)
				{
					base = source;
					y = lambda;
					
				}
				public Object current() 
				{
					return cur;
				}
				
				public boolean moveNext() throws Exception 
				{
					if (head == null)
					{
						if (!base.moveNext())
							return false;
						head = base.current();
					}
					
					SequenceCache result = new SequenceCache(null);
					result.append(head);
					Object groupKeys = y.invoke(head);
					Object groupKey = first((IEnumerable) groupKeys);
					String keyString = groupKey.toString();
					
					while (true)
					{
						if (!base.moveNext())
						{
							head = null;
							break;
						}
						
						head = base.current();
						Object itemKeys = y.invoke(head);
						Object itemKey = first((IEnumerable)itemKeys);
						if (keyString.equals(itemKey.toString()))
							result.append(head);
						else
							break;	
					}
					
					cur = new Group(groupKey, result);
					pos++;
					return true;
				}

				public int position() 
				{
					return pos;
				}
				
				public void close() {base.close();}
			}
						
			public GroupAdjacent(IEnumerable source, SequenceFactory lambda)
			{
				x = source;
				y = lambda;
			}

			public IEnumerator enumerator() throws Exception 
			{
				return new Enumerator(x.enumerator(), y);
			}
		}
		
		return new GroupAdjacent(x, y);
	}
	
	public static IEnumerable groupStartingWith(IEnumerable x, SequenceFactory y)
	{
		class GroupStartingWith implements IEnumerable
		{
			IEnumerable source;
			SequenceFactory lambda;
			
			class Enumerator implements IEnumerator
			{
				IEnumerator base;
				SequenceFactory lambda;
				Object head;
				Object cur;
				int pos = 0;
				
				public Enumerator(IEnumerator x, SequenceFactory y)
				{
					base = x;
					lambda = y;
				}
				
				public Object current() 
				{
					return cur;
				}

				public boolean moveNext() throws Exception 
				{
					if (head == null)
					{
						if (!base.moveNext())
							return false;
						head = base.current();
					}
					
					SequenceCache result = new SequenceCache(null);
					result.append(head);
					
					while(true)
					{
						if (!base.moveNext())
						{
							head = null;
							break;
						}
					
						head = base.current();
						Object itemKeys = lambda.invoke(head);
						Object itemKey = first((IEnumerable) itemKeys);
						boolean b = ((Boolean) itemKey).booleanValue();
						if (b)
							break;
						else
							result.append(head);
					}
					
					cur = new Group(new MFEmptySequence(), result);
					pos++;
					return true;
				}

				public int position() 
				{
					return pos;
				}	
				
				public void close() {base.close();}
			}
			
			public GroupStartingWith(IEnumerable x, SequenceFactory y)
			{
				source = x;
				lambda = y;
			}
			
			public IEnumerator enumerator() throws Exception 
			{
				return new Enumerator(source.enumerator(), lambda);
			}
		}
		
		return new GroupStartingWith(x, y);
	}
	
	public static IEnumerable groupEndingWith(IEnumerable x, SequenceFactory y)
	{
		class GroupEndingWith implements IEnumerable
		{
			IEnumerable source;
			SequenceFactory lambda;
			
			class Enumerator implements IEnumerator
			{
				IEnumerator base;
				SequenceFactory lambda;
				Object cur;
				int pos = 0;
				
				public Enumerator(IEnumerator x, SequenceFactory y)
				{
					base = x;
					lambda = y;
				}
				
				public Object current() 
				{
					return cur;
				}

				public boolean moveNext() throws Exception 
				{
					if (!base.moveNext())
							return false;
					
					SequenceCache result = new SequenceCache(null);
										
					while(true)
					{					
						Object p = base.current();
						result.append(p);
						Object itemKeys = lambda.invoke(p);
						Object itemKey = first((IEnumerable) itemKeys);
						boolean b = ((Boolean) itemKey).booleanValue();
						if (b)
							break;
						if (!base.moveNext())
							break;
					}
					
					cur = new Group(new MFEmptySequence(), result);
					pos++;
					return true;
				}

				public int position() 
				{
					return pos;
				}	
				
				public void close() {base.close();}
			}
			
			public GroupEndingWith(IEnumerable x, SequenceFactory y)
			{
				source = x;
				lambda = y;
			}
			
			public IEnumerator enumerator() throws Exception 
			{
				return new Enumerator(source.enumerator(), lambda);
			}
		}
		
		return new GroupEndingWith(x, y);
	}

	public static IEnumerable groupIntoBlocks( IEnumerable sequence, BigInteger blocksize )
	{
		class GroupIntoBlocks implements IEnumerable
		{
			IEnumerable sequence;
			BigInteger blocksize;

			public GroupIntoBlocks( IEnumerable sequence, BigInteger blocksize )
			{
				this.sequence = sequence;
				this.blocksize = blocksize;
			}

			public IEnumerator enumerator() throws Exception 
			{
				return new Enumerator( sequence.enumerator(), blocksize );
			}

			class Enumerator implements IEnumerator
			{
				IEnumerator enumerator;
				BigInteger blocksize;
				Object cur;
				int pos = 0;

				public Enumerator( IEnumerator enumerator, BigInteger blocksize )
				{
					this.enumerator = enumerator;
					this.blocksize = blocksize;
				}

				public Object current()
				{
					return cur;
				}

				public boolean moveNext() throws Exception
				{
					SequenceCache result = new SequenceCache( null );

					for ( BigInteger i = BigInteger.ZERO; i.compareTo( blocksize ) < 0; i = i.add( BigInteger.ONE ) )
					{
						if ( !enumerator.moveNext() )
							if ( i.compareTo( BigInteger.ZERO ) == 0 )
								return false;
							else
								break;

						result.append( enumerator.current() );
					}

					cur = new Group( new MFEmptySequence(), result );
					pos++;
					return true;
				}

				public int position()
				{
					return pos;
				}

				public void close() { enumerator.close(); }
			}
		}

 		if (blocksize.compareTo(BigInteger.ONE) < 0)
			throw new IllegalArgumentException("The group size " + blocksize + " is invalid since it must be greater than or equal one.");

		return new GroupIntoBlocks( sequence, blocksize );
	}

	public static IEnumerable resolveFilename( String pattern )
	{
		class WildCardFileFilter implements FileFilter
		{
			private String _pattern;
			private boolean _caseInsensitive;
		 
			public WildCardFileFilter(String pattern)
			{
				_pattern = "^" + pattern.replace(".", "\\x2E").replace("*", ".*").replace("?", ".") + "$";
				//String osName = java.lang.System.getProperty("os.name").toLowerCase();
				// _caseInsensitive = osName.contains("windows") || osName.contains("mac os x"); 
				_caseInsensitive = false;
				File upperA = new File("A");
				File lowerA = new File("a");
				if (upperA.compareTo(lowerA) == 0)
					_caseInsensitive = true;
			}
		 
			public boolean accept(File file)
			{
				if (file.isDirectory()) 
					return false;

				Pattern pattern;
				if (_caseInsensitive)
					pattern = Pattern.compile(_pattern, Pattern.CASE_INSENSITIVE);
				else
					pattern = Pattern.compile(_pattern);
					
				return pattern.matcher(file.getName()).find();
			}
		}

		class ResolveFilenameEnumerable implements IEnumerable
		{
			String pattern;
			
			class Enumerator implements IEnumerator
			{
				File files[];
				int pos = -1;
				
				public Enumerator ( String pattern )
				{
					int nsep = pattern.replace('\\', '/').lastIndexOf('/') + 1;
					String rootpath = pattern.substring(0, nsep);
					if ( rootpath.length() == 0 )
						rootpath = ".";
					String searchpattern = pattern.substring(nsep);
					File dir = new File(rootpath);
					files = dir.listFiles(new WildCardFileFilter(searchpattern));
				}
				
				public Object current()
				{
					if (pos == -1) throw new UnsupportedOperationException("No current.");
					return files[pos].toString();
				}

				public boolean moveNext() throws Exception 
				{
					return files==null ? false : (++pos) < files.length;
				}

				public int position() 
				{
					return pos;
				}
				
				public void close() {}
			}

			public ResolveFilenameEnumerable( String _pattern )
			{
				pattern = _pattern;
			}
			
			public IEnumerator enumerator() throws Exception 
			{
				return new Enumerator( pattern );
			}
		}
		
		if (pattern.indexOf(":") > 1)       // URLs can't be resolved
				return box(pattern);
		return new ResolveFilenameEnumerable( pattern );
	}
	
	public static com.altova.mapforce.IMFNode resultDocument(String filename, String encoding, com.altova.mapforce.IMFNode content) 
	{
		return  (new com.altova.mapforce.MFDocument(filename, box(content)));
	}
	
	public static com.altova.mapforce.IMFNode resultDocument(String filename, String encoding, IEnumerable content) 
	{
		return  (new com.altova.mapforce.MFDocument(filename, content));
	}
	
	public static IEnumerable avg(IEnumerable source) throws Exception
	{
		IEnumerator en = source.enumerator();
		if (!en.moveNext())
		{
			en.close();
			return new MFEmptySequence();
		}
		
		BigDecimal acc = (BigDecimal) en.current();
		int cnt = 1;
		while (en.moveNext())
		{
			acc = acc.add((BigDecimal)en.current());
			++cnt;
		}
		en.close();
		return new MFSingletonSequence(Core.divide(acc, BigDecimal.valueOf(cnt)));
	}
	
	public static BigDecimal sum(IEnumerable source) throws Exception
	{
		IEnumerator en = source.enumerator();
		BigDecimal acc = BigDecimal.ZERO;
		while (en.moveNext())
			acc = acc.add((BigDecimal)en.current());
		en.close();
		return acc;
	}
	
	public static int count(IEnumerable source) throws Exception 
	{
		IEnumerator en = source.enumerator();
		int cnt = 0;
		while (en.moveNext()) ++cnt;
		en.close();
		return cnt;
	}
	
	public static IEnumerable max(IEnumerable source) throws Exception
	{
		IEnumerator en = source.enumerator();
		if (!en.moveNext())
		{
			en.close();
			return new MFEmptySequence();
		}
		BigDecimal max = (BigDecimal)en.current();
		while (en.moveNext())
		{
			BigDecimal x = (BigDecimal) en.current();
			max = max.max(x);
		}
		en.close();
		return new MFSingletonSequence(max);			
	}

	public static IEnumerable min(IEnumerable source) throws Exception
	{
		IEnumerator en = source.enumerator();
		if (!en.moveNext())
		{
			en.close();
			return new MFEmptySequence();
		}
		BigDecimal min = (BigDecimal)en.current();
		while (en.moveNext())
		{
			BigDecimal x = (BigDecimal) en.current();
			min = min.min(x);
		}
		en.close();
		return new MFSingletonSequence(min);			
	}
	
	public static IEnumerable maxString(IEnumerable source) throws Exception
	{
		IEnumerator en = source.enumerator();
		if (!en.moveNext())
		{
			en.close();
			return new MFEmptySequence();
		}
		String max = (String)en.current();
		while (en.moveNext())
		{
			String x = (String) en.current();
			if (max.compareTo(x) < 0)
				max = x;
		}
		en.close();
		return new MFSingletonSequence(max);			
	}

	public static IEnumerable minString(IEnumerable source) throws Exception
	{
		IEnumerator en = source.enumerator();
		if (!en.moveNext())
		{
			en.close();
			return new MFEmptySequence();
		}
		String min = (String)en.current();
		while (en.moveNext())
		{
			String x = (String) en.current();
			if (min.compareTo(x) > 0)
				min = x;
		}
		en.close();
		return new MFSingletonSequence(min);			
	}
	
	public static String stringJoin(IEnumerable source, IEnumerable delimiter) throws Exception
	{
		String delim = "";
		if (exists(delimiter)) delim = (String) first(delimiter);
		IEnumerator en = source.enumerator();
		if (!en.moveNext())
		{
			en.close();
			return "";
		}
		StringBuffer builder = new StringBuffer((String)en.current());
		while (en.moveNext())
		{
			builder.append(delim);
			builder.append((String)en.current());
		}
		en.close();
		return builder.toString();
	}
	
	public static IEnumerable box(Object o) 
	{ 
		return new MFSingletonSequence(o); 
	}
	
	public static Object first(IEnumerable e) throws Exception
	{ 
		IEnumerator r = e.enumerator(); 
		if (!r.moveNext()) throw new UnsupportedOperationException("The source node does not exist, which is invalid.\nIn order to process invalid input, disable optimizations based on min/maxOccurs in component settings."); 
		Object o = r.current();
		r.close();
		return o; 
	}

	public static Object last(IEnumerable e) throws Exception
	{ 
		IEnumerator r = e.enumerator(); 
		if (!r.moveNext()) 
			throw new UnsupportedOperationException("The source node does not exist, which is invalid.\nIn order to process invalid input, disable optimizations based on min/maxOccurs in component settings.");
		
		Object o = r.current();
		while (r.moveNext())
			o = r.current();
		r.close();
		return o; 
	}
	
		
	// exists
	public static boolean exists(com.altova.mapforce.IEnumerable x) throws Exception  
	{
		IEnumerator en = x.enumerator(); 
		boolean b = en.moveNext();
		en.close();
		return b;
	}
	
	// nodeName
	public static javax.xml.namespace.QName nodeName(com.altova.mapforce.IMFNode n)
	{
		return new javax.xml.namespace.QName(n.getNamespaceURI(), n.getLocalName(), n.getPrefix() == null ? "" : n.getPrefix());
	}
	
	// logical functions
	public static boolean logicalNot(boolean b) { return !b; }
	public static boolean logicalOr(boolean l, boolean r) { return l || r; }
	public static boolean logicalAnd(boolean l, boolean r) { return l && r; }	

	// comparison functions
	public static boolean equal(boolean a, boolean b) { return a == b; }
	public static boolean equal(int a, int b) { return a == b; }
	public static boolean equal(long a, long b) { return a == b; }
	public static boolean equal(double a, double b) { return a == b; }
	public static boolean equal(String a, String b) { return a.equals(b); }
	public static boolean equal(DateTime a, DateTime b) { return a.compareTo(b) == 0; }
	public static boolean equal(Duration a, Duration b) { return a.compareTo(b) == 0; }
	public static boolean equal(BigInteger a, BigInteger b) { return a.compareTo(b) == 0; }
	public static boolean equal(BigDecimal a, BigDecimal b) { return a.compareTo(b) == 0; }
	public static boolean equal(javax.xml.namespace.QName a, javax.xml.namespace.QName b) { return a.equals(b); }

	public static boolean greater(boolean a, boolean b) { return a && !b; }
	public static boolean greater(int a, int b) { return a > b; }
	public static boolean greater(long a, long b) { return a > b; }
	public static boolean greater(double a, double b) { return a > b; }
	public static boolean greater(String a, String b) { return a.compareTo(b) > 0; }
	public static boolean greater(DateTime a, DateTime b) { return a.compareTo(b) > 0; }
	public static boolean greater(Duration a, Duration b) { return a.compareTo(b) > 0; }
	public static boolean greater(BigInteger a, BigInteger b) { return a.compareTo(b) > 0; }
	public static boolean greater(BigDecimal a, BigDecimal b) { return a.compareTo(b) > 0; }

	public static boolean less(boolean a, boolean b) { return !a && b; }
	public static boolean less(int a, int b) { return a < b; }
	public static boolean less(long a, long b) { return a < b; }
	public static boolean less(double a, double b) { return a < b; }
	public static boolean less(String a, String b) { return a.compareTo(b) < 0; }
	public static boolean less(DateTime a, DateTime b) { return a.compareTo(b) < 0; }
	public static boolean less(Duration a, Duration b) { return a.compareTo(b) < 0; }
	public static boolean less(BigInteger a, BigInteger b) { return a.compareTo(b) < 0; }
	public static boolean less(BigDecimal a, BigDecimal b) { return a.compareTo(b) < 0; }

	public static boolean equalOrGreater(boolean a, boolean b) { return a == b || (a && !b); }
	public static boolean equalOrGreater(int a, int b) { return a >= b; }
	public static boolean equalOrGreater(long a, long b) { return a >= b; }
	public static boolean equalOrGreater(double a, double b) { return a >= b; }
	public static boolean equalOrGreater(String a, String b) { return a.compareTo(b) >= 0; }
	public static boolean equalOrGreater(DateTime a, DateTime b) { return a.compareTo(b) >= 0; }
	public static boolean equalOrGreater(Duration a, Duration b) { return a.compareTo(b) >= 0; }
	public static boolean equalOrGreater(BigInteger a, BigInteger b) { return a.compareTo(b) >= 0; }
	public static boolean equalOrGreater(BigDecimal a, BigDecimal b) { return a.compareTo(b) >= 0; }

	public static boolean equalOrLess(boolean a, boolean b) { return a == b || (!a && b); }
	public static boolean equalOrLess(int a, int b) { return a <= b; }
	public static boolean equalOrLess(long a, long b) { return a <= b; }
	public static boolean equalOrLess(double a, double b) { return a <= b; }
	public static boolean equalOrLess(String a, String b) { return a.compareTo(b) <= 0; }
	public static boolean equalOrLess(DateTime a, DateTime b) { return a.compareTo(b) <= 0; }
	public static boolean equalOrLess(Duration a, Duration b) { return a.compareTo(b) <= 0; }
	public static boolean equalOrLess(BigInteger a, BigInteger b) { return a.compareTo(b) <= 0; }
	public static boolean equalOrLess(BigDecimal a, BigDecimal b) { return a.compareTo(b) <= 0; }

	public static boolean notEqual(boolean a, boolean b) { return a != b; }
	public static boolean notEqual(int a, int b) { return a != b; }
	public static boolean notEqual(long a, long b) { return a != b; }
	public static boolean notEqual(double a, double b) { return a != b; }
	public static boolean notEqual(String a, String b) { return !a.equals(b); }
	public static boolean notEqual(DateTime a, DateTime b) { return a.compareTo(b) != 0; }
	public static boolean notEqual(Duration a, Duration b) { return a.compareTo(b) != 0; }
	public static boolean notEqual(BigInteger a, BigInteger b) { return a.compareTo(b) != 0; }
	public static boolean notEqual(BigDecimal a, BigDecimal b) { return a.compareTo(b) != 0; }
	public static boolean notEqual(javax.xml.namespace.QName a, javax.xml.namespace.QName b) { return !a.equals(b); }

	// Mathematical functions
	public static int modulus(int a, int b) { return a % b; }
	public static long modulus(long a, long b) { return a % b; }
	public static double modulus(double a, double b) { return a % b; }
	public static BigInteger modulus(BigInteger a, BigInteger b) { return a.subtract(a.divide(b).multiply(b)); }
	public static BigDecimal modulus(BigDecimal a, BigDecimal b) { return a.remainder(b); }

	public static int multiply(int a, int b) { return a * b; }
	public static long multiply(long a, long b) { return a * b; }
	public static double multiply(double a, double b) { return a * b; }
	public static BigInteger multiply(BigInteger a, BigInteger b) { return a.multiply(b); }
	public static BigDecimal multiply(BigDecimal a, BigDecimal b) { return a.multiply(b); }

	public static int subtract(int a, int b) { return a - b; }
	public static long subtract(long a, long b) { return a - b; }
	public static double subtract(double a, double b) { return a - b; }
	public static BigInteger subtract(BigInteger a, BigInteger b) { return a.subtract(b); }
	public static BigDecimal subtract(BigDecimal a, BigDecimal b) { return a.subtract(b); }

	public static int add(int a, int b) { return a + b; }
	public static long add(long a, long b) { return a + b; }
	public static double add(double a, double b) { return a + b; }
	public static BigInteger add(BigInteger a, BigInteger b) { return a.add(b); }
	public static BigDecimal add(BigDecimal a, BigDecimal b) { return a.add(b); }

	public static int divide(int a, int b) { return a / b; }
	public static long divide(long a, long b) { return a / b; }
	public static double divide(double a, double b) { return a / b; }
	public static BigInteger divide(BigInteger a, BigInteger b) { return a.divide(b); }
	public static BigDecimal divide(BigDecimal a, BigDecimal b) { return a.divide(b, 60 + a.scale() + b.scale(), BigDecimal.ROUND_HALF_UP); }

	public static int ceiling(int x) { return x; }
	public static long ceiling(long x) { return x; }
	public static int floor(int x) { return x; }
	public static long floor(long x) { return x; }
	public static int round(int x) { return x; }
	public static long round(long x) { return x; }

	public static double ceiling(double d) { return Math.ceil(d); }
	public static double floor(double d) { return Math.floor(d); }
	public static double round(double d) { return round(new BigDecimal(d)).doubleValue(); }

	public static BigInteger ceiling(BigInteger n) { return n; }
	public static BigDecimal ceiling(BigDecimal n) { return n.setScale(0, BigDecimal.ROUND_CEILING); }
	public static BigInteger floor(BigInteger n) { return n; }
	public static BigDecimal floor(BigDecimal n) { return n.setScale(0, BigDecimal.ROUND_FLOOR); }
	public static BigInteger round(BigInteger n) { return n; }
	public static BigDecimal round(BigDecimal n) { return n.setScale(0, n.signum() == -1 ? BigDecimal.ROUND_HALF_DOWN : BigDecimal.ROUND_HALF_UP); }

	// string functions
	public static String concat(String a, String b) { return a + b; }
	
	public static String normalizeSpace(String a) {
		StringBuffer result = new StringBuffer();
		boolean needSpace = false;
		for (int i = 0; i < a.length(); i++) {
			char c = a.charAt(i);
			if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
				needSpace = true;
			else
			{
				if (needSpace && result.length() != 0)
					result.append(' ');
				result.append(c);
				needSpace = false;
			}
		}
		return result.toString();
	}

	public static boolean startsWith(String str, String substr) {
		return str.startsWith(substr);
	}

	public static int stringLength(String str) {
		return str.length();
	}

	public static String substring(String str, int start, int length) {
		int from = start;
		int to = start + length;
		if (from < 1) from = 1;
		if (to > str.length() + 1) to = str.length() + 1;
		if (to <= from) return "";
		int rfrom = from - 1;
		int rto = to - 1;
		return str.substring(rfrom, rto);
	}

	public static String substring(String str, double start, double length) {
		double from = start;
		double to = start + length;
		if (from < 1) from = 1;
		if (to > str.length() + 1) to = str.length() + 1;
		if (to <= from) return "";
		int rfrom = (int)Math.round(from) - 1;
		int rto = (int)Math.round(to) - 1;
		if (rto > str.length()) rto = str.length();
		if (rto <= rfrom) return "";
		return str.substring(rfrom, rto);
	}

	public static String substring(String str, int start) 
	{
		return substring(str, start, null);
	}

	public static String substring(String str, double start) 
	{
		return substring(str, start, null);
	}

	public static String substring(String str, int start, Object lengthNull) {
		return substring(str, start, str.length() - start + 1);
	}

	public static String substring(String str, double start, Object lengthNull)	{
		int istart = (int) start;
		return substring(str, istart, lengthNull);
	}

	public static String substringAfter(String str, String substr) {
		int position = str.indexOf(substr);
		if (position >= 0)
			return (str.substring(position + substr.length()));
		else
			return "";
	}

	public static String substringBefore(String str, String substr) {
		int position = str.indexOf(substr);
		if (position >= 0)
			return str.substring(0, position);
		else
			return "";
	}

	public static String translate(String a, String b, String c) {
		String result = "";
		for (int i = 0 ; i < a.length(); i++) {
			char ai = a.charAt(i);
			int off = b.indexOf(ai);
			if (off != -1 && off < c.length())
				result += c.charAt(off);
			else if (off == -1)
				result += ai;
		}
		return result;
	}

	public static boolean contains(String str, String substr) {
		return str.indexOf(substr) >= 0;
	}		

	// conversion functions
	public static boolean toBoolean(boolean b) { return CoreTypes.castToBool(b); }
	public static boolean toBoolean(int b) { return CoreTypes.castToBool(b); }
	public static boolean toBoolean(long b) { return CoreTypes.castToBool(b); }
	public static boolean toBoolean(double b) { return CoreTypes.castToBool(b); }
	public static boolean toBoolean(BigInteger b) { return CoreTypes.castToBool(b); }
	public static boolean toBoolean(BigDecimal b) { return CoreTypes.castToBool(b); }
	public static boolean toBoolean(String b) { if (b == null || b.length() == 0) return false; return true; }

	public static BigDecimal toNumber(boolean b) { return CoreTypes.castToBigDecimal(b); }
	public static BigDecimal toNumber(int b) { return CoreTypes.castToBigDecimal(b); }
	public static BigDecimal toNumber(long b) { return CoreTypes.castToBigDecimal(b); }
	public static BigDecimal toNumber(double b) { return CoreTypes.castToBigDecimal(b); }
	public static BigDecimal toNumber(BigInteger b) { return CoreTypes.castToBigDecimal(b); }
	public static BigDecimal toNumber(BigDecimal b) { return CoreTypes.castToBigDecimal(b); }
	public static BigDecimal toNumber(String b) { return CoreTypes.castToBigDecimal(b); }

	public static String toString(Object o) throws Exception
	{
		if (o instanceof Boolean)
			return CoreTypes.castToString((Boolean) o);
		if (o instanceof Integer)
			return CoreTypes.castToString((Integer) o);
		if (o instanceof Long)
			return CoreTypes.castToString((Long) o);
		if (o instanceof Double)
			return CoreTypes.castToString((Double) o);
		if (o instanceof BigInteger)
			return CoreTypes.castToString((BigInteger) o);
		if (o instanceof BigDecimal)
			return CoreTypes.castToString((BigDecimal) o);
		if (o instanceof String)
			return CoreTypes.castToString((String) o);
		if (o instanceof DateTime)
			return CoreTypes.castToString((DateTime) o);
		if (o instanceof Duration)
			return CoreTypes.castToString((Duration) o);
		if (o instanceof javax.xml.namespace.QName)
			return CoreTypes.castToString((javax.xml.namespace.QName) o);
		if (o instanceof com.altova.mapforce.IMFNode)
			return CoreTypes.castToString((com.altova.mapforce.IMFNode) o);
			
		return null;
	}
	
	
	public static IEnumerable documentURI(IEnumerable ns) throws Exception
	{
		if (exists(ns))
		{
			Object n = first(ns);
			if (n instanceof com.altova.mapforce.IMFDocumentNode)
				return box(((com.altova.mapforce.IMFDocumentNode) n).getDocumentUri());
		}
		
		return new MFEmptySequence();
	}
	
	public static IEnumerable tokenizeRegexp(String input, String pattern) 
	{
		return tokenizeRegexp(input, pattern, "");
	}
	
	static class ArrayEnumerable implements IEnumerable 
	{
		String[] a;
		public ArrayEnumerable(String[] a) { this.a = a; }
		public IEnumerator enumerator() { return new Enumerator(a); }

		class Enumerator implements IEnumerator {
			String[] a;
			int index;
			public Enumerator(String[] a) { this.a = a; this.index = -1; }
			public boolean moveNext() { ++index; return index < a.length; }
			public int position() { return index + 1; }
			public Object current() { return a[index]; }
			public void close() { }
		}
	}
	
	public static IEnumerable tokenizeRegexp(String input, String pattern, String flags) 
	{
		int flag = 0;
		String regex = pattern;
		for (char c : flags.toCharArray())
		{
			switch(c)
			{
			case 's':
				flag |= Pattern.DOTALL;
				break;
			case 'm':
				flag |= Pattern.MULTILINE;
				break;
			case 'i':
				flag |= Pattern.CASE_INSENSITIVE;
				break;
			case 'x':
				regex = regex.replace(" ", "");
				regex = regex.replace("\t", "");
				regex = regex.replace("\n", "");
				regex = regex.replace("\r", "");
				break;
			default:
				throw new IllegalArgumentException( "regular expression flag \'" + c + "\' is illegal." );
			}
		}
		Pattern re = Pattern.compile(regex, flag);		
		return new ArrayEnumerable(re.split(input, -1));
	}
	
	public static IEnumerable tokenize(String input, String delimiter)
	{
		ArrayList tokens = new ArrayList();
		int i=0;
		int j=0;
		int dl = delimiter.length();
		//int il = input.length();
		while(true)
		{
			i = input.indexOf(delimiter, j);
			if (i == -1) 
			{
				tokens.add(input.substring(j));
				break;
			}
			tokens.add(input.substring(j, i));
			j = i + dl;
		}
		
		return new com.altova.mapforce.MFElement.ArrayListAsEnumerable(tokens);
	}
	
	public static IEnumerable tokenizeByLength(String input, double length)
	{
		ArrayList tokens = new ArrayList();
		
		int l = input.length();
		int step = (int) length;

		if (length < 1)
			throw new IllegalArgumentException("Length for tokenizing is " + length + " which is invalid since it must be greater or equal than 1.");
		
		for (int i=0; i 0xFFFF)
			throw new IllegalArgumentException( "char-from-code(" + val.intValue() + ") undefined." );
		return Character.toString(c);
	}

	public static java.math.BigInteger codeFromChar(String val)
	{
		if (val.length() == 0)
			return java.math.BigInteger.valueOf(0);
		return java.math.BigInteger.valueOf((long) val.charAt(0));
	}

	public static String FormatNumber(BigDecimal bd, String sPattern)
	{
		DecimalFormatParser dfp = new DecimalFormatParser();
		DecimalFormatParser.DecimalFormat format = dfp.new DecimalFormat();
		if(!dfp.setPattern( sPattern, format))
			throw new IllegalArgumentException( "Incorrect pattern: '" + sPattern + "'");
		
		return dfp.formatNumber( bd);
	}
	
	public static String FormatDateTime(DateTime dt, String sPattern)
	{
		DateTimeFormatParser dtfp = new DateTimeFormatParser( sPattern);

		return dtfp.formatDateTime( dt);
	}

	public static String FormatDateTime(DateTime dt, String sPattern, String sLanguage)
	{
		return FormatDateTime(dt, sPattern);
	}

	public static DateTime ParseDateTime(String sInput, String sPattern)
	{
		if( sPattern.length() == 0 )
			throw new IllegalArgumentException( "Empty pattern.");

		DateTimeFormatParser dtfp = new DateTimeFormatParser( sPattern);

		return dtfp.parseDateTime( sInput);
	}

	public static BigDecimal ParseNumber(String sNumber, String sPattern)
	{
		DecimalFormatParser dfp = new DecimalFormatParser();
		DecimalFormatParser.DecimalFormat format = dfp.new DecimalFormat();
		if(!dfp.setPattern(sPattern, format, true))
			throw new IllegalArgumentException( "Incorrect pattern: '" + sPattern + "'");
		
		return dfp.parseNumber( sNumber);
	}

	public static long autoNumber(RuntimeContext context, String id, long start, long step, String restartOnChange)
	{
		long r = 0;
		
		if (!context.getAutoNumberStateMap().containsKey(id) || !context.getAutoNumberStateMap().get(id).restartOnChange.equals(restartOnChange))
			r = start;
		else
			r = context.getAutoNumberStateMap().get(id).current + step;
			
		context.getAutoNumberStateMap().put(id, new RuntimeContext.AutoNumberStateEntry(r, restartOnChange));
		return r;
	}

	public static void resetAutoNumber(RuntimeContext context, String id)
	{
		context.getAutoNumberStateMap().remove(id);
	}

	public static IEnumerable throwUserException(String content)
	{
		throw new com.altova.UserException(content);
	}

	public static com.altova.mapforce.IMFNode createElement(javax.xml.namespace.QName qname, com.altova.mapforce.IEnumerable content)
	{
		return new com.altova.mapforce.MFElement(qname, content);
	}

	public static com.altova.mapforce.IMFNode createElement(java.lang.String name, com.altova.mapforce.IEnumerable content)
	{
		return new com.altova.mapforce.MFElement(name, content);
	}
	
	public static com.altova.mapforce.IMFNode createAttribute(javax.xml.namespace.QName qname, com.altova.mapforce.IEnumerable content)
	{
		return new com.altova.mapforce.MFAttribute(qname, content);
	}

	public static com.altova.mapforce.IMFNode createAttribute(java.lang.String name, com.altova.mapforce.IEnumerable content)
	{
		return new com.altova.mapforce.MFAttribute(name, content);
	}
	
	public static javax.xml.namespace.QName createQName(String localname, String uri)
	{
		int sep = localname.indexOf(':');
		if (sep >= 0)
			return new javax.xml.namespace.QName(uri, localname.substring(sep + 1), localname.substring(0, sep));
		else
			return new javax.xml.namespace.QName(uri, localname, "");
	}

	public static String localNameFromQName(javax.xml.namespace.QName qn) {return qn.getLocalPart();}
	public static String namespaceUriFromQName(javax.xml.namespace.QName qn) {return qn.getNamespaceURI();}
		
	public static IEnumerable selectChildren(com.altova.mapforce.IMFNode node)
	{
		return node.select(com.altova.mapforce.IMFNode.MFQueryKind_AllChildren, null);
	}

	public static IEnumerable selectAttributes(com.altova.mapforce.IMFNode node)
	{
		return node.select(com.altova.mapforce.IMFNode.MFQueryKind_AllAttributes, null);
	}

	public static IEnumerable filterElements(javax.xml.namespace.QName qname, com.altova.mapforce.IMFNode node)
	{
		return node.select(com.altova.mapforce.IMFNode.MFQueryKind_ChildrenByQName, qname);
	}

	public static IEnumerable filterElements(java.lang.String name, com.altova.mapforce.IMFNode node)
	{
		return node.select(com.altova.mapforce.IMFNode.MFQueryKind_ChildrenByNodeName, name);
	}

	public static IEnumerable filterAttributes(javax.xml.namespace.QName qname, com.altova.mapforce.IMFNode node)
	{
		return node.select(com.altova.mapforce.IMFNode.MFQueryKind_AttributeByQName, qname);
	}

	public static IEnumerable filterAttributes(java.lang.String name, com.altova.mapforce.IMFNode node)
	{
		return node.select(com.altova.mapforce.IMFNode.MFQueryKind_AttributeByNodeName, name);
	}

	public static boolean nodeNameEqual(javax.xml.namespace.QName qname, com.altova.mapforce.IMFNode node)
	{
		return qname.getLocalPart().equals( node.getLocalName() ) && qname.getNamespaceURI().equals( node.getNamespaceURI() );
	}

	public static boolean nodeNameEqual(java.lang.String nodename, com.altova.mapforce.IMFNode node)
	{
		return nodename.equals(node.getNodeName());
	}

	public static boolean attributeNameEqual(javax.xml.namespace.QName qname, com.altova.mapforce.IMFNode node)
	{
		return nodeNameEqual( qname, node );
	}

	public static com.altova.mapforce.IMFNode createNamespace(String prefix, String content)
	{
		if (prefix.length() == 0)
			return new com.altova.mapforce.MFAttribute("xmlns", "http://www.w3.org/2000/xmlns/", "", box(content));
		else
			return new com.altova.mapforce.MFAttribute(prefix, "http://www.w3.org/2000/xmlns/", "xmlns", box(content));
	}
	
	public static java.lang.String getPlatformPathDelimiter()
	{
		return java.io.File.separator;
	}
	
	public static com.altova.mapforce.IMFNode createComment(String content)
	{
		String str = content.replace("--", "- -");
		
		if (str.endsWith("-"))
			str += " ";
		
		return new com.altova.mapforce.MFComment(str);
	}
	
	public static com.altova.mapforce.IMFNode createProcessingInstruction(String content, String name)
	{
		if (!content.contains("?>"))
			return new com.altova.mapforce.MFProcessingInstruction(content, name);
		
		return new com.altova.mapforce.MFProcessingInstruction(content.replace("?>", "? >"), name);
	}

	public static com.altova.mapforce.IMFNode createCData(String content)
	{
		return new com.altova.mapforce.MFCData(content);
	}

	public static IEnumerable generateSequence(BigInteger from, BigInteger to)
	{
		class GenerateSequence implements IEnumerable
		{
			private BigInteger from;
			private BigInteger to;
			
			class Enumerator implements IEnumerator
			{
				private int pos = 0;
				private BigInteger current;
				private BigInteger to;
				
				public Enumerator(BigInteger from, BigInteger to)
				{
					this.current = from;
					this.to = to;
				}
				
				public Object current()
				{
					return current;
				}

				public boolean moveNext() throws Exception 
				{
					if ( pos >= 1 )
					{
						if ( current.equals( to ) )
							return false;
						current = current.add( BigInteger.ONE );
					}
					pos++;
					return true;
				}

				public int position() 
				{
					return pos;
				}
				
				public void close() {}
			}
			
			public GenerateSequence(BigInteger from, BigInteger to)
			{
				this.from = from;
				this.to = to;
			}

			public IEnumerator enumerator() throws Exception {return new Enumerator(from, to);}
		}

		if ( from.compareTo( to ) > 0 )
			return new MFEmptySequence();

		return new GenerateSequence(from, to);
	}

	public static IEnumerable replicateSequence( IEnumerable sequence, BigInteger count )
	{
		class ReplicateSequence implements IEnumerable
		{
			private IEnumerable sequence;
			private BigInteger count;

			class Enumerator implements IEnumerator
			{
				private int pos = 0;
				private IEnumerable sequence;
				private IEnumerator enumerator;
				private BigInteger count;
				
				public Enumerator( IEnumerable sequence, BigInteger count ) throws Exception 
				{
					this.sequence = sequence;
					this.enumerator = sequence.enumerator();
					this.count = count;
				}
				
				public Object current()
				{
					return enumerator.current();
				}

				public boolean moveNext() throws Exception 
				{
					while ( true )
					{
						if ( enumerator.moveNext() )
						{
							pos++;
							return true;
						}

						// if ( --count == 0 )
						count = count.subtract( BigInteger.ONE );
						if ( count.compareTo( BigInteger.ZERO ) == 0 )
						{
							sequence = null;
							enumerator = null;
							return false;
						}

						enumerator = sequence.enumerator();
					}
				}

				public int position() 
				{
					return pos;
				}
				
				public void close()
				{
					sequence = null;
					enumerator = null;
				}
			}

			public ReplicateSequence( IEnumerable sequence, BigInteger count )
			{
				this.sequence = sequence;
				this.count = count;
			}

			public IEnumerator enumerator() throws Exception { return new Enumerator( sequence, count ); }
		}

		int comp = count.compareTo( BigInteger.ZERO );
		if ( comp < 0 )
			throw new IllegalArgumentException("Replication count is " + count + " which is invalid since it must not be negative.");

		if ( comp == 0 )
			return new MFEmptySequence();

		comp = count.compareTo( BigInteger.ONE );
		if ( comp == 0 )
			return sequence;

		return new ReplicateSequence( sequence, count );
	}

	private static class FilterSequenceByPositionRange implements IEnumerable
	{
		private IEnumerable sequence;
		private BigInteger from, till;		// 1-based, both inclusive

		class Enumerator implements IEnumerator
		{
			private int pos = 0;
			private IEnumerator enumerator;
			private BigInteger skip, take;

			public Enumerator( IEnumerator enumerator, BigInteger skip, BigInteger take ) throws Exception 
			{
				this.enumerator = enumerator;
				this.skip = skip;
				this.take = take;
			}
			
			public Object current()
			{
				return enumerator.current();
			}

			public boolean moveNext() throws Exception 
			{
				while ( skip.compareTo( BigInteger.ZERO ) > 0 )
				{
					skip = skip.subtract( BigInteger.ONE );
					if ( !enumerator.moveNext() )
						return false;
				}

				if ( take.compareTo( BigInteger.ZERO ) == 0 )
					return false;

				take = take.subtract( BigInteger.ONE );
				if ( !enumerator.moveNext() )
					return false;

				pos++;
				return true;
			}

			public int position() 
			{
				return pos;
			}
			
			public void close()
			{
				enumerator = null;
			}
		}

		public FilterSequenceByPositionRange( IEnumerable sequence, BigInteger from, BigInteger till )
		{
			this.sequence = sequence;
			this.from = from;
			this.till = till;
		}

		public IEnumerator enumerator() throws Exception
		{
			if ( till.compareTo( from ) < 0 )
				return (new MFEmptySequence()).enumerator();

			BigInteger skip = from.compareTo( BigInteger.ZERO ) > 0 ? from.subtract( BigInteger.ONE ) : BigInteger.ZERO;
			BigInteger take = till.subtract( skip );

			return new Enumerator( sequence.enumerator(), skip, take );
		}
	}

	public static IEnumerable itemAt( IEnumerable sequence, BigInteger position )
	{
		return new FilterSequenceByPositionRange( sequence, position, position );
	}

	public static IEnumerable itemsFromTill( IEnumerable sequence, BigInteger from, BigInteger till )
	{
		return new FilterSequenceByPositionRange( sequence, from, till );
	}

	public static IEnumerable firstItems( IEnumerable sequence, BigInteger count )
	{
		return new FilterSequenceByPositionRange( sequence, BigInteger.ONE, count );
	}

	public static IEnumerable skipFirstItems( IEnumerable sequence, BigInteger count )
	{
		return new FilterSequenceByPositionRange( sequence, count.add( BigInteger.ONE ), BigInteger.valueOf( Integer.MAX_VALUE ) );
	}

	public static IEnumerable lastItems( IEnumerable sequence, BigInteger count ) throws Exception
	{
		BigInteger len = BigInteger.valueOf( Core.count( sequence ) );
		BigInteger start = count.compareTo( len ) > 0 ? BigInteger.ONE : len.subtract( count ).add( BigInteger.ONE );
		return new FilterSequenceByPositionRange( sequence, start, len );
	}
}