001: // LanguageTag.java
002: // $Id: LanguageTag.java,v 1.3 2000/08/16 21:38:01 ylafon Exp $
003: // (c) COPYRIGHT MIT, INRIA and Keio, 1999
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.www.mime;
007:
008: import java.io.Serializable;
009:
010: /**
011: * This class is used to represent parsed Language tags,
012: * It creates a representation from a string based representation
013: * of the Language tag, as defined in RFC 1766
014: * NOTE, we don't check that languages are defined according to ISO 639
015: */
016:
017: public class LanguageTag implements Serializable, Cloneable {
018: public static int NO_MATCH = -1;
019: public static int MATCH_LANGUAGE = 1;
020: public static int MATCH_SPECIFIC_LANGUAGE = 2;
021: // subtag is not dialect as subtype can be
022: // dialect or country identification or script variation, etc...
023: public static int MATCH_SUBTAG = 3;
024: public static int MATCH_SPECIFIC_SUBTAG = 4;
025:
026: /**
027: * String representation of the language
028: *
029: * @serial
030: */
031: protected String language = null;
032: /**
033: * String representation of subtag
034: *
035: * @serial
036: */
037: protected String subtag = null;
038:
039: /**
040: * external form of this language tag
041: *
042: * @serial
043: */
044: protected String external = null;
045:
046: /**
047: * How good the given LanguageTag matches the receiver of the method ?
048: * This method returns a matching level among:
049: * <dl>
050: * <dt>NO_MATCH<dd>Language not matching,</dd>
051: * <dt>MATCH_LANGUAGE<dd>Languages match roughly (with *),</dd>
052: * <dt>MATCH_SPECIFIC_LANGUAGE<dd>Languages match exactly,</dd>
053: * <dt>MATCH_SUBTAG<dd>Languages match, subtags matches roughly</dd>
054: * <dt>MATCH_SPECIFIC_SUBAG<dd>Languages match, subtag matches exactly</dd>
055: * </dl>
056: * The matches are ranked from worst match to best match, a simple
057: * Max ( match[i], matched) will give the best match.
058: * @param other The other LanguageTag to match against ourself.
059: */
060:
061: public int match(LanguageTag other) {
062: int match = NO_MATCH;
063: // match types:
064: if (language.equals("*") || other.language.equals("*")) {
065: match = MATCH_LANGUAGE;
066: } else if (!language.equalsIgnoreCase(other.language)) {
067: return NO_MATCH;
068: } else {
069: match = MATCH_SPECIFIC_LANGUAGE;
070: }
071: // match subtypes:
072: if ((subtag == null) || (other.subtag == null))
073: return match;
074: if (subtag.equals("*") || other.subtag.equals("*")) {
075: match = MATCH_SUBTAG;
076: } else if (!subtag.equalsIgnoreCase(other.subtag)) {
077: return NO_MATCH;
078: } else {
079: match = MATCH_SPECIFIC_SUBTAG;
080: }
081: return match;
082: }
083:
084: /**
085: * A printable representation of this LanguageTag.
086: * The printed representation is guaranteed to be parseable by the
087: * String constructor.
088: */
089:
090: public String toString() {
091: if (external == null) {
092: if (subtag != null) {
093: external = language + "-" + subtag;
094: } else {
095: external = language;
096: }
097: }
098: return external;
099: }
100:
101: /**
102: * Get the language
103: * @return The language, encoded as a String.
104: */
105:
106: public String getLanguage() {
107: return language;
108: }
109:
110: /**
111: * Get the subtag
112: * @return The subtag, encoded as a string
113: */
114:
115: public String getSubtag() {
116: return language;
117: }
118:
119: /**
120: * Construct a Language tag from a spec
121: * @parameter spec, A string representing a LangateTag
122: */
123: public LanguageTag(String spec) {
124: int strl = spec.length();
125: int start = 0, look = -1;
126: // skip leading/trailing blanks:
127: while ((start < strl) && (spec.charAt(start)) <= ' ')
128: start++;
129: while ((strl > start) && (spec.charAt(strl - 1) <= ' '))
130: strl--;
131: // get the type:
132: StringBuffer sb = new StringBuffer();
133: while ((start < strl) && ((look = spec.charAt(start)) != '-')
134: && ((look = spec.charAt(start)) != ';')) {
135: sb.append((char) look);
136: start++;
137: }
138: this .language = sb.toString();
139: if (look == '-') {
140: start++;
141: sb.setLength(0);
142: while ((start < strl)
143: && ((look = spec.charAt(start)) > ' ')
144: && (look != ';')) {
145: sb.append((char) look);
146: start++;
147: }
148: this .subtag = sb.toString();
149: }
150: }
151:
152: /**
153: * construct directly a language tag
154: * it NEEDS both language and subtype parameters
155: */
156:
157: public LanguageTag(String language, String subtag) {
158: this.language = language;
159: this.subtag = subtag;
160: }
161: }
|