001/*license*\
002   Codelet: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
003
004   This software is dual-licensed under the:
005   - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
006   - Apache Software License (ASL) version 2.0.
007
008   Either license may be applied at your discretion. More information may be found at
009   - http://en.wikipedia.org/wiki/Multi-licensing.
010
011   The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
012   - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
013   - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
014\*license*/
015package  com.github.aliteralmind.codelet.util;
016   import  com.github.xbn.array.CrashIfArray;
017   import  com.github.xbn.array.Duplicates;
018   import  com.github.xbn.array.NullContainer;
019   import  com.github.xbn.array.NullElement;
020   import  com.github.xbn.io.NewTextAppenterFor;
021   import  com.github.xbn.io.TextAppenter;
022   import  com.github.xbn.lang.CrashIfObject;
023   import  com.github.xbn.regexutil.IgnoreCase;
024   import  com.github.xbn.text.CrashIfString;
025   import  com.github.xbn.util.DefaultValueFor;
026   import  com.github.xbn.util.EnumUtil;
027   import  java.util.Arrays;
028   import  java.util.Collections;
029   import  java.util.List;
030   import  java.util.Objects;
031   import  java.util.Properties;
032   import  java.util.regex.Pattern;
033   import  org.apache.commons.io.FilenameUtils;
034   import  org.apache.commons.io.IOCase;
035   import  static com.github.xbn.lang.XbnConstants.*;
036/**
037   <p>For black- or white-listing file paths or fully-qualified class names, with overrides. This is based on <code>org.apache.commons.io.{@link org.apache.commons.io.FilenameUtils FilenameUtils}.{@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String, IOCase) wildcardMatch}(String, String, IOCase)</code>, with the exception paths and all wildcard patterns must be non-{@code null} and non-empty.</p>
038
039{@.codelet.and.out com.github.aliteralmind.codelet.examples.util.BlackWhiteListForJavaClasses%eliminateCommentBlocksAndPackageDecl()}
040
041 * @since  0.1.0
042 * @author  Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <a href="http://codelet.aliteralmind.com">{@code http://codelet.aliteralmind.com}</a>, <a href="https://github.com/aliteralmind/codelet">{@code https://github.com/aliteralmind/codelet}</a>
043 **/
044public class FilenameBlackWhiteList  {
045   private static final String[] EMPTY_STRING_ARRAY = {};
046   private final boolean      isWhitelist       ;
047   private final IOCase       caseSensitivity   ;
048   private final List<String> propersImtblList  ;
049   private final List<String> overridesImtblList;
050   private final TextAppenter dbgAptr           ;
051   /**
052      <p>Create a new instance.</p>
053
054    * @param  type  May not be {@code null}. Get with {@link #isWhitelist() isWhitelist}{@code ()}.
055    * @param  case_sensitivity  May not be {@code null}. Get with {@link #getCaseSensitivity() getCaseSensitivity}{@code ()}.
056    * @param  proper_items  The wildcard-match strings that define this black-or-white list. May not be {@code null} or empty, or contain {@code null} or duplicate elements.
057    * @param  override_items  If non-{@code null} and non-empty, the wildcard-match strings that should trump any proper items. When non-{@code null}, may not contain any {@code null} or duplicate elements, and each item <i>should</i> be a valid subset of those items in {@code proper_items}.
058    * @see  #FilenameBlackWhiteList(FilenameBlackWhiteList, BlackOrWhite, IOCase, Appendable)
059    */
060   public FilenameBlackWhiteList(BlackOrWhite type, IOCase case_sensitivity, String[] proper_items, String[] override_items, Appendable dbgAccept_ifNonNull)  {
061      Objects.requireNonNull(case_sensitivity, "case_sensitivity");
062      try  {
063         isWhitelist = type.isWhite();
064      }  catch(RuntimeException rx)  {
065         throw  CrashIfObject.nullOrReturnCause(type, "type", null, rx);
066      }
067      CrashIfArray.bad(proper_items, "proper_items", NullContainer.BAD, 1, null, NullElement.BAD, 1, null, Duplicates.BAD);
068      CrashIfArray.bad(override_items, "override_items", NullContainer.BAD, 0, null, NullElement.BAD, 1, null, Duplicates.BAD);
069      caseSensitivity    = case_sensitivity;
070      propersImtblList   = Collections.unmodifiableList(Arrays.asList(proper_items));
071
072      if(override_items == null)  {
073         override_items = EMPTY_STRING_ARRAY;
074      }
075      overridesImtblList = Collections.unmodifiableList(Arrays.asList(override_items));
076      dbgAptr = NewTextAppenterFor.appendableUnusableIfNull(dbgAccept_ifNonNull);
077   }
078   /**
079      <p>Create a new instance from the lists in an existing {@code FilenameBlackWhiteList}.</p>
080
081    * @param  to_copyItemsFrom  May not be {@code null}.
082    * @param  type  May not be {@code null}. Get with {@link #isWhitelist() isWhitelist}{@code ()}.
083    * @param  case_sensitivity  May not be {@code null}. Get with {@link #getCaseSensitivity() getCaseSensitivity}{@code ()}.
084    * @see  #FilenameBlackWhiteList(BlackOrWhite, IOCase, String[], String[], Appendable)
085    */
086   public FilenameBlackWhiteList(FilenameBlackWhiteList to_copyItemsFrom, BlackOrWhite type, IOCase case_sensitivity, Appendable dbgAccept_ifNonNull)  {
087      Objects.requireNonNull(case_sensitivity, "case_sensitivity");
088      try  {
089         isWhitelist = type.isWhite();
090      }  catch(RuntimeException rx)  {
091         throw  CrashIfObject.nullOrReturnCause(type, "type", null, rx);
092      }
093      caseSensitivity    = case_sensitivity;
094      propersImtblList   = to_copyItemsFrom.propersImtblList;
095      overridesImtblList = to_copyItemsFrom.overridesImtblList;
096      dbgAptr = NewTextAppenterFor.appendableUnusableIfNull(dbgAccept_ifNonNull);
097   }
098   /**
099      <p>Is this a whitelist?.</p>
100
101    * @return  <ul>
102         <li>{@code true}: {@linkplain #isMatchedByProper(String) Proper matching} paths, when not {@linkplain #isMatchedByOverride(String) overridden}, are {@linkplain #doAccept(String) accepted}</li>
103         <li>{@code false}: Proper matching paths, when not overridden, are not accepted.</li>
104      </ul>
105    * @see  #FilenameBlackWhiteList(BlackOrWhite, IOCase, String[], String[], Appendable)
106    */
107   public boolean isWhitelist()  {
108      return  isWhitelist;
109   }
110   /**
111      <p>Is case ignored, required, or system-determined?.</p>
112
113    * @return  <ul>
114         <li><code>{@link org.apache.commons.io.IOCase}.{@link org.apache.commons.io.IOCase#INSENSITIVE INSENSITIVE}</code>: If case is ignored.</li>
115         <li><code>IOCase.{@link org.apache.commons.io.IOCase#SENSITIVE SENSITIVE}</code>: If case is not ignored.</li>
116         <li><code>IOCase.{@link org.apache.commons.io.IOCase#SYSTEM SYSTEM}</code>: If the underlying operation system determines case sensitivity.</li>
117      </ul>
118    * @see  #isMatchedByProper(String) isMatchedByProper(s)
119    * @see  #isMatchedByOverride(String) isMatchedByOverride(s)
120    * @see  org.apache.commons.io.FilenameUtils#wildcardMatchOnSystem(String, String)
121    */
122   public IOCase getCaseSensitivity()  {
123      return  caseSensitivity;
124   }
125   /**
126      <p>The unmodifiable list of wildcard items that, when matched--and not overridden--are either acceptable (white-listed) or unacceptable (black-listed).</p>
127
128    * @see  #getImmutableOverrideList()
129    * @see  #isMatchedByProper(String) isMatchedByProper(s)
130    * @see  #FilenameBlackWhiteList(BlackOrWhite, IOCase, String[], String[], Appendable) FilenameBlackWhiteList(bow,ioc,s[],s[])
131    */
132   public List<String> getImmutableProperList()  {
133      return  propersImtblList;
134   }
135   /**
136      <p>The unmodifiable list of wildcard items that, when matched, override the &quot;proper&quot; finding. This is ignored when no proper item is matched.</p>
137
138    * @see  #getImmutableProperList()
139    * @see  #isMatchedByOverride(String) isMatchedByOverride(s)
140    * @see  #FilenameBlackWhiteList(BlackOrWhite, IOCase, String[], String[], Appendable) FilenameBlackWhiteList(bow,ioc,s[],s[])
141    */
142   public List<String> getImmutableOverrideList()  {
143      return  overridesImtblList;
144   }
145   public String toString()  {
146      return  appendToString(new StringBuilder()).toString();
147   }
148   public StringBuilder appendToString(StringBuilder to_appendTo)  {
149      try  {
150         return  to_appendTo.append(BlackOrWhite.getBlackIfTrue(!isWhitelist())).
151            append(" (").append(getCaseSensitivity()).append("), propers=").append(Arrays.toString(getImmutableProperList().toArray())).append(", overrides=").append(Arrays.toString(getImmutableOverrideList().toArray()));
152      }  catch(RuntimeException rx)  {
153         throw  CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
154      }
155   }
156   /**
157      <p>Is the path (or fully-qualified class name) accepted?.</p>
158
159    * @param  path  May not be {@code null} or empty.
160    * @return  <TABLE ALIGN="left" BORDER="1" CELLSPACING="0" CELLPADDING="4" BGCOLOR="#EEEEEE"><TR ALIGN="center" VALIGN="middle">
161         <TD>{@code isMatchedByProper(path)}</TD>
162         <TD>{@code isMatchedByOverride(path)}</TD>
163         <TD>{@code isWhitelist()}</TD>
164         <TD><b><u>Returned</u></b></TD>
165      </TR><TR>
166         <TD>{@code true}</TD>
167         <TD>{@code true}</TD>
168         <TD>{@code true}</TD>
169         <TD><b>{@code false}</b></TD>
170      </TR><TR>
171         <TD>{@code true}</TD>
172         <TD>{@code true}</TD>
173         <TD>{@code false}</TD>
174         <TD><b>{@code true}</b></TD>
175      </TR><TR>
176         <TD>{@code true}</TD>
177         <TD>{@code false}</TD>
178         <TD>{@code true}</TD>
179         <TD><b>{@code true}</b></TD>
180      </TR><TR>
181         <TD>{@code true}</TD>
182         <TD>{@code false}</TD>
183         <TD>{@code false}</TD>
184         <TD><b>{@code false}</b></TD>
185      </TR><TR>
186         <TD>{@code false}</TD>
187         <TD><i>n/a</i></TD>
188         <TD>{@code true}</TD>
189         <TD><b>{@code false}</b></TD>
190      </TR><TR>
191         <TD>{@code false}</TD>
192         <TD><i>n/a</i></TD>
193         <TD>{@code false}</TD>
194         <TD><b>{@code true}</b></TD>
195      </TR></TABLE>
196    * @see  org.apache.commons.io.FilenameUtils
197    */
198   public boolean doAccept(String path)  {
199      if(dbgAptr.isUseable())  {
200         dbgAptr.appentln("doAccept? path=\"" + path + "\"");
201      }
202      CrashIfString.nullEmpty(path, "path", null);
203
204      boolean isMatchedByProper = isMatchedByProper(path);
205      boolean isMatchedByOverride = isMatchedByOverride(path);
206
207      if(dbgAptr.isUseable())  {
208         dbgAptr.appentln("  - isMatchedByProper(path)=" + isMatchedByProper);
209         dbgAptr.appentln("  - isMatchedByOverride(path)=" + isMatchedByOverride);
210         dbgAptr.appentln("  - isWhitelist()=" + isWhitelist());
211      }
212
213      boolean doAccept = false;
214      if(isMatchedByProper)  {
215         doAccept = (isMatchedByOverride
216            ?  !isWhitelist()
217            :  isWhitelist());
218
219      }  else  {
220         doAccept = (!isWhitelist());
221      }
222
223      if(dbgAptr.isUseable())  {
224         dbgAptr.appentln("  - " + (doAccept ? "ACCEPTED" : "unacceptable"));
225      }
226
227      return  doAccept;
228   }
229   /**
230      <p>Does the path match a main item?.</p>
231
232      <p>For each item in the {@linkplain #getImmutableProperList() proper-list}, this calls</p>
233
234<blockquote><pre>{@link org.apache.commons.io.FilenameUtils FilenameUtils}.{@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String, IOCase) wildcardMatch}(path, <i>[proper-item]</i>, {@link #getCaseSensitivity() getCaseSensitivity}())</pre></blockquote>
235
236      <p>If this returns {@code true} for any element, <i>this</i> function returns {@code true}. If it returns {@code false} for every element, <i>this</i> function returns {@code false}.</p>
237
238    * @see  #doAccept(String)
239    */
240   public boolean isMatchedByProper(String path)  {
241      return  isMatchedByProper(false, path);
242   }
243      private boolean isMatchedByProper(boolean doCrashIfPath_nullEmpty, String path)  {
244         if(doCrashIfPath_nullEmpty)  {
245            CrashIfString.nullEmpty(path, "path", null);
246         }
247         for(String proper : getImmutableProperList())  {
248            if(FilenameUtils.wildcardMatch(path, proper, getCaseSensitivity()))  {
249               return  true;
250            }
251         }
252         return  false;
253      }
254
255   /**
256      <p>Does the path match an override item?. This should only be used after a proper item is matched.</p>
257
258      <p>For each item in the {@linkplain #getImmutableOverrideList() override-list}, this calls</p>
259
260<blockquote><pre>{@link org.apache.commons.io.FilenameUtils FilenameUtils}.{@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String, IOCase) wildcardMatch}(path, <i>[proper-item]</i>, {@link #getCaseSensitivity() getCaseSensitivity}())</pre></blockquote>
261
262      <p>If this returns {@code true} for any element, <i>this</i> function returns {@code true}. If it returns {@code false} for every element, <i>this</i> function returns {@code false}.</p>
263
264    * @see  #doAccept(String)
265    */
266   public boolean isMatchedByOverride(String path)  {
267      return  isMatchedByOverride(false, path);
268   }
269      private boolean isMatchedByOverride(boolean doCrashIfPath_nullEmpty, String path)  {
270         if(doCrashIfPath_nullEmpty)  {
271            CrashIfString.nullEmpty(path, "path", null);
272         }
273         for(String override : getImmutableOverrideList())  {
274            if(FilenameUtils.wildcardMatch(path, override, getCaseSensitivity()))  {
275               return  true;
276            }
277         }
278         return  false;
279      }
280   /**
281        @return  <code>true</code> If {@code to_compareTo} is non-{@code null}, a {@code FilenameBlackWhiteList}, and all its fields {@linkplain #areFieldsEqual(FilenameBlackWhiteList) are equal}. This is implemented as suggested by Joshua Bloch in &quot;Effective Java&quot; (2nd ed, item 8, page 46).
282    */
283   @Override
284   public boolean equals(Object to_compareTo)  {
285      //Check for object equality first, since it's faster than instanceof.
286      if(this == to_compareTo)  {
287         return  true;
288      }
289      if(!(to_compareTo instanceof FilenameBlackWhiteList))  {
290         //to_compareTo is either null or not an FilenameBlackWhiteList.
291         //java.lang.Object.object(o):
292         // "For any non-null reference value x, x.equals(null) should return false."
293         //See the bottom of this class for a counter-argument (which I'm not going with).
294         return  false;
295      }
296
297      //Safe to cast
298      FilenameBlackWhiteList o = (FilenameBlackWhiteList)to_compareTo;
299
300      //Finish with field-by-field comparison.
301      return  areFieldsEqual(o);
302   }
303   /**
304      <p>Are <i>all</i> fields equal?.</p>
305
306    * @param  to_compareTo  May not be {@code null}.
307    */
308   public boolean areFieldsEqual(FilenameBlackWhiteList to_compareTo)  {
309      try  {
310         return  (to_compareTo.isWhitelist() == isWhitelist()  &&
311            to_compareTo.getCaseSensitivity() == getCaseSensitivity()  &&
312            to_compareTo.getImmutableProperList().equals(getImmutableProperList())  &&
313            to_compareTo.getImmutableOverrideList().equals(getImmutableOverrideList()));
314      }  catch(RuntimeException rx)  {
315         throw  CrashIfObject.nullOrReturnCause(to_compareTo, "to_compareTo", null, rx);
316      }
317   }
318   /**
319      <p>Creates a new white-or-blacklist from a set of properties.</p>
320
321      <p>All {@code "Name"} parameters must be the name of existing properties in {@code props}.</p>
322
323    * @param  props  May not be {@code null}, and must contain properties named as in the {@code "*Name"} parameters.
324    * @return  <code>{@link #newFromConfigStringVars(String, String, String, String, String, Appendable, Appendable) newFromConfigStringVars}(black_white_off, ignore_require_system, separator, separated_propers, separated_overrides, dbgLoading_ifNonNull, dbgAccept_ifNonNull)</code>
325      <br/>Where all variables (except {@code separator}) are the values of the properties with an empty-string default. Such as
326      <br/> &nbsp; &nbsp; <code>String ignore_require_system = props.getProperty(ignore_require_systemName, &quot;&quot;)</code>
327    */
328   public static final FilenameBlackWhiteList newFromProperties(Properties props, String separator, String black_white_offName, String ignore_require_systemName, String separated_propersName, String separated_overridesName, Appendable dbgLoading_ifNonNull, Appendable dbgAccept_ifNonNull)  {
329      TextAppenter dbgAptr = NewTextAppenterFor.appendableUnusableIfNull(dbgLoading_ifNonNull);
330      String black_white_off = null;
331      try  {
332         black_white_off = props.getProperty(black_white_offName, "");
333      }  catch(RuntimeException rx)  {
334         throw  CrashIfObject.nullOrReturnCause(props, "props", null, rx);
335      }
336      String ignore_require_system = props.getProperty(ignore_require_systemName, "");
337      String separated_propers = props.getProperty(separated_propersName, "");
338      String separated_overrides = props.getProperty(separated_overridesName, "");
339
340      if(dbgAptr.isUseable())  {
341         dbgAptr.appentln("FilenameBlackWhiteList.newFromProperties:");
342         dbgAptr.appentln(" - " + black_white_offName + "=" + black_white_off);
343         dbgAptr.appentln(" - " + ignore_require_systemName + "=" + ignore_require_system);
344         dbgAptr.appentln(" - " + separated_propersName + "=" + separated_propers);
345         dbgAptr.appentln(" - " + separated_overridesName + "=" + separated_overrides);
346      }
347
348      try  {
349         return  newFromConfigStringVars(black_white_off, ignore_require_system, separator, separated_propers, separated_overrides, dbgLoading_ifNonNull, dbgAccept_ifNonNull);
350      }  catch(RuntimeException rx)  {
351         throw  new RuntimeException("separator=\"" + separator + "\", " + black_white_offName + "=\"" + black_white_off + "\"" + LINE_SEP + " - " + ignore_require_systemName + "=\"" + ignore_require_system + "\"" + LINE_SEP + " - " + separated_propersName + "=\"" + separated_propers + "\"" + LINE_SEP + " - " + separated_overridesName + "=\"" + separated_overrides + "\"", rx);
352      }
353   }
354   /**
355      <p>Creates a new white-or-blacklist from a set of string-variables as found in a configuration text file.</p>
356
357    * @param  black_white_off  Is this a {@linkplain com.github.aliteralmind.codelet.util.BlackOrWhite#BLACK blacklist}, {@linkplain com.github.aliteralmind.codelet.util.BlackOrWhite#WHITE whitelist}, or nothing? Must be {@code "black"}, {@code "white"}, or {@code "off"} (the case of this parameter's value is ignored). If {@code "off"}, this function <i><b>returns</b></i> a new {@code FilenameBlackWhiteList} that {@linkplain #newForAcceptAll(Appendable) accepts everything}.
358    * @param  ignore_require_system  Should case be {@linkplain org.apache.commons.io.IOCase#INSENSITIVE ignored}, {@linkplain org.apache.commons.io.IOCase#SENSITIVE <i>not</i> ignored}, or determined by the operating {@linkplain org.apache.commons.io.IOCase#SYSTEM system}? Must be {@code "ignore"}, {@code "require"}, or {@code "system"} (the case of <i>this parameter's value</i> is ignored).
359    * @param  separator  The character used to separate each proper and override value. Such as a comma ({@code ","}), {@linkplain com.github.xbn.lang.XbnConstants#LINE_SEP line-separator} ({@code "\r\n"}), or tab ({@code "\t"}). May not be {@code null}, empty, or contain any letters, digits, underscores ({@code '_'}), question-marks ({@code '?'}), or asterisks ({@code '*'}).
360    * @param  separated_propers  The separated list of &quot;proper&quot; items. Must be separated by {@code separator}, and otherwise must conform to the restrictions for the {@link #FilenameBlackWhiteList(BlackOrWhite, IOCase, String[], String[], Appendable) proper_items} constructor parameter.
361    * @param  separated_overrides  The separated list of override items. Must be non-{@code null} (if none, this must be the empty string: {@code ""}), separated by {@code separator}, and otherwise must conform to the restrictions for the {@code override_items} constructor parameter.
362    * @see  #newFromProperties(Properties, String, String, String, String, String, Appendable, Appendable) newFromProperties
363    */
364   public static final FilenameBlackWhiteList newFromConfigStringVars(String black_white_off, String ignore_require_system, String separator, String separated_propers, String separated_overrides, Appendable dbgLoading_ifNonNull, Appendable dbgAccept_ifNonNull)  {
365      TextAppenter dbgAptr = NewTextAppenterFor.appendableUnusableIfNull(dbgLoading_ifNonNull);
366
367      if(dbgAptr.isUseable())  {
368         dbgAptr.appentln("FilenameBlackWhiteList newFromConfigStringVars:");
369      }
370
371      try  {
372         if(black_white_off.toLowerCase().equals("off"))  {
373            if(dbgAptr.isUseable())  {
374               dbgAptr.appentln(" - newForAcceptAll(dbgAccept_ifNonNull). DONE");
375            }
376            return  newForAcceptAll(dbgAccept_ifNonNull);
377         }
378      }  catch(RuntimeException rx)  {
379         throw  CrashIfObject.nullOrReturnCause(black_white_off, "black_white_off", null, rx);
380      }
381
382      BlackOrWhite bw = EnumUtil.toValueWithNullDefault(black_white_off, "black_white_off", IgnoreCase.YES, DefaultValueFor.NOTHING, BlackOrWhite.BLACK);
383
384      if(dbgAptr.isUseable())  {
385         dbgAptr.appentln(" - BlackOrWhite." + bw);
386      }
387
388      IOCase ioc = null;
389      try  {
390         switch(ignore_require_system.toUpperCase())  {
391            case  "IGNORE":  ioc = IOCase.INSENSITIVE;  break;
392            case  "REQUIRE":  ioc = IOCase.SENSITIVE;  break;
393            case  "SYSTEM":  ioc = IOCase.SYSTEM;  break;
394            default:
395               throw  new IllegalArgumentException("ignore_require_system.toUpperCase() (\"" + ignore_require_system.toUpperCase() + "\") does not equal \"IGNORE\", \"REQUIRE\", or \"SYSTEM\".");
396         }
397      }  catch(RuntimeException rx)  {
398         throw  CrashIfObject.nullOrReturnCause(ignore_require_system, "ignore_require_system", null, rx);
399      }
400
401      if(dbgAptr.isUseable())  {
402         dbgAptr.appentln(" - IOCase." + ioc);
403      }
404
405      CrashIfString.nullEmpty(separator, "separator", null);
406      if(Pattern.compile("[?*\\w]").matcher(separator).find())  {
407         throw  new IllegalArgumentException("separator (\"" + separator + "\") contains an illegal character.");
408      }
409
410      if(dbgAptr.isUseable())  {
411         dbgAptr.appentln(" - separator valid: \"" + separator + "\"");
412      }
413
414      String[] propers = null;
415      try  {
416         propers = separated_propers.split(separator);
417      }  catch(RuntimeException rx)  {
418         throw  CrashIfObject.nullOrReturnCause(separated_propers, "separated_propers", null, rx);
419      }
420
421      if(dbgAptr.isUseable())  {
422         dbgAptr.appentln(" - Propers: " + Arrays.toString(propers));
423      }
424
425      String[] overrides = null;
426      try  {
427         if(separated_overrides.length() == 0)  {
428            overrides = EMPTY_STRING_ARRAY;
429         }  else  {
430            overrides = separated_overrides.split(separator);
431         }
432      }  catch(RuntimeException rx)  {
433         throw  CrashIfObject.nullOrReturnCause(separated_overrides, "separated_overrides", null, rx);
434      }
435
436      if(dbgAptr.isUseable())  {
437         dbgAptr.appentln(" - Overrides: " + Arrays.toString(overrides) + "...DONE");
438      }
439
440      return  new FilenameBlackWhiteList(bw, ioc, propers, overrides, dbgAccept_ifNonNull);
441   }
442   /**
443      <p>A new instance that accepts everything.</p>
444
445    * @return  <code>new {@link #FilenameBlackWhiteList(BlackOrWhite, IOCase, String[], String[], Appendable) FilenameBlackWhiteList}({@link com.github.aliteralmind.codelet.util.BlackOrWhite BlackOrWhite}.{@link com.github.aliteralmind.codelet.util.BlackOrWhite#WHITE WHITE}, {@link org.apache.commons.io.IOCase IOCase}.{@link org.apache.commons.io.IOCase#INSENSITIVE INSENSITIVE}, (new String[]{&quot;*&quot;}), (new String[]{}), dbgAccept_ifNonNull)</code>.
446
447    */
448   public static final FilenameBlackWhiteList newForAcceptAll(Appendable dbgAccept_ifNonNull)  {
449      return  (new FilenameBlackWhiteList(BlackOrWhite.WHITE, IOCase.INSENSITIVE, (new String[]{"*"}), EMPTY_STRING_ARRAY, dbgAccept_ifNonNull));
450   }
451}