1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | package Torello.HTML; import Torello.Java.StrFilter; import Torello.Java.StrCmpr; import java.util.function.Predicate; import java.util.Iterator; import java.net.URL; /** * A simple lambda-target which extends {@code Predicate<URL>}. * * <EMBED CLASS='external-html' DATA-FILE-ID=URL_FILTER> * * @see StrFilter */ @FunctionalInterface public interface URLFilter extends Predicate<URL>, java.io.Serializable { /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUIDFI> */ public static final long serialVersionUID = 1; // ******************************************************************************************** // ******************************************************************************************** // Functional-Interface Method // ******************************************************************************************** // ******************************************************************************************** /** * <EMBED CLASS='external-html' DATA-FILE-ID=FUNC_INTER_METH> * * <BR /><BR />This method will receive a {@code URL.} The purpose of this method is to * provide an easy means to filter certain {@code URL's} from a {@code URL}-generating list. * * <BR /><BR /><B><SPAN STYLE="color: red;">PRECISE NOTE:</B></SPAN> This method should return * {@code FALSE} if the passed {@code URL} <I><B>should be skipped</B></I>. A return value of * {@code TRUE} implies that the {@code URL} is not to be ignored or passed over, but rather * 'kept.' * * <BR /><BR /><B>NOTE:</B> This behavior is compatible with the Java Stream's method * {@code "filter(Predicate<...>)".} * * @param url This is a {@code URL} that will be checked against the constraints specified by * {@code 'this'} filter. * * @return When implementing this method, returning {@code TRUE} must mean that the {@code URL} * has passed the filter's test-requirements (and will subsequently be retained by whatever * code is carrying out the filter operation). */ public boolean test(URL url); // ******************************************************************************************** // ******************************************************************************************** // The basic-required methods, in order to make this a "Respectable Filter Class" // ******************************************************************************************** // ******************************************************************************************** /* * This is the standard-java {@code Predicate} method {@code 'and'}. If a user wants to apply * two {@code URLFilters,} this method will use a lambda-expression to create a new * {@code URLFilter} that "logically-AND's" the {@code 'other' Predicate} with {@code 'this' * Predicate.} * * @param other Some other {@code URLFilter} - one that does some other test. * * @return A new Java-{@code Predicate} that performs both tests ({@code 'this'} and * {@code 'other'}), and returns the logical-AND. * default URLFilter and(URLFilter other) { // FAIL-FAST: Check that the user-provided-parameters would not cause exceptions once // the lambda-predicate is invoked. if (other == null) throw new NullPointerException ("The parameter 'other' to URLFilter.and(other) was null."); return (URL url) -> this.test(url) && other.test(url); } /* * This is the standard-java {@code Predicate} method {@code 'or'}. If a user wants to apply * two {@code URLFilters,} this method will use a lambda-expression to create a new * {@code URLFilter} that "logically-OR's" the {@code 'other' Predicate} with {@code 'this' * Predicate.} * * @param other Some other {@code URLFilter} - one that does some other test. * * @return A new Java-{@code Predicate} that performs both tests ({@code 'this'} and * {@code 'other'}), and returns the logical-OR. * default URLFilter or(URLFilter other) { // FAIL-FAST: Check that the user-provided-parameters would not cause exceptions once // the lambda-predicate is invoked. if (other == null) throw new NullPointerException ("The parameter 'other' to URLFilter.or(other) was null."); return (URL url) -> this.test(url) || other.test(url); } /* * This is the standard-java predicate method {@code 'not'}. This method will use a * lambda-expression to create a new {@code URLFilter} that is the "logical-NOT" of the * original test (a.k.a. {@code 'this' Predicate}). * * @return A new Java-{@code Predicate} that performs negates the results of {@code 'this'} * {@code Predicate.} * default URLFilter negate() { return (URL url) -> ! this.test(url); } */ /** * This {@code URLFilter} will KEEP any Image {@code URL's} whose name ends with the standard * image filenames. * * <BR /><BR /><B>WARNING:</B> There are occasions where an Image-{@code URL} is "handled" by * a web-server internally, and the actual {@code URL} itself does not look like an image * file-name at all. This has the inconvenient implication for this (factory-generated) * {@code Predicate} that it might return erroneous results. An actual image file that does * not end with {@code '.jpg'} or {@code '.bmp'} could be rejected, and a {@code URL} that * happens to end with these {@code String's} but is not an image, might also be kept. * * @see StrCmpr#endsWithXOR_CI(String, String[]) */ public static final URLFilter imagesKEEP = (URL url) -> { return StrCmpr.endsWithXOR_CI (url.toString().trim(), ".jpg", ".jpeg", ".gif", ".png", ".bmp"); }; /** * This {@code URLFilter} will REJECT any Image {@code URL's} whose name ends with the * standard image filenames. * * <BR /><BR /><B>WARNING:</B> There are occasions where an Image-{@code URL} is "handled" by * a web-server internally, and the actual {@code URL} itself does not look like an image * file-name at all. This has the inconvenient implication for this (factory-generated) * {@code Predicate} that it might return erroneous results. An actual image file that does * not end with {@code '.jpg'} or {@code '.bmp'} could be kept, and a {@code URL} that happens * to end with these {@code String's} but is not an image, could be rejected. * * @see StrCmpr#endsWithNAND_CI(String, String[]) */ public static final URLFilter imagesREJECT = (URL url) -> { return StrCmpr.endsWithNAND_CI (url.toString().trim(), ".jpg", ".jpeg", ".gif", ".png", ".bmp"); }; /** * This is similar to the java streams function {@code filter(Predicate<>)}. Elements that do * not meet the criteria specified by this (factory-generated) {@code URLFilter} - * <I>specifically, if an element of the input-parameter {@code 'urlList'} would evaluate to * {@code FALSE}</I> - then that element shall be removed from the list. * * @param urls An {@code Iterable} of {@code URL's} which the user would like filtered using * {@code 'this'} filter. * * @return The number of elements that were removed from parameter {@code 'urls'} based on the * results of the {@code URLFilter.test()} of {@code 'this'} instance. */ public default int filter(Iterable<URL> urls) { int removeCount = 0; Iterator<URL> iter = urls.iterator(); // If the filter test returns FALSE, then remove the URL from the collection. // Increment the removeCount Counter. while (iter.hasNext()) if (! test(iter.next())) { removeCount++; iter.remove(); } return removeCount; } /** * This wraps a {@code StrFilter} inside of a {@code URLFilter}. The {@code String}-comparison * that is performed will use the full-path-name of the {@code URL}. * * <BR /><BR /><B><SPAN STYLE="color: red;">StrFilter NOTE:</SPAN></B> The class * {@code 'StrFilter'} can be used in conjunction with the class-specific filters, for * instance, this class {@code 'URLFilter'} * * @param sf This is a {@code String Predicate} that has (usually, but not required) been built * by one of the many {@code String}-Filter Factory-Build static-methods of * {@code class StrFilter.} The {@code Predicate's} that are constructed via the build methods * of {@code StrFilter} call the standard method {@code java.lang.Object.toString()} on the * objects they receive for testing. * * @return FileNodeFilter This will return an instance of a {@code URLFilter} that will test * the {@code url} as a {@code String.} * * @see StrFilter */ public static URLFilter fromStrFilter(StrFilter sf) { if (sf == null) throw new NullPointerException( "The String-Filter Predicate Parameter 'sf' in static-factory builder method " + "'fromStrFilter' was passed a null value." ); return (URL url) -> sf.test(url); } } |