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

io.continual.templating.ContinualTemplateSource Maven / Gradle / Ivy

package io.continual.templating;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;

import org.slf4j.LoggerFactory;

import com.github.f4b6a3.ulid.Ulid;

import io.continual.resources.ResourceLoader;

public interface ContinualTemplateSource extends AutoCloseable
{
	public static class TemplateNotFoundException extends Exception
	{
		public TemplateNotFoundException ( String msg ) { super ( msg ); }
		public TemplateNotFoundException ( Throwable t ) { super ( t ); }
		private static final long serialVersionUID = 1L;
	};

	/**
	 * Get a name for this template (used mainly for logging)
	 * @return a name
	 */
	String getName ();

	/**
	 * Get the (default) template as an input stream
	 * @return an input stream
	 * @throws TemplateNotFoundException
	 */
	InputStream getTemplate () throws TemplateNotFoundException;

	/**
	 * Close this template source
	 */
	default void close () throws Exception {}

	/**
	 * Build a template source from a UTF-8 string
	 * @param stringVal
	 * @return a template source
	 */
	public static ContinualTemplateSource fromString ( final String stringVal )
	{
		return new ContinualTemplateSource ()
		{
			@Override
			public InputStream getTemplate () throws TemplateNotFoundException
			{
				return new ByteArrayInputStream ( stringVal.getBytes ( StandardCharsets.UTF_8 ) );
			}

			@Override
			public String getName ()
			{
				return stringVal;
			}
		};
	}

	/**
	 * Build a template source from a resource name
	 * @param resName
	 * @return a template source
	 */
	public static ContinualTemplateSource fromResource ( final String resName, final String relativeName )
	{
		return new ContinualTemplateSource ()
		{
			InputStream is = null;

			@Override
			public String getName ()
			{
				return relativeName;
			}

			@Override
			public InputStream getTemplate () throws TemplateNotFoundException
			{
				try
				{
					is = ResourceLoader.load ( resName );
					if ( is == null )
					{
						LoggerFactory.getLogger ( ContinualTemplateSource.class ).warn ( "Couldn't load resource {}" , resName );
						throw new TemplateNotFoundException ( "Couldn't load resource " + resName );
					}
					return is;
				}
				catch ( IOException e )
				{
					throw new TemplateNotFoundException ( e );
				}
			}

			@Override
			public void close () throws IOException
			{
				if ( is != null )
				{
					is.close ();
				}
			}
		};
	}

	/**
	 * Build a template source from a file
	 * @param file
	 * @return a template source
	 */
	public static ContinualTemplateSource fromFile ( final File file )
	{
		return new ContinualTemplateSource ()
		{
			FileInputStream fFile = null;

			@Override
			public String getName ()
			{
				return file.getName ();
			}

			@Override
			public InputStream getTemplate () throws TemplateNotFoundException
			{
				if ( fFile != null ) throw new IllegalStateException ( "Template was already retrieved." );
				try
				{
					fFile = new FileInputStream ( file );
					return fFile;
				}
				catch ( FileNotFoundException e )
				{
					throw new TemplateNotFoundException ( e );
				}
			}

			@Override
			public void close () throws IOException
			{
				if ( fFile != null )
				{
					fFile.close ();
				}
			}
		};
	}

	/**
	 * Build a template source from an input stream
	 * @param is
	 * @return a template source
	 */
	public static ContinualTemplateSource fromInputStream ( final InputStream is )
	{
		// we return a manufactured unique name so that the input stream isn't inadvertently cached by name 
		return fromInputStream ( is, "input stream " + Ulid.fast ().toLowerCase () );
	}

	/**
	 * Build a template source from an input stream
	 * @param is
	 * @return a template source
	 */
	public static ContinualTemplateSource fromInputStream ( final InputStream is, String uniqueName )
	{
		return new ContinualTemplateSource ()
		{
			@Override
			public String getName () { return uniqueName; }

			@Override
			public InputStream getTemplate () { return is; }

			@Override
			public void close () throws IOException { is.close (); }
		};
	}

	/**
	 * Build a template source from a sequences of sources
	 * @param streams
	 * @return a template source
	 */
	public static ContinualTemplateSource combinedStreams ( ContinualTemplateSource... streams )
	{
		return new ContinualTemplateSource ()
		{
			@Override
			public String getName ()
			{
				final StringBuilder sb = new StringBuilder ();
				for ( ContinualTemplateSource src : streams )
				{
					if ( sb.length () > 0 )
					{
						sb.append ( " + " );
					}
					sb.append ( src.getName () );
				}
				return sb.toString ();
			}

			@Override
			public InputStream getTemplate () throws TemplateNotFoundException
			{
				final LinkedList srcs = new LinkedList<> ();
				for ( ContinualTemplateSource src : streams )
				{
					srcs.add ( src.getTemplate () );
				}

				return new InputStream ()
				{
					@Override
					public int read () throws IOException
					{
						while ( !srcs.isEmpty () )
						{
							// get the lead stream
							final InputStream currentStream = srcs.peek ();

							final int data = currentStream.read ();
							if ( data == -1 )
							{
								// end of this stream. remove it.
								srcs.remove ();
							}
							else
							{
								return data;
							}
						}

						// eof
						return -1;
					}
				};
			}

			@Override
			public void close () throws Exception
			{
				for ( ContinualTemplateSource src : streams )
				{
					src.close ();
				}
			}
		};
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy