Package org.apache.abdera.i18n.rfc4646

Source Code of org.apache.abdera.i18n.rfc4646.Subtag

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  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.  For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.abdera.i18n.rfc4646;

import java.io.Serializable;
import java.util.Locale;

import org.apache.abdera.i18n.rfc4646.enums.Extlang;
import org.apache.abdera.i18n.rfc4646.enums.Language;
import org.apache.abdera.i18n.rfc4646.enums.Region;
import org.apache.abdera.i18n.rfc4646.enums.Script;
import org.apache.abdera.i18n.rfc4646.enums.Singleton;
import org.apache.abdera.i18n.rfc4646.enums.Variant;

/**
* A Lang tag subtag
*/
public final class Subtag
  implements Serializable,
             Cloneable,
             Comparable<Subtag> {

  private static final long serialVersionUID = -4496128268514329138L;

  public enum Type {
    /** Primary language subtag **/  PRIMARY,
    /** Extended Language subtag **/ EXTLANG,
    /** Script subtag **/            SCRIPT,
    /** Region subtag **/            REGION,
    /** Variant subtag **/           VARIANT,
    /** Singleton subtag **/         SINGLETON,
    /** Extension subtag **/         EXTENSION,
    /** Primary-use subtag **/       PRIVATEUSE,
    /** Grandfathered subtag **/     GRANDFATHERED,
    /** Wildcard subtag ("*") **/    WILDCARD,
    /** Simple subtag (ranges) **/   SIMPLE
  }
 
  private final Type type;
  private final String name;
  private Subtag prev;
  private Subtag next;
 
  /**
   * Create a Subtag
   */
  public Subtag(Language language) {
    this(Type.PRIMARY, language.name().toLowerCase(Locale.US));
  }
 
  /**
   * Create a Subtag
   */
  public Subtag(Script script) {
    this(Type.SCRIPT, toTitleCase(script.name()));
  }
 
  /**
   * Create a Subtag
   */
  public Subtag(Region region) {
    this(Type.REGION, getRegionName(region.name()));
  }
 
  private static String getRegionName(String name) {
    return name.startsWith("UN") && name.length() == 5 ?
      name.substring(2) : name;
  }
 
  /**
   * Create a Subtag
   */
  public Subtag(Variant variant) {
    this(Type.VARIANT, getVariantName(variant.name().toLowerCase(Locale.US)));
  }
 
  private static String getVariantName(String name) {
    return name.startsWith("_") ?
      name.substring(1) : name;
  }
 
  /**
   * Create a Subtag
   */
  public Subtag(Extlang extlang) {
    this(Type.EXTLANG, extlang.name().toLowerCase(Locale.US));
  }
 
  /**
   * Create a Subtag
   */
  public Subtag(Singleton singleton) {
    this(Type.SINGLETON, singleton.name().toLowerCase(Locale.US));
  }
 
  /**
   * Create a Subtag
   */
  public Subtag(Type type, String name) {
    this(type,name,null);
  }
 
  Subtag() {
    this(Type.WILDCARD,"*");
  }
 
  /**
   * Create a Subtag
   */
  public Subtag(
    Type type,
    String name,
    Subtag prev) {
      this.type = type;
      this.name = name;
      this.prev = prev;
      if (prev != null)
        prev.setNext(this);
  }

  Subtag(
      Type type,
      String name,
      Subtag prev,
      Subtag next) {
        this.type = type;
        this.name = name;
        this.prev = prev;
        this.next = next;
    }
 
  /**
   * Get the subtag type
   */
  public Type getType() {
    return type;
  }
 
  /**
   * Get the subtag value
   */
  public String getName() {
    return toString();
  }
 
  void setPrevious(Subtag prev) {
    this.prev = prev;
  }
 
  /**
   * Get the previous subtag
   */
  public Subtag getPrevious() {
    return prev;
  }
 
  void setNext(Subtag next) {
    this.next = next;
    if (next != null) next.setPrevious(this);
  }
 
  /**
   * Get the next subtag
   */
  public Subtag getNext() {
    return next;
  }
 
  public String toString() {
    switch(type) {
      case PRIMARY: return name.toLowerCase(Locale.US);
      case REGION: return name.toUpperCase(Locale.US);
      case SCRIPT: return toTitleCase(name);
      default: return name.toLowerCase(Locale.US);
    }
  }
 
  private static String toTitleCase(String string) {
    if (string == null) return null;
    if (string.length() == 0) return string;
    char[] chars = string.toLowerCase(Locale.US).toCharArray();
    chars[0] = (char)(chars[0] - 32);
    return new String(chars);
  }

  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.toLowerCase(Locale.US).hashCode());
    result = prime * result + ((type == null) ? 0 : type.hashCode());
    return result;
  }

  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    final Subtag other = (Subtag) obj;
    if (other.getType() == Type.WILDCARD ||
        getType() == Type.WILDCARD)
      return true;
    if (name == null) {
      if (other.name != null) return false;
    } else if (!name.equalsIgnoreCase(other.name)) return false;
    if (other.getType() == Type.SIMPLE ||
        getType() == Type.SIMPLE)
      return true;
    if (type == null) {
      if (other.type != null) return false;
    } else if (!type.equals(other.type)) return false;
    return true;
  }
 
  public Subtag clone() {
    try {
      Subtag tag = (Subtag) super.clone();
      if (getNext() != null)
        tag.setNext(getNext().clone());
      return tag;
    } catch (CloneNotSupportedException e) {
      return new Subtag(
        type,
        name,
        prev!=null?prev.clone():null,
        next!=null?next.clone():null); // not going to happen
    }
  }

  /**
   * True if this subtag has been deprecated
   */
  public boolean isDeprecated() {
    switch(type) {
      case PRIMARY:
        Language e = getEnum();
        return e.isDeprecated();
      }
      case SCRIPT: {
        Script e = getEnum();
        return e.isDeprecated();
      }
      case REGION: {
        Region e = getEnum();
        return e.isDeprecated();
      }
      case VARIANT: {
        Variant e = getEnum();
        return e.isDeprecated();
      }
      case EXTLANG: {
        Extlang e = getEnum();
        return e.isDeprecated();
      }
      case EXTENSION: {
        Singleton e = getEnum();
        return e.isDeprecated();
      }
      default: return false;
    }
  }
 
  /**
   * Get this subtags Enum, allowing the subtag to be verified
   */
  @SuppressWarnings("unchecked")
  public <T extends Enum<?>>T getEnum() {
    switch (type) {
      case PRIMARY: return (T)Language.valueOf(this);
      case SCRIPT: return (T)Script.valueOf(this);
      case REGION: return (T)Region.valueOf(this);
      case VARIANT: return (T)Variant.valueOf(this);
      case EXTLANG: return (T)Extlang.valueOf(this);
      case EXTENSION: return (T)Singleton.valueOf(this);
      default: return null;
    }
  }
 
  /**
   * True if this subtag is valid
   */
  public boolean isValid() {
    switch (type) {
      case PRIMARY:
      case SCRIPT:
      case REGION:
      case VARIANT:
      case EXTLANG:
        try {
          getEnum();
          return true;
        } catch (Exception e) {
          return false;
        }
      case EXTENSION:
        return name.matches("[A-Za-z0-9]{2,8}");
      case GRANDFATHERED:
        return name.matches("[A-Za-z]{1,3}(?:-[A-Za-z0-9]{2,8}){1,2}");
      case PRIVATEUSE:
        return name.matches("[A-Za-z0-9]{1,8}");
      case SINGLETON:
        return name.matches("[A-Za-z]");
      case WILDCARD:
        return name.equals("*");
      case SIMPLE:
        return name.matches("[A-Za-z0-9]{1,8}");
      default: return false;
    }
  }
 
  /**
   * Return the canonicalized version of this subtag
   */
  public Subtag canonicalize() {
    switch(type) {
      case REGION:
        Region region = getEnum();
        return region.getPreferred().newSubtag();
      case PRIMARY:
        Language language = getEnum();
        return language.getPreferred().newSubtag();
      case SCRIPT:
        Script script = getEnum();
        return script.getPreferred().newSubtag();
      case VARIANT:
        Variant variant = getEnum();
        return variant.getPreferred().newSubtag();
      case EXTLANG:
        Extlang extlang = getEnum();
        return extlang.getPreferred().newSubtag();
      case EXTENSION:
      case GRANDFATHERED:
      case PRIVATEUSE:
      case SINGLETON:
      default: return this;
    }
  }

  /**
   * Create a new wildcard subtag
   */
  public static Subtag newWildcard() {
    return new Subtag();
  }

  public int compareTo(Subtag o) {
    int c = o.type.compareTo(type);
    return c != 0 ? c : o.name.compareTo(name);
  }
}
TOP

Related Classes of org.apache.abdera.i18n.rfc4646.Subtag

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.