GuessEncodingEncoder.java
package fr.sii.ogham.sms.sender.impl.cloudhopper.encoder;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.sii.ogham.sms.encoder.Encoded;
import fr.sii.ogham.sms.encoder.Encoder;
import fr.sii.ogham.sms.encoder.SupportingEncoder;
import fr.sii.ogham.sms.exception.message.EncodingException;
import fr.sii.ogham.sms.sender.impl.cloudhopper.exception.GuessEncodingException;
/**
* Automatically determine best {@link Encoder} to use for encoding the message.
*
* <p>
* The guessing is really simple:
* <ol>
* <li>The first {@link Encoder} is tested to check if message can be encoded
* with that encoder:
* <ul>
* <li>If the {@link Encoder} implements {@link SupportingEncoder}, the
* {@link SupportingEncoder#canEncode(String)} is called to check if the
* {@link Encoder} is able to encode the message. If false is returned, the
* {@link Encoder} is skipped (not executed).</li>
* <li>If the {@link Encoder} doesn't implement {@link SupportingEncoder}, the
* {@link Encoder} is executed. The {@link Encoder} may throw an
* {@link EncodingException} if it can't encode correctly the message. If that
* exception is raised, it is caught and the {@link Encoder} is skipped.</li>
* <li>If the {@link Encoder} is not skipped (it could encode the message
* correctly), its result is directly returned.</li>
* </ul>
* <li>The next {@link Encoder} is tested and so on until one {@link Encoder}
* returns the encoded message</li>
* </ol>
*
* <p>
* If none of the possible encoders could encode the message, the
* {@link GuessEncodingException} is raised.
*
*
* @author Aurélien Baudet
*
*/
public class GuessEncodingEncoder implements SupportingEncoder {
private static final Logger LOG = LoggerFactory.getLogger(GuessEncodingEncoder.class);
private final List<Encoder> possibleEncoders;
/**
* Initializes with the list of possible encoders to test. If an encoder
* implements {@link SupportingEncoder}, the
* {@link SupportingEncoder#canEncode(String)} is used to check if the text
* message can be encoded using that {@link Encoder}. Otherwise, the
* {@link Encoder} is executed to try encoding the message. If the message
* can't be encoded, an {@link EncodingException} is raised. The exception
* is caught and the next {@link Encoder} is executed.
*
* @param possibleEncoders
* the possible encoders used to encode the message
*/
public GuessEncodingEncoder(List<Encoder> possibleEncoders) {
super();
this.possibleEncoders = possibleEncoders;
}
@Override
public boolean canEncode(String message) {
for (Encoder encoder : possibleEncoders) {
if (canEncode(encoder, message)) {
return true;
}
}
return false;
}
@Override
public Encoded encode(String message) throws EncodingException {
for (Encoder encoder : possibleEncoders) {
if (!canEncode(encoder, message)) {
continue;
}
try {
return encoder.encode(message);
} catch (EncodingException e) {
LOG.debug("Encoder failed to encode => try next one", e);
}
}
throw new GuessEncodingException("Failed to guess encoding for message", message);
}
private static boolean canEncode(Encoder encoder, String message) {
if (encoder instanceof SupportingEncoder) {
return ((SupportingEncoder) encoder).canEncode(message);
}
return true;
}
}