Java tutorial
/* Copyright (C) 2013-2014 Ian Teune <ian.teune@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.tinspx.util.io.charset; import static com.google.common.base.Preconditions.*; import com.google.common.base.Predicates; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import com.tinspx.util.base.BasicError; import com.tinspx.util.base.Errors; import com.tinspx.util.collect.Predicated; import com.tinspx.util.io.ErrorIOException; import java.io.IOException; import java.util.List; import javax.annotation.Nullable; import lombok.ToString; /** * Set the detected {@code Charset} through {@link #onCharset(String)}. Report * any errors through {@link #onError(BasicError)}. {@link #failIfNotDetected()} * will cause the future to fail if no {@code Charset} has been detected. * * @see AbstractContentCharDet * @see AbstractHeaderCharDet * @author Ian */ @ToString(callSuper = true, of = { "detected", "complete" }) public abstract class AbstractCharDet implements CharsetDetector, BasicError.Listener { protected final SettableFuture<String> future = SettableFuture.create(); /** * true when a {@code Charset} has been detected */ protected boolean detected; /** * true when a {@code Charset} has been detected or detection has failed */ protected boolean complete; private final List<BasicError> errors = Lists.newCopyOnWriteArrayList(); @Override public ListenableFuture<String> charsetFuture() { return future; } /** * if no {@code Charset} has been detected, sets an {@code IOException} on * {@link #future} with all errors reported through * {@link #onError(com.tinspx.util.base.BasicError)}. */ protected void failIfNotDetected() { if (!complete) { final String msg = "charset detection failed"; if (errors != null) { future.setException(new ErrorIOException(msg, errors)); } else { future.setException(new IOException(msg)); } complete = true; } } /** * subclasses should call this method once a {@code Charset} has been * successfully detected * * @param charset non-null detected {@code Charset} */ protected void onCharset(String charset) { if (future.set(checkNotNull(charset))) { detected = true; } complete = true; } /** * Determines is {@code name} is a valid {@code Charset} name. A valid name * is neither null nor empty. */ @SuppressWarnings("null") protected boolean isValidName(@Nullable String name) { return !Strings.isNullOrEmpty(name) && !name.trim().isEmpty(); } /** * Sets the {@code Charset} to {@code name} if it is a valid {@code Charset} * same. Returns {@code true} if {@code name} was valid and the * {@code Charset} was set. */ @SuppressWarnings("null") protected boolean setIfValid(@Nullable String name) { if (!Strings.isNullOrEmpty(name) && !(name = name.trim()).isEmpty()) { onCharset(name); return true; } return false; } /** * Sets the {@code Charset} from the first valid name in * {@code charsetNames}. A valid name is not null and not empty. Returns * {@code true} if the {@code Charset} was found and set. */ protected boolean setFirstValid(@Nullable Iterable<String> charsetNames) { if (charsetNames != null) { String name = null; for (String n : charsetNames) { if (!Strings.isNullOrEmpty(n) && !(n = n.trim()).isEmpty()) { name = n; break; } } if (name != null) { onCharset(name); return true; } } return false; } @Override public void onError(BasicError error) { if (error == null) { error = Errors.message("null error"); } errors.add(error); } public List<BasicError> errors() { return Predicated.list(errors, Predicates.notNull()); } }