package org.jboss.forge.addon.facets;

import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 
 * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
 * 
 * @param <FACETTYPE> the base {@link Facet} type supported by this {@link Faceted} type.
 */
public abstract class AbstractFaceted<FACETTYPE extends Facet<?>> implements MutableFaceted<FACETTYPE>
{
   private Set<FACETTYPE> facets = Collections.newSetFromMap(new ConcurrentHashMap<FACETTYPE, Boolean>());

   @Override
   public boolean hasFacet(Class<? extends FACETTYPE> type)
   {
      return getFacetAsOptional(type).isPresent();
   }

   @SuppressWarnings("unchecked")
   @Override
   public boolean hasAllFacets(Class<? extends FACETTYPE>... facetDependencies)
   {
      return hasAllFacets(Arrays.asList(facetDependencies));
   }

   @Override
   public boolean hasAllFacets(Iterable<Class<? extends FACETTYPE>> facetDependencies)
   {
      for (Class<? extends FACETTYPE> facetDependency : facetDependencies)
      {
         if (!hasFacet(facetDependency))
         {
            return false;
         }
      }
      return true;
   }

   @Override
   public <F extends FACETTYPE> F getFacet(Class<F> type) throws FacetNotFoundException
   {
      return getFacetAsOptional(type)
               .orElseThrow(() -> new FacetNotFoundException("No Facet of type [" + type + "] is installed."));
   }

   @Override
   @SuppressWarnings("unchecked")
   public <F extends FACETTYPE> Optional<F> getFacetAsOptional(Class<F> type)
   {
      return (Optional<F>) facets.stream().filter((facet) -> type.isInstance(facet)).findFirst();
   }

   @Override
   public Iterable<FACETTYPE> getFacets()
   {
      return Collections.unmodifiableCollection(facets);
   }

   @Override
   public boolean install(FACETTYPE facet)
   {
      if (facet.getFaceted() != this)
         throw new IllegalArgumentException("[" + facet + "].getOrigin() was [" + facet.getFaceted()
                  + "] but needed to be [" + this + "]. If your facet type implements "
                  + MutableFacet.class.getSimpleName() + ", " +
                  "ensure that a valid origin was supplied during facet creation.");

      if (supports(facet))
      {
         if (facet.isInstalled() || facet.install())
         {
            facets.add(facet);
            return true;
         }
      }
      return false;
   }

   @Override
   public boolean register(FACETTYPE facet)
   {
      if (facet.getFaceted() != this)
         throw new IllegalArgumentException("[" + facet + "].getOrigin() was [" + facet.getFaceted()
                  + "] but needed to be [" + this + "]. If your facet type implements "
                  + MutableFacet.class.getSimpleName() + ", " +
                  "ensure that a valid origin was supplied during facet creation.");

      if (supports(facet))
      {
         if (facet.isInstalled())
         {
            facets.add(facet);
            return true;
         }
      }
      return false;
   }

   @Override
   @SuppressWarnings("unchecked")
   public <F extends FACETTYPE> Iterable<F> getFacets(Class<F> type)
   {
      return (Set<F>) facets.stream().filter((facet) -> type.isInstance(facet)).collect(Collectors.toSet());
   }

   @Override
   public boolean uninstall(FACETTYPE facet)
   {
      return facet.isInstalled() ? (facet.uninstall() && facets.remove(facet))
               : (!facets.contains(facet) || facets.remove(facet));
   }

   @Override
   public boolean unregister(FACETTYPE facet)
   {
      return facet.isInstalled() ? false : facets.remove(facet);
   }

}

@@ -87,16 +87,42 @@
 ctions;%0A
+import java.util.HashSet;%0A
 import j
@@ -212,44 +212,8 @@
 Map;
-%0Aimport java.util.stream.Collectors;
 %0A%0A/*
@@ -700,85 +700,41 @@
 urn 
-g
+safeG
 etFacet
-AsOptional(type).isPresent();%0A   %7D%0A%0A   @SuppressWarnings(%22unchecked%22)
+(type) != null;%0A   %7D%0A
 %0A   
@@ -1321,73 +1321,85 @@
     
-return getFacetAsOptional
+F facet = safeGetFacet
 (type)
+;
 %0A      
-         .orElseThrow(() -%3E
+if (facet == null)%0A      %7B%0A         throw
  new
@@ -1474,63 +1474,86 @@
 d.%22)
-)
 ;%0A   
+   
 %7D%0A
-%0A   @Override%0A   @SuppressWarnings(%22unchecked%22)
+      else%0A      %7B%0A         return facet;%0A      %7D%0A   %7D%0A%0A   @Override
 %0A   
@@ -1649,17 +1649,16 @@
 urn 
-(
 Optional
 %3CF%3E)
@@ -1657,81 +1657,42 @@
 onal
+.
 %3CF%3E
-) facets.stream().filter((facet) -%3E type.isInstance(facet)).findFirst(
+ ofNullable(safeGetFacet(type)
 );%0A 
@@ -3208,109 +3208,728 @@
     
-return (Set%3CF%3E) facets.stream().filter((facet) -%3E type.isInstance(facet)).collect(Collectors.toSet())
+Set%3CF%3E result = new HashSet%3CF%3E();%0A      for (FACETTYPE facet : facets)%0A      %7B%0A         if (type.isInstance(facet))%0A         %7B%0A            result.add((F) facet);%0A         %7D%0A      %7D%0A      return result;%0A   %7D%0A%0A   /**%0A    * Returns the installed facet that is an instance of the provided type argument, null otherwise.%0A    * %0A    * It does not throw any exception%0A    * %0A    * @param type the facet type%0A    * @return the Facet if found, otherwise, null%0A    */%0A   @SuppressWarnings(%22unchecked%22)%0A   private %3CF extends FACETTYPE%3E F safeGetFacet(Class%3CF%3E type)%0A%0A   %7B%0A      for (FACETTYPE facet : facets)%0A      %7B%0A         if (type.isInstance(facet))%0A         %7B%0A            return (F) facet;%0A         %7D%0A      %7D%0A      return null
 ;%0A  

Revert "AbstractFaceted uses JDK 8 features"