001package io.jstach.jstachio.spi; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.ServiceLoader; 006 007import io.jstach.jstachio.JStachio; 008 009/** 010 * Creates JStachios mainly with the {@link ServiceLoader} or a {@link Builder}. 011 * 012 * @author agentgt 013 * 014 */ 015public final class JStachioFactory { 016 017 /** 018 * @hidden 019 */ 020 private JStachioFactory() { 021 022 } 023 024 /** 025 * Provides a singleton JStachio resolved by the {@link ServiceLoader} 026 * @return service loader based jstachio. 027 */ 028 public static JStachio defaultJStachio() { 029 return Holder.INSTANCE; 030 } 031 032 /** 033 * A <em>mutable</em> builder to create {@link JStachio} from 034 * {@link JStachioExtension}s. 035 * @return empty builder 036 */ 037 public static Builder builder() { 038 return new Builder(); 039 } 040 041 private static class Holder extends AbstractJStachio { 042 043 private static Holder INSTANCE = Holder.of(); 044 045 private final JStachioExtensions extensions; 046 047 public Holder(JStachioExtensions extensions) { 048 this.extensions = extensions; 049 } 050 051 private static Holder of() { 052 Iterable<JStachioExtension> it = ServiceLoader.load(JStachioExtension.class); 053 return new Holder(JStachioExtensions.of(it)); 054 } 055 056 @Override 057 public JStachioExtensions extensions() { 058 return this.extensions; 059 } 060 061 } 062 063 /** 064 * Builder for creating jstachios. 065 * 066 * @author agent 067 * 068 */ 069 public static class Builder { 070 071 private List<JStachioExtension> extensions = new ArrayList<>(); 072 073 /** 074 * Constructor is hidden for now. 075 */ 076 private Builder() { 077 } 078 079 /** 080 * Adds an extension 081 * @param extension not null 082 * @return this 083 */ 084 public Builder add(JStachioExtension extension) { 085 extensions.add(extension); 086 return this; 087 } 088 089 /** 090 * Add extensions. 091 * 092 * Useful for adding ServiceLoader results: <pre> 093 * <code class="language-java"> 094 * builder.add(ServiceLoader.load(JStachioExtension.class)); 095 * </code> </pre> 096 * @param extensions not null 097 * @return this 098 */ 099 public Builder add(Iterable<JStachioExtension> extensions) { 100 extensions.forEach(this.extensions::add); 101 return this; 102 } 103 104 /** 105 * Builds a JStachio by coalescing the extensions. 106 * 107 * @apiNote See {@link JStachioExtensions} for logic on how the extensions are 108 * consolidated. 109 * @return resolved JStachio 110 */ 111 public JStachio build() { 112 return new DefaultJStachio(JStachioExtensions.of(extensions)); 113 } 114 115 /** 116 * Current mutable list of extensions. 117 * @return mutable list of extensions 118 */ 119 public List<JStachioExtension> extensions() { 120 return extensions; 121 } 122 123 } 124 125}