// Path: src/main/java/com/ryantenney/passkit4j/io/NamedInputStreamSupplier.java
// public interface NamedInputStreamSupplier extends InputStreamSupplier {
// 
// 	public String getName();
// 
// }
// 
// Path: src/main/java/com/ryantenney/passkit4j/model/PassInformation.java
// @Data
// public abstract class PassInformation {
// 
// 	@JsonIgnore private final String typeName;
// 
// 	private List<Field<?>> headerFields;
// 	private List<Field<?>> primaryFields;
// 	private List<Field<?>> secondaryFields;
// 	private List<Field<?>> backFields;
// 	private List<Field<?>> auxiliaryFields;
// 
// 	protected PassInformation(final String typeName) {
// 		this.typeName = typeName;
// 	}
// 
// 	public String typeName() {
// 		return this.typeName;
// 	}
// 
// 	public PassInformation headerFields(Field<?>... fields) {
// 		this.headerFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation headerFields(List<Field<?>> fields) {
// 		this.headerFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation primaryFields(Field<?>... fields) {
// 		this.primaryFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation primaryFields(List<Field<?>> fields) {
// 		this.primaryFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation secondaryFields(Field<?>... fields) {
// 		this.secondaryFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation secondaryFields(List<Field<?>> fields) {
// 		this.secondaryFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation backFields(Field<?>... fields) {
// 		this.backFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation backFields(List<Field<?>> fields) {
// 		this.backFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation auxiliaryFields(Field<?>... fields) {
// 		this.auxiliaryFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation auxiliaryFields(List<Field<?>> fields) {
// 		this.auxiliaryFields = fields;
// 		return this;
// 	}
// 
// }
// 
// Path: src/main/java/com/ryantenney/passkit4j/sign/PassSigner.java
// public interface PassSigner {
// 
// 	public byte[] generateSignature(byte[] data) throws PassSigningException;
// 
// }
// 
// Path: src/main/java/com/ryantenney/passkit4j/sign/PassSigningException.java
// public class PassSigningException extends Exception {
// 
// 	private static final long serialVersionUID = 6021707149897120829L;
// 
// 	public PassSigningException(String message) {
// 		super(message);
// 	}
// 
// 	public PassSigningException(Throwable cause) {
// 		super(cause);
// 	}
// 
// 	public PassSigningException(String message, Throwable cause) {
// 		super(message, cause);
// 	}
// 
// }


import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.DigestException;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import lombok.Delegate;
import lombok.Getter;
import lombok.experimental.Accessors;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.ryantenney.passkit4j.io.NamedInputStreamSupplier;
import com.ryantenney.passkit4j.model.PassInformation;
import com.ryantenney.passkit4j.sign.PassSigner;
import com.ryantenney.passkit4j.sign.PassSigningException;
			throw new PassSerializationException(e);
		} finally {
			try {
				if (zip != null) zip.close();
			} catch (IOException e) {
				throw new PassSerializationException("Error closing output stream", e);
			}
		}
	}

	protected static ObjectNode generatePass(Pass pass) {
		ObjectNode tree = objectMapper.valueToTree(pass);

		PassInformation info = pass.passInformation();
		tree.put(info.typeName(), objectMapper.valueToTree(info));

		return tree;
	}

	protected static ObjectNode generateManifest(Map<String, String> files) {
		ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
		for (Map.Entry<String, String> file : files.entrySet()) {
			node.put(file.getKey(), file.getValue());
		}
		return node;
	}

	protected static Map<String, String> writeAndHashFiles(List<NamedInputStreamSupplier> files, ZipOutputStream output) throws IOException, NoSuchAlgorithmException, DigestException, NoSuchProviderException {
		Map<String, String> hashes = new HashMap<String, String>();
		for (NamedInputStreamSupplier file : files) {
// Path: src/main/java/com/ryantenney/passkit4j/io/NamedInputStreamSupplier.java
// public interface NamedInputStreamSupplier extends InputStreamSupplier {
// 
// 	public String getName();
// 
// }
// 
// Path: src/main/java/com/ryantenney/passkit4j/model/PassInformation.java
// @Data
// public abstract class PassInformation {
// 
// 	@JsonIgnore private final String typeName;
// 
// 	private List<Field<?>> headerFields;
// 	private List<Field<?>> primaryFields;
// 	private List<Field<?>> secondaryFields;
// 	private List<Field<?>> backFields;
// 	private List<Field<?>> auxiliaryFields;
// 
// 	protected PassInformation(final String typeName) {
// 		this.typeName = typeName;
// 	}
// 
// 	public String typeName() {
// 		return this.typeName;
// 	}
// 
// 	public PassInformation headerFields(Field<?>... fields) {
// 		this.headerFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation headerFields(List<Field<?>> fields) {
// 		this.headerFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation primaryFields(Field<?>... fields) {
// 		this.primaryFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation primaryFields(List<Field<?>> fields) {
// 		this.primaryFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation secondaryFields(Field<?>... fields) {
// 		this.secondaryFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation secondaryFields(List<Field<?>> fields) {
// 		this.secondaryFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation backFields(Field<?>... fields) {
// 		this.backFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation backFields(List<Field<?>> fields) {
// 		this.backFields = fields;
// 		return this;
// 	}
// 
// 	public PassInformation auxiliaryFields(Field<?>... fields) {
// 		this.auxiliaryFields = Arrays.asList(fields);
// 		return this;
// 	}
// 
// 	public PassInformation auxiliaryFields(List<Field<?>> fields) {
// 		this.auxiliaryFields = fields;
// 		return this;
// 	}
// 
// }
// 
// Path: src/main/java/com/ryantenney/passkit4j/sign/PassSigner.java
// public interface PassSigner {
// 
// 	public byte[] generateSignature(byte[] data) throws PassSigningException;
// 
// }
// 
// Path: src/main/java/com/ryantenney/passkit4j/sign/PassSigningException.java
// public class PassSigningException extends Exception {
// 
// 	private static final long serialVersionUID = 6021707149897120829L;
// 
// 	public PassSigningException(String message) {
// 		super(message);
// 	}
// 
// 	public PassSigningException(Throwable cause) {
// 		super(cause);
// 	}
// 
// 	public PassSigningException(String message, Throwable cause) {
// 		super(message, cause);
// 	}
// 
// }


// Path: src/main/java/com/ryantenney/passkit4j/PassSerializer.java
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.DigestException;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import lombok.Delegate;
import lombok.Getter;
import lombok.experimental.Accessors;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.ryantenney.passkit4j.io.NamedInputStreamSupplier;
import com.ryantenney.passkit4j.model.PassInformation;
import com.ryantenney.passkit4j.sign.PassSigner;
import com.ryantenney.passkit4j.sign.PassSigningException;

			throw new PassSerializationException(e);
		} finally {
			try {
				if (zip != null) zip.close();
			} catch (IOException e) {
				throw new PassSerializationException("Error closing output stream", e);
			}
		}
	}

	protected static ObjectNode generatePass(Pass pass) {
		ObjectNode tree = objectMapper.valueToTree(pass);

		PassInformation info = pass.passInformation();
		tree.put(info.typeName(), objectMapper.valueToTree(info));

		return tree;
	}

	protected static ObjectNode generateManifest(Map<String, String> files) {
		ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
		for (Map.Entry<String, String> file : files.entrySet()) {
			node.put(file.getKey(), file.getValue());
		}
		return node;
	}

	protected static Map<String, String> writeAndHashFiles(List<NamedInputStreamSupplier> files, ZipOutputStream output) throws IOException, NoSuchAlgorithmException, DigestException, NoSuchProviderException {
		Map<String, String> hashes = new HashMap<String, String>();
		for (NamedInputStreamSupplier file : files) {
			OutputStreamHasher hasher = hasher(zipEntry(file.getName(), output));