blob: 89eb34beb736f6ca16821f9727f2923e380db7ae [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*
* CharsetMapping.java
*
* Created on December 10, 2003, 3:22 PM
*/
package org.netbeans.modules.j2ee.sun.share;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.SortedMap;
import java.util.TreeMap;
import java.text.MessageFormat;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import org.openide.util.NbBundle;
/** Object for nice usage of Charsets in comboboxes, sorted lists, etc.
* Provides same equality properties as Charset (but with CharsetMapping)
* but a better "display name" via toString().
*
* There are also several static utility methods for finding and creating
* Charset and CharsetMappings.
*
* @author Peter Williams
*/
public class CharsetMapping implements Comparable {
private final ResourceBundle bundle = NbBundle.getBundle(
"org.netbeans.modules.j2ee.sun.share.Bundle"); // NOI18N
private Charset charset;
private String chosenAlias;
private boolean showAliases;
private String displayText;
private boolean textOutOfDate;
/** Create a mapping for a charset
*
* @param c The charset for this mapping
*/
public CharsetMapping(final Charset c) {
this(c, c.displayName(), true);
}
/** Create a mapping for a charset with the obtion to turn on or off display
* of aliases next to the the charset canonical name.
*
* @param c The charset for this mapping
* @param sa
*/
public CharsetMapping(final Charset c, boolean sa) {
this(c, c.displayName(), sa);
}
/** Create a mapping for a charset alias
*
* @param c The charset for this mapping
* @param alias The particular alias represented by this mapping
*/
public CharsetMapping(final Charset c, String alias) {
this(c, alias, false);
}
private CharsetMapping(final Charset c, String alias, boolean sa) {
charset = c;
chosenAlias = alias;
showAliases = sa;
displayText = buildDisplayText();
}
/** equals() maps to Charset.equals()
*
* @return true/false based on whether the embedded charset objects compare
* as equal.
*/
public boolean equals(Object o) {
boolean result = false;
if(o instanceof CharsetMapping) {
CharsetMapping cm = (CharsetMapping) o;
result = chosenAlias.equals(cm.getAlias());
}
return result;
}
/** hashCode() maps to Charset.hashCode()
*
* @return the hashcode
*/
public int hashCode() {
return charset.hashCode();
}
/** A more readable display string. If the mappings are for canonical charsets
* only and "showAliases" is true, then the string will include a bracketed
* display of all aliases for this charset after showing the canonical name.
*
* @return A descriptive string
*/
public String toString() {
if(textOutOfDate) {
displayText = buildDisplayText();
}
return displayText;
}
/** The charset
*
* @return the charset this is a mapping for
*/
public Charset getCharset() {
return charset;
}
/** The alias string. If this is a canonical map, will return canonical string.
*
* @return the charset alias this is a mapping for
*/
public String getAlias() {
return chosenAlias;
}
/** Force the display text to be recalculated. Recalculation won't happen
* until next time text is requested.
*/
public void updateDisplayText() {
textOutOfDate = true;
}
private String buildDisplayText() {
String result = chosenAlias;
if(showAliases) {
StringBuffer aliasList = new StringBuffer(200);
for(Iterator iter = charset.aliases().iterator(); iter.hasNext(); ) {
aliasList.append((String) iter.next());
if(iter.hasNext()) {
aliasList.append(", "); // NOI18N
}
}
Object [] args = new Object [] { chosenAlias, aliasList.toString() };
result = MessageFormat.format(
bundle.getString("LBL_CharsetComboBoxDisplayText"), args); // NOI18N
}
if(result == null || result.length() == 0) {
result = bundle.getString("LBL_UnnamedCharset"); // NOI18N
}
textOutOfDate = false;
return result;
}
/** For sorted collections. We compare the alias representations of the
* embedded charset.
*
* @param obj the Charset to compare to
* @return result of comparison (negative, 0, or positive depending on match)
*/
public int compareTo(Object obj) {
int result = -1;
if(obj instanceof CharsetMapping) {
// !PW FIXME This is different than equals. Why?
// -- To properly sort charsets by alias, we need this implementation
// like this. But how do we reconcile this with the way equals
// works?
//
CharsetMapping targetMapping = (CharsetMapping) obj;
result = chosenAlias.compareTo(targetMapping.getAlias());
}
return result;
}
private static boolean useAliases = false;
private static SortedMap sortedCanonicalCharsetMappings = null;
private static SortedMap getSortedCanonicalCharsetMappings() {
if(sortedCanonicalCharsetMappings == null) {
SortedMap charsets = Charset.availableCharsets();
sortedCanonicalCharsetMappings = new TreeMap();
for(Iterator iter = charsets.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry) iter.next();
CharsetMapping mapping = new CharsetMapping((Charset) entry.getValue());
sortedCanonicalCharsetMappings.put(mapping.getAlias(), mapping);
}
}
return sortedCanonicalCharsetMappings;
}
private static SortedMap sortedAliasCharsetMappings = null;
private static SortedMap getSortedAliasCharsetMappings() {
if(sortedAliasCharsetMappings == null) {
SortedMap charsets = Charset.availableCharsets();
sortedAliasCharsetMappings = new TreeMap();
for(Iterator iter = charsets.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry) iter.next();
Charset charset = (Charset) entry.getValue();
CharsetMapping mapping = new CharsetMapping(charset, false);
sortedAliasCharsetMappings.put(mapping.getAlias(), mapping);
for(Iterator aliasIter = charset.aliases().iterator(); aliasIter.hasNext(); ) {
String alias = (String) aliasIter.next();
CharsetMapping aliasMapping = new CharsetMapping(charset, alias);
sortedAliasCharsetMappings.put(alias, aliasMapping);
}
}
}
return sortedAliasCharsetMappings;
}
/** Return a sorted map containg mappings for all charsets supported by the
* current JVM. Depending on the value of the global alias flag, the map
* will contain Charsets indexed by canonical name only, or also indexed
* by alias.
*
* @return SortedMap containing CharsetMapping objects
*/
public static SortedMap getSortedAvailableCharsetMappings() {
SortedMap result;
if(useAliases) {
if(sortedAliasCharsetMappings == null){
sortedAliasCharsetMappings = getSortedAliasCharsetMappings();
}
result = sortedAliasCharsetMappings;
} else {
if(sortedCanonicalCharsetMappings == null){
sortedCanonicalCharsetMappings = getSortedCanonicalCharsetMappings();
}
result = sortedCanonicalCharsetMappings;
}
return result;
}
/** Retrieve the CharsetMapping object matching this charset.
*
* @param c Charset to search for.
* @return CharsetMapping matching the passed in charset. Null if not found.
*/
public static CharsetMapping getCharsetMapping(Charset c) {
return (CharsetMapping) getSortedAvailableCharsetMappings().get(c.name());
}
/** Retrieve the CharsetMapping object matching this name.
*
* @param name Charset name to search for.
* @return CharsetMapping matching the passed in name. Null if not found.
*/
public static CharsetMapping getCharsetMapping(String name) {
CharsetMapping result = null;
if(name != null) {
try {
Charset charset = Charset.forName(name);
if(charset != null) {
result = (CharsetMapping) getSortedAvailableCharsetMappings().get(charset.name());
}
} catch(Exception ex) {
// FIXME handle this one better: Unrecognized or otherwise illegal charset specified.
}
}
return result;
}
/*
public static class CharsetComparator implements Comparator {
public int compare(Object o1, Object o2) {
int result = -1;
if(o1 instanceof Charset && o2 instanceof Charset) {
Charset s1 = (Charset) o1;
Charset s2 = (Charset) o2;
result = s1.compareTo(s2);
}
return result;
}
}
*/
/** -----------------------------------------------------------------------
* property storage and notification of the user option.
*/
public static final String CHARSET_DISPLAY_TYPE = "CharsetDisplayType";
public static final Integer CHARSET_CANONICAL = new Integer(0);
public static final Integer CHARSET_ALIAS_ASIDE = new Integer(1);
public static final Integer CHARSET_ALIAS_SELECTION = new Integer(2);
private static Integer displayOption = CHARSET_ALIAS_ASIDE;
private static java.beans.PropertyChangeSupport propSupport = new PropertyChangeSupport(CharsetMapping.class);;
public static void addPropertyChangeListener(PropertyChangeListener listener) {
propSupport.addPropertyChangeListener(listener);
}
public static void removePropertyChangeListener(PropertyChangeListener listener) {
propSupport.removePropertyChangeListener(listener);
}
public static void setDisplayOption(Integer option) {
Integer newDisplayOption = getDisplayOptionEnum(option);
if(newDisplayOption != null && newDisplayOption != displayOption) {
Integer oldDisplayOption = displayOption;
displayOption = newDisplayOption;
updateInternalState();
propSupport.firePropertyChange(CHARSET_DISPLAY_TYPE, oldDisplayOption, displayOption);
}
}
private static void updateInternalState() {
if(displayOption == CHARSET_CANONICAL) {
useAliases = false;
if(sortedCanonicalCharsetMappings == null){
sortedCanonicalCharsetMappings = getSortedCanonicalCharsetMappings();
}
Collection mappings = sortedCanonicalCharsetMappings.values();
for(Iterator iter = mappings.iterator(); iter.hasNext(); ) {
CharsetMapping mapping = (CharsetMapping) iter.next();
mapping.showAliases = false;
mapping.updateDisplayText();
}
} else if(displayOption == CHARSET_ALIAS_ASIDE) {
useAliases = false;
if(sortedCanonicalCharsetMappings == null){
sortedCanonicalCharsetMappings = getSortedCanonicalCharsetMappings();
}
Collection mappings = sortedCanonicalCharsetMappings.values();
for(Iterator iter = mappings.iterator(); iter.hasNext(); ) {
CharsetMapping mapping = (CharsetMapping) iter.next();
mapping.showAliases = true;
mapping.updateDisplayText();
}
} else if(displayOption == CHARSET_ALIAS_SELECTION) {
useAliases = true;
}
}
public static Integer getDisplayOption() {
return displayOption;
}
private static Integer getDisplayOptionEnum(Integer option) {
Integer result = null;
if(option != null) {
if(CHARSET_CANONICAL.compareTo(option) == 0) {
result = CHARSET_CANONICAL;
} else if(CHARSET_ALIAS_ASIDE.compareTo(option) == 0) {
result = CHARSET_ALIAS_ASIDE;
} else if(CHARSET_ALIAS_SELECTION.compareTo(option) == 0) {
result = CHARSET_ALIAS_SELECTION;
}
}
return result;
}
}