/**
 * Copyright (C) 2011
 *   Michael Mosmann <michael@mosmann.de>
 *   Martin Jöhren <m.joehren@googlemail.com>
 *
 * with contributions from
 * 	konstantin-ba@github,
	Archimedes Trajano (trajano@github),
	Kevin D. Keck (kdkeck@github),
	Ben McCann (benmccann@github)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.flapdoodle.embed.process.config.store;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

public class FileSet {

	private final List<Entry> _entries;

	public FileSet(Collection<Entry> entries) {
		if (entries==null) throw new NullPointerException("entries is NULL");
		_entries = Collections.unmodifiableList(new ArrayList<Entry>(entries));
		boolean oneOrMoreExecutableFound=false;
		for (Entry e : _entries) {
			if (e.type()==FileType.Executable) {
				oneOrMoreExecutableFound=true;
				break;
			}
		}
		if (!oneOrMoreExecutableFound) {
			throw new IllegalArgumentException("there is no executable in this file set");
		}
	}
	
	
	public List<Entry> entries() {
		return Collections.unmodifiableList(_entries);
	}

	public static class Entry {

		private final FileType _type;
		private final String _destination;
		private final Pattern _matchingPattern;

		public Entry(FileType type, String destination, Pattern matchingPattern) {
			_type = type;
			_destination = destination;
			_matchingPattern = matchingPattern;
		}

		public FileType type() {
			return _type;
		}

		public String destination() {
			return _destination;
		}

		public Pattern matchingPattern() {
			return _matchingPattern;
		}

		@Override
		public boolean equals(Object other) {
			if (this == other) {
				return true;
			}

			if (other == null || getClass() != other.getClass()) {
				return false;
			}

			Entry entry = (Entry) other;

			return _type == entry._type
				&& !(_destination != null ? !_destination.equals(entry._destination) : entry._destination != null)
				&& !(_matchingPattern != null ? !_matchingPattern.equals(entry._matchingPattern) : entry._matchingPattern != null);
		}

		@Override
		public int hashCode() {
			int result = _type != null ? _type.hashCode() : 0;
			result = 31 * result + (_destination != null ? _destination.hashCode() : 0);
			result = 31 * result + (_matchingPattern != null ? _matchingPattern.hashCode() : 0);
			return result;
		}
	}
	
	public static Builder builder() {
		return new Builder();
	}
	
	public static class Builder {

		private final List<Entry> _entries=new ArrayList<FileSet.Entry>();
		
		public Builder addEntry(FileType type, String filename) {
			return addEntry(type,filename,".*"+filename);
		}
		
		public Builder addEntry(FileType type, String filename, String pattern) {
			return addEntry(type,filename,Pattern.compile(pattern,Pattern.CASE_INSENSITIVE));
		}
		
		public Builder addEntry(FileType type, String filename, Pattern pattern) {
			_entries.add(new Entry(type,filename,pattern));
			return this;
		}
		
		public FileSet build() {
			return new FileSet(_entries);
		}
	}

}

@@ -1024,16 +1024,115 @@
 ttern;%0A%0A
+import static sun.management.snmp.jvminstr.JvmThreadInstanceEntryImpl.ThreadStateMap.Byte1.other;%0A%0A
 public c
@@ -1666,19 +1666,17 @@
 %0A%09%09%7D%0A%09%7D%0A
-%09%0A%09
+%0A
 %0A%09public
@@ -2363,16 +2363,22 @@
  == null
+) %7B //
  %7C%7C getC
@@ -2438,37 +2438,290 @@
 %0A%09%09%09
-Entry entry = (Entry) other;%0A
+/* Preferable to checking class instance equality guard. See #43. */%0A%09%09%09if (!(other instanceof FileSet.Entry)) %7B%0A%09%09%09%09return false;%0A%09%09%09%7D%0A%0A%09%09%09Entry entry = (Entry) other;%0A%0A%09%09%09/* Because Pattern doesn't implement equals, use its underlying expression (String) for equality. See #43. */
 %0A%09%09%09
@@ -2909,37 +2909,97 @@
 ern.
-equals(entry._matchingPattern
+pattern().equals(null == entry._matchingPattern ? null : entry._matchingPattern.pattern()
 ) : 
@@ -3204,24 +3204,139 @@
 ode() : 0);%0A
+%09%09%09/* Because Pattern doesn't implement hashCode, use its underlying expression (String) for equality. See #43. */%0A
 %09%09%09result = 
@@ -3394,16 +3394,26 @@
 Pattern.
+pattern().
 hashCode
@@ -3442,25 +3442,24 @@
 ult;%0A%09%09%7D%0A%09%7D%0A
-%09
 %0A%09public sta
@@ -3509,17 +3509,16 @@
 r();%0A%09%7D%0A
-%09
 %0A%09public
@@ -3611,18 +3611,16 @@
 try%3E();%0A
-%09%09
 %0A%09%09publi
@@ -3721,26 +3721,24 @@
 ename);%0A%09%09%7D%0A
-%09%09
 %0A%09%09public Bu
@@ -3887,26 +3887,24 @@
 TIVE));%0A%09%09%7D%0A
-%09%09
 %0A%09%09public Bu
@@ -4040,18 +4040,16 @@
 is;%0A%09%09%7D%0A
-%09%09
 %0A%09%09publi

Use underlying expression for equality and hashes (for #43)