All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.okapi.common.encoder.EncoderManager Maven / Gradle / Ivy

There is a newer version: 1.47.0
Show newest version
/*===========================================================================
  Copyright (C) 2008-2009 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
===========================================================================*/

package net.sf.okapi.common.encoder;

import java.nio.charset.CharsetEncoder;
import java.security.InvalidParameterException;
import java.util.Hashtable;
import java.util.Map.Entry;

import net.sf.okapi.common.IParameters;
import net.sf.okapi.common.MimeTypeMapper;
import net.sf.okapi.common.exceptions.OkapiException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides caching and lookup mechanism for the text encoders used when writing out text
 * processed by a filter.
 */
public class EncoderManager implements IEncoder {

	private final Logger LOGGER = LoggerFactory.getLogger(getClass());
	
	private Hashtable mimeMap; // mimeType to encoder class name map
	private Hashtable encoders; // mimeType to encoder instance map
	private String mimeType = "";
	private IEncoder encoder;
	private String defEncoding;
	private String defLineBreak;
	private IParameters defParams;

	/**
	 * Creates a new encoder manager, with default pre-defined encoder loaded.
	 */
	public EncoderManager () {
		mimeMap = new Hashtable<>();
		encoders = new Hashtable<>();
		// All the filters have their mapping, all mapping should be explicit only
		// Not needed anymore: setAllKnownMappings();
	}

	/**
	 * Sets all mappings known by the core libraries.  
	 */
	public void setAllKnownMappings () {
		// All known mappings
		mimeMap.put(MimeTypeMapper.XML_MIME_TYPE, "net.sf.okapi.common.encoder.XMLEncoder");
		mimeMap.put(MimeTypeMapper.XLIFF_MIME_TYPE, "net.sf.okapi.common.encoder.XMLEncoder");
		mimeMap.put(MimeTypeMapper.XLIFF2_MIME_TYPE, "net.sf.okapi.common.encoder.XMLEncoder");
		mimeMap.put(MimeTypeMapper.ODF_MIME_TYPE, "net.sf.okapi.common.encoder.XMLEncoder");
		mimeMap.put(MimeTypeMapper.PROPERTIES_MIME_TYPE, "net.sf.okapi.common.encoder.PropertiesEncoder");
		mimeMap.put(MimeTypeMapper.HTML_MIME_TYPE, "net.sf.okapi.common.encoder.HtmlEncoder");
		mimeMap.put(MimeTypeMapper.XHTML_MIME_TYPE, "net.sf.okapi.common.encoder.HtmlEncoder");
		mimeMap.put(MimeTypeMapper.PO_MIME_TYPE, "net.sf.okapi.common.encoder.POEncoder");
		mimeMap.put(MimeTypeMapper.DOCX_MIME_TYPE, "net.sf.okapi.common.encoder.OpenXMLEncoder");
		mimeMap.put(MimeTypeMapper.DTD_MIME_TYPE, "net.sf.okapi.common.encoder.DTDEncoder");
		mimeMap.put(MimeTypeMapper.TS_MIME_TYPE, "net.sf.okapi.common.encoder.TSEncoder");		
		mimeMap.put(MimeTypeMapper.PHP_MIME_TYPE, "net.sf.okapi.common.encoder.PHPContentEncoder");		
		mimeMap.put(MimeTypeMapper.TTX_MIME_TYPE, "net.sf.okapi.common.encoder.XMLEncoder");
		mimeMap.put(MimeTypeMapper.JSON_MIME_TYPE, "net.sf.okapi.common.encoder.JSONEncoder");
		mimeMap.put(MimeTypeMapper.REGEX_MIME_TYPE, "net.sf.okapi.common.encoder.RegexEncoder");
		mimeMap.put(MimeTypeMapper.MARKDOWN_MIME_TYPE, "net.sf.okapi.common.encoder.MarkdownEncoder");
	}

	@Override
	public void reset() {
		clearMap();
	}

	/**
	 * Clears all encoders from the manager.
	 */
	public void clearMap () {
		mimeMap.clear();
		encoders.clear();
	}
	
	/**
	 * Sets a mapping in the manager. If a mapping for this MIME type exists already
	 * in the manager, it will be overridden by this new one.
	 * @param mimeType The MIME type identifier for this mapping.
	 * @param className The class name of the encoder to use.
	 */
	public void setMapping (String mimeType,
		String className)
	{
		if (this.mimeType.equals(mimeType)) this.mimeType = "";
		
		mimeMap.put(mimeType, className);
		IEncoder encoder = encoders.get(mimeType);
		if (encoder != null && !className.equals(encoder.getClass().getName())) {
			encoders.remove(mimeType);
		}
	}
	
	public void setMapping (String mimeType, IEncoder encoder) {
		if (encoder == null) {
			throw new InvalidParameterException("encoder cannot be null");
		}
		
		if (this.mimeType.equals(mimeType)) this.mimeType = "";
		
		mimeMap.put(mimeType, encoder.getClass().getName());
		encoders.put(mimeType, encoder);
	}
	
	/**
	 * Removes a given mapping from the manager.
	 * @param mimeType The MIME type identifier of the mapping to remove.
	 */
	public void removeMapping (String mimeType) {
		mimeMap.remove(mimeType);
		encoders.remove(mimeType);
	}
	
	/**
	 * Adds the mappings of a given encoder manager into this manager.
	 * If, for a given MIME type, both encoder manager have a different mapping, the original
	 * mapping of this manager remains unchanged and a warning is generated.
	 * @param otherManager the other encoder manager.
	 */
	public void mergeMappings (EncoderManager otherManager) {
		for ( Entry entry : otherManager.mimeMap.entrySet() ) {
			// Check if the MIME type is already mapped
			if ( mimeMap.containsKey(entry.getKey()) ) {
				if ( !mimeMap.get(entry.getKey()).equals(entry.getValue()) ) {
					// Same MIME type, but different encoder class name:
					// Generate a warning, and keep the current mapping
					LOGGER.warn("The MIME type '{}' is currently mapped to '{}', but conflicts with another mapping ('{}').",
						entry.getKey(), mimeMap.get(entry.getKey()), entry.getValue());
				}
				// Else: Same mapping, nothing to do
			}
			else { // Add the mapping
				setMapping(entry.getKey(), entry.getValue());
			}
		}
		
		for ( Entry entry : otherManager.encoders.entrySet() ) {
			// Check if the MIME type is already mapped
			if ( encoders.containsKey(entry.getKey()) ) {
				if ( !encoders.get(entry.getKey()).equals(entry.getValue()) ) {
					// Same MIME type, but different encoder:
					// Generate a warning, and keep the current mapping
					LOGGER.warn("The MIME type '{}' is currently mapped to '{}', but conflicts with another mapping ('{}').",
						entry.getKey(), mimeMap.get(entry.getKey().getClass().getName()), entry.getValue().getClass().getName());
				}
				// Else: Same mapping, nothing to do
			}
			else { // Add the mapping
				setMapping(entry.getKey(), entry.getValue());
			}
		}
	}
	
	/**
	 * Updates the current cached encoder for this manager.
	 * The method {@link #setDefaultOptions(IParameters, String, String)} must have been called
	 * before calling this method.
	 * @param newMimeType The MIME type identifier for the encoder to use now. If there is no mapping for the
	 * given MIME type, the cache is cleared and no encoder is active.
	 */
	public void updateEncoder (String newMimeType) {
		try {
			if ( newMimeType == null ) return;
			// Check if the current encoder is for the same MIME-type
			if ( mimeType.equals(newMimeType) ) return;
		
			// If not: lookup what encoder to use
			mimeType = newMimeType;
			String name = mimeMap.get(mimeType);
			if ( name == null ) { // Not in the map: Use the default one.
				encoder = new DefaultEncoder();
			}
			else { // Else: Instantiate the encoder based on the class name
				if (encoders.containsKey(mimeType)) {
					encoder = encoders.get(mimeType);
				}
				else {
					encoder = (IEncoder)Class.forName(name).newInstance();
					encoders.put(mimeType, encoder);
				}				
			}
			// And set the options
			encoder.setOptions(defParams, defEncoding, defLineBreak);
		} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
			throw new OkapiException(e);
		}
	}

	/**
	 * Encodes a given text with the encoder currently cached. If no encoder is currently
	 * cached, the text is returned untouched.
	 * @param text The text to encode.
	 * @param context The context of the text: 0=text, 1=skeleton, 2=inline.
	 * @return The encoded text.
	 */
	@Override
	public String encode (String text,
			EncoderContext context)
	{
		if ( encoder != null ) return encoder.encode(text, context);
		else return text;
	}

	/**
	 * Encodes a given character with the encoder currently cached. If no encoder is currently
	 * cached, the character is returned as its string value.
	 * @param value The character to encode.
	 * @param context The context of the character: 0=text, 1=skeleton, 2=inline.
	 * @return The encoded character 9as a string since it can be now made up of
	 * more than one character).
	 */
	@Override
	public String encode (char value,
			EncoderContext context)
	{
		if ( encoder != null ) return encoder.encode(value, context);
		else return String.valueOf(value); 
	}

	/**
	 * Encodes a given code-point with the encoder currently cached. If no encoder is currently
	 * cached, the character is returned as its string value.
	 * @param codePoint The code-point to encode.
	 * @param context The context of the character: 0=text, 1=skeleton, 2=inline.
	 * @return The encoded character 9as a string since it can be now made up of
	 * more than one character).
	 */
	@Override
	public String encode (int codePoint,
			EncoderContext context)
	{
		if ( encoder != null ) return encoder.encode(codePoint, context);
		else {
			if ( Character.isSupplementaryCodePoint(codePoint) ) {
				return new String(Character.toChars(codePoint));
			}
			return String.valueOf((char)codePoint); 
		}
	}

	/**
	 * Gets the encoder currently cached by this manager.
	 * @return The encoder currently cached by this manager, or null if there is none.
	 */
	public IEncoder getEncoder () {
		return encoder;
	}

	/**
	 * Sets the options for the encoder currently cached. If no encoder is currently
	 * cached, the method does nothing.
	 * @param params The parameters object with all the configuration information 
	 * specific to this encoder.
	 * @param encoding The name of the charset encoding to use.
	 * @param lineBreak Type of line-break to use in the output.
	 */
	@Override
	public void setOptions (IParameters params,
		String encoding,
		String lineBreak)
	{
		if ( encoder != null ) {
			encoder.setOptions(params, encoding, lineBreak);
		}
	}

	@Override
	public String toNative (String propertyName,
		String value)
	{
		if ( encoder != null ) {
			return encoder.toNative(propertyName, value);
		}
		// No change if there is no encoder active
		return value;
	}

	/**
	 * Sets the default options for this encoder manager. The values
	 * passed here are set as the values to use for each encoder as they
	 * are invoked.
	 * @param params The default parameter object.
	 * @param encoding The default encoding.
	 * @param lineBreak The string that the encoder will use as a line break.
	 */
	public void setDefaultOptions (IParameters params,
		String encoding,
		String lineBreak)
	{
		defParams = params;
		defEncoding = encoding;
		if ( lineBreak == null ) {
			throw new InvalidParameterException("lineBreak parameter is null");
		}
		defLineBreak = lineBreak;
	}

	@Override
	public String getLineBreak () {
		if ( encoder != null ) {
			return encoder.getLineBreak();
		}
		return this.defLineBreak;
	}

	@Override
	public CharsetEncoder getCharsetEncoder () {
		if ( encoder != null ) {
			return encoder.getCharsetEncoder();
		}
		return null;
	}

	public final Hashtable getMimeMap() {
		return mimeMap;
	}

	public final Hashtable getEncoders() {
		return encoders;
	}

	public final String getMimeType() {
		return mimeType;
	}

	@Override
    public final String getEncoding() {
		return defEncoding;
	}

	public final String getDefLineBreak() {
		return defLineBreak;
	}

	@Override
	public IParameters getParameters() {
		return defParams;
	}

	/////////////////////////////////////
	// For serialization only
	////////////////////////////////////
	
	protected String getDefEncoding() {
		return defEncoding;
	}

	protected void setDefEncoding(String defEncoding) {
		this.defEncoding = defEncoding;
	}

	protected IParameters getDefParams() {
		return defParams;
	}

	protected void setDefParams(IParameters defParams) {
		this.defParams = defParams;
	}

	protected void setMimeMap(Hashtable mimeMap) {
		this.mimeMap = mimeMap;
	}

	protected void setEncoders(Hashtable encoders) {
		this.encoders = encoders;
	}

	protected void setMimeType(String mimeType) {
		this.mimeType = mimeType;
	}

	protected void setEncoder(IEncoder encoder) {
		this.encoder = encoder;
	}

	protected void setDefLineBreak(String defLineBreak) {
		this.defLineBreak = defLineBreak;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy