package io.domisum.lib.auxiliumlib.util;

import io.domisum.lib.auxiliumlib.annotations.API;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.util.Optional;

@API
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ExceptionUtil
{
	
	// CONTAINS
	@API
	@SuppressWarnings("unchecked")
	public static <T extends Throwable> Optional<T> getContained(Throwable throwable, Class<T> type)
	{
		ValidationUtil.notNull(throwable, "throwable");
		
		if(type.equals(throwable.getClass()))
			return Optional.of((T) throwable);
		
		var cause = throwable.getCause();
		if(cause == null)
			return Optional.empty();
		
		return getContained(cause, type);
	}
	
	@API
	public static boolean doesContain(Throwable throwable, Class<? extends Throwable> type)
	{
		return getContained(throwable, type).isPresent();
	}
	
	
	// TO STRING
	@API
	public static String convertToString(Throwable throwable)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(throwable.toString()).append("\n");
		
		for(StackTraceElement stackTraceElement : throwable.getStackTrace())
			stringBuilder.append("    ").append(stackTraceElement.toString()).append("\n");
		
		if(throwable.getCause() != null)
			stringBuilder.append("Caused by: ").append(convertToString(throwable.getCause()));
		
		return stringBuilder.toString();
	}
	
	@API
	public static String getSynopsis(Throwable throwable)
	{
		String causeSynopsis = throwable.getCause() == null ? null : getSynopsis(throwable.getCause());
		String synopsis = throwable.getClass().getSimpleName()+": "+throwable.getMessage();
		if(causeSynopsis != null)
			synopsis += "; caused by: ("+causeSynopsis+")";
		
		return synopsis;
	}
	
}

@@ -164,24 +164,72 @@
 va.util.
-Optional
+HashSet;%0Aimport java.util.Optional;%0Aimport java.util.Set
 ;%0A%0A@API%0A
@@ -365,16 +365,447 @@
 ecked%22)%0A
+%09public static %3CT extends Throwable%3E Set%3CT%3E getContained(Throwable throwable, Class%3CT%3E type)%0A%09%7B%0A%09%09ValidationUtil.notNull(throwable, %22throwable%22);%0A%09%09%0A%09%09var contained = new HashSet%3CT%3E();%0A%09%09if(type.equals(throwable.getClass()))%0A%09%09%09contained.add((T) throwable);%0A%09%09%0A%09%09var cause = throwable.getCause();%0A%09%09if(cause != null)%0A%09%09%09contained.addAll(getContained(cause, type));%0A%09%09%0A%09%09return contained;%0A%09%7D%0A%09%0A%09@API%0A%09@SuppressWarnings(%22unchecked%22)%0A
 %09public 
@@ -844,24 +844,30 @@
 ional%3CT%3E get
+Single
 Contained(Th
@@ -1128,32 +1128,38 @@
 %0A%09%09%0A%09%09return get
+Single
 Contained(cause,
@@ -1269,16 +1269,16 @@
 ype)%0A%09%7B%0A
-
 %09%09return
@@ -1277,24 +1277,30 @@
 %09%09return get
+Single
 Contained(th

Add ExceptionUtil#getContained for multiple contained exceptions