/* StyleContext.java --
   Copyright (C) 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.text;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;

public class StyleContext 
  implements Serializable, AbstractDocument.AttributeContext
{
  /** The serialization UID (compatible with JDK1.5). */
  private static final long serialVersionUID = 8042858831190784241L;

  public class NamedStyle
    implements Serializable, Style
  {
    /** The serialization UID (compatible with JDK1.5). */
    private static final long serialVersionUID = -6690628971806226374L;

    protected transient ChangeEvent changeEvent;
    protected EventListenerList listenerList;
      
    private transient AttributeSet attributes;

    public NamedStyle()
    {
      this(null, null);
    }

    public NamedStyle(Style parent)
    {
      this(null, parent);
    }

    public NamedStyle(String name, Style parent)
    {
      attributes = getEmptySet();
      listenerList = new EventListenerList();
      if (name != null)
        setName(name);
      if (parent != null)
        setResolveParent(parent);
    }

    public String getName()
    {
      String name = null;
      if (isDefined(StyleConstants.NameAttribute))
        name = getAttribute(StyleConstants.NameAttribute).toString();
      return name;
    }

    public void setName(String n)
    {
      if (n != null)
        addAttribute(StyleConstants.NameAttribute, n);
    }

    public void addChangeListener(ChangeListener l)
    {
      listenerList.add(ChangeListener.class, l);
    }
      
    public void removeChangeListener(ChangeListener l)
    {
      listenerList.remove(ChangeListener.class, l);
    }
      
    public <T extends EventListener> T[] getListeners(Class<T> listenerType)
    {
      return listenerList.getListeners(listenerType);
    }

    public ChangeListener[] getChangeListeners()
    {
      return (ChangeListener[]) getListeners(ChangeListener.class);
    }

    protected  void fireStateChanged()
    {
      ChangeListener[] listeners = getChangeListeners();
      for (int i = 0; i < listeners.length; ++i)
        {
          // Lazily create event.
          if (changeEvent == null)
            changeEvent = new ChangeEvent(this);
          listeners[i].stateChanged(changeEvent);
        }
    }

    public void addAttribute(Object name, Object value)
    {
      attributes = StyleContext.this.addAttribute(attributes, name, value);
      fireStateChanged();
    }

    public void addAttributes(AttributeSet attr)
    {
      attributes = StyleContext.this.addAttributes(attributes, attr);
      fireStateChanged();
    }

    public boolean containsAttribute(Object name, Object value)
    {
      return attributes.containsAttribute(name, value);
    }
      
    public boolean containsAttributes(AttributeSet attrs)
    {
      return attributes.containsAttributes(attrs);
    }

    public AttributeSet copyAttributes()
    {
      // The RI returns a NamedStyle as copy, so do we.
      NamedStyle copy = new NamedStyle();
      copy.attributes = attributes.copyAttributes();
      return copy;
    }
            
    public Object getAttribute(Object attrName)
    {
      return attributes.getAttribute(attrName);
    }

    public int getAttributeCount()
    {
      return attributes.getAttributeCount();
    }

    public Enumeration<?> getAttributeNames()
    {
      return attributes.getAttributeNames();
    }
      
    public boolean isDefined(Object attrName)
    {
      return attributes.isDefined(attrName);        
    }

    public boolean isEqual(AttributeSet attr)
    {
      return attributes.isEqual(attr);
    }

    public void removeAttribute(Object name)
    {
      attributes = StyleContext.this.removeAttribute(attributes, name);
      fireStateChanged();
    }

    public void removeAttributes(AttributeSet attrs)
    {
      attributes = StyleContext.this.removeAttributes(attributes, attrs);
      fireStateChanged();
    }

    public void removeAttributes(Enumeration<?> names)
    {
      attributes = StyleContext.this.removeAttributes(attributes, names);
      fireStateChanged();
    }


    public AttributeSet getResolveParent()
    {
      return attributes.getResolveParent();        
    }

    public void setResolveParent(AttributeSet parent)
    {
      if (parent != null)
        addAttribute(StyleConstants.ResolveAttribute, parent);
      else
        removeAttribute(StyleConstants.ResolveAttribute);
    }
      
    public String toString()
    {
      return "NamedStyle:" + getName() + " " + attributes;
    }

    private void writeObject(ObjectOutputStream s)
      throws IOException
    {
      s.defaultWriteObject();
      writeAttributeSet(s, attributes);
    }

    private void readObject(ObjectInputStream s)
      throws ClassNotFoundException, IOException
    {
      s.defaultReadObject();
      attributes = SimpleAttributeSet.EMPTY;
      readAttributeSet(s, this);
    }
  }
  
  public class SmallAttributeSet
    implements AttributeSet
  {
    final Object [] attrs;
    private AttributeSet resolveParent;
    public SmallAttributeSet(AttributeSet a)
    {
      int n = a.getAttributeCount();
      int i = 0;
      attrs = new Object[n * 2];
      Enumeration e = a.getAttributeNames();
      while (e.hasMoreElements())
        {
          Object name = e.nextElement();
          Object value = a.getAttribute(name);
          if (name == ResolveAttribute)
            resolveParent = (AttributeSet) value;
          attrs[i++] = name;
          attrs[i++] = value;
        }
    }

    public SmallAttributeSet(Object [] a)
    {
      attrs = a;
      for (int i = 0; i < attrs.length; i += 2)
        {
          if (attrs[i] == ResolveAttribute)
            resolveParent = (AttributeSet) attrs[i + 1];
        }
    }

    public Object clone()
    {
      return this;
    }

    public boolean containsAttribute(Object name, Object value)
    {
      return value.equals(getAttribute(name));
    }

    public boolean containsAttributes(AttributeSet a)
    {
      boolean res = true;
      Enumeration e = a.getAttributeNames();
      while (e.hasMoreElements() && res)
        {
          Object name = e.nextElement();
          res = a.getAttribute(name).equals(getAttribute(name));
        }
      return res;
    }

    public AttributeSet copyAttributes()
    {
      return this;
    }

    public boolean equals(Object obj)
    {
      boolean eq = false;
      if (obj instanceof AttributeSet)
        {
          AttributeSet atts = (AttributeSet) obj;
          eq = getAttributeCount() == atts.getAttributeCount()
               && containsAttributes(atts);
        }
      return eq;
    }
 
    public Object getAttribute(Object key)
    {
      Object att = null;
      if (key == StyleConstants.ResolveAttribute)
        att = resolveParent;

      for (int i = 0; i < attrs.length && att == null; i += 2)
        {
          if (attrs[i].equals(key))
            att = attrs[i + 1];
        }

      // Check the resolve parent, unless we're looking for the 
      // ResolveAttribute, which must not be looked up
      if (att == null)
          {
            AttributeSet parent = getResolveParent();
            if (parent != null)
              att = parent.getAttribute(key);
          }
      
      return att;
    }

    public int getAttributeCount()
    {
      return attrs.length / 2;
    }

    public Enumeration<?> getAttributeNames()
    {      
      return new Enumeration() 
        {
          int i = 0;
          public boolean hasMoreElements() 
          { 
            return i < attrs.length; 
          }
          public Object nextElement() 
          { 
            i += 2; 
            return attrs[i-2]; 
          }
        };
    }

    public AttributeSet getResolveParent()
    {
      return resolveParent;
    }

    public int hashCode()
    {
      return java.util.Arrays.asList(attrs).hashCode();
    }

    public boolean isDefined(Object key)
    {
      for (int i = 0; i < attrs.length; i += 2)
        {
          if (attrs[i].equals(key))
            return true;
        }
      return false;
    }
	
    public boolean isEqual(AttributeSet attr)
    {
      boolean eq;
      // If the other one is also a SmallAttributeSet, it is only considered
      // equal if it's the same instance.
      if (attr instanceof SmallAttributeSet)
        eq = attr == this;
      else
        eq = getAttributeCount() == attr.getAttributeCount()
             && this.containsAttributes(attr);
      return eq;
    }
	
    public String toString()
    {
      StringBuilder sb = new StringBuilder();
      sb.append('{');
      for (int i = 0; i < attrs.length; i += 2)
        {
          if (attrs[i + 1] instanceof AttributeSet)
            {
              sb.append(attrs[i]);
              sb.append("=AttributeSet,");
            }
          else
            {
              sb.append(attrs[i]);
              sb.append('=');
              sb.append(attrs[i + 1]);
              sb.append(',');
            }
        }
      sb.append("}");
      return sb.toString();
    }
  }

  /**
   * Register StyleConstant keys as static attribute keys for serialization.
   */
  static
  {
    // Don't let problems while doing this prevent class loading.
    try
      {
        for (Iterator i = StyleConstants.keys.iterator(); i.hasNext();)
          registerStaticAttributeKey(i.next());
      }
    catch (Throwable t)
      {
        t.printStackTrace();
      }
  }

  /**
   * The name of the default style.
   */
  public static final String DEFAULT_STYLE = "default";
  
  static Hashtable sharedAttributeSets = new Hashtable();
  static Hashtable sharedFonts = new Hashtable();

  static StyleContext defaultStyleContext;
  static final int compressionThreshold = 9;

  /**
   * These attribute keys are handled specially in serialization.
   */
  private static Hashtable writeAttributeKeys;
  private static Hashtable readAttributeKeys;

  private NamedStyle styles;

  /**
   * Used for searching attributes in the pool.
   */
  private transient MutableAttributeSet search = new SimpleAttributeSet();

  /**
   * A pool of immutable AttributeSets.
   */
  private transient Map attributeSetPool =
    Collections.synchronizedMap(new WeakHashMap());

  /**
   * Creates a new instance of the style context. Add the default style
   * to the style table.
   */
  public StyleContext()
  {
    styles = new NamedStyle(null);
    addStyle(DEFAULT_STYLE, null);
  }

  protected SmallAttributeSet createSmallAttributeSet(AttributeSet a)
  {
    return new SmallAttributeSet(a);
  }
  
  protected MutableAttributeSet createLargeAttributeSet(AttributeSet a)
  {
    return new SimpleAttributeSet(a);
  }

  public void addChangeListener(ChangeListener listener)
  {
    styles.addChangeListener(listener);
  }

  public void removeChangeListener(ChangeListener listener)
  {
    styles.removeChangeListener(listener);
  }

  public ChangeListener[] getChangeListeners()
  {
    return styles.getChangeListeners();
  }
    
  public Style addStyle(String name, Style parent)
  {
    Style newStyle = new NamedStyle(name, parent);
    if (name != null)
      styles.addAttribute(name, newStyle);
    return newStyle;
  }

  public void removeStyle(String name)
  {
    styles.removeAttribute(name);
  }

  /**
   * Get the style from the style table. If the passed name
   * matches {@link #DEFAULT_STYLE}, returns the default style.
   * Otherwise returns the previously defined style of
   * <code>null</code> if the style with the given name is not defined.
   *
   * @param name the name of the style.
   *
   * @return the style with the given name or null if no such defined.
   */
  public Style getStyle(String name)
  {
    return (Style) styles.getAttribute(name);
  }
  
  /**
   * Get the names of the style. The returned enumeration always
   * contains at least one member, the default style.
   */
  public Enumeration<?> getStyleNames()
  {
    return styles.getAttributeNames();
  }

  private void readObject(ObjectInputStream in)
    throws ClassNotFoundException, IOException
  {
    search = new SimpleAttributeSet();
    attributeSetPool = Collections.synchronizedMap(new WeakHashMap());
    in.defaultReadObject();
  }

  private void writeObject(ObjectOutputStream out)
    throws IOException
  {
    cleanupPool();
    out.defaultWriteObject();
  }

  //
  // StyleContexts only understand the "simple" model of fonts present in
  // pre-java2d systems: fonts are a family name, a size (integral number
  // of points), and a mask of style parameters (plain, bold, italic, or
  // bold|italic). We have an inner class here called SimpleFontSpec which
  // holds such triples.
  //
  // A SimpleFontSpec can be built for *any* AttributeSet because the size,
  // family, and style keys in an AttributeSet have default values (defined
  // over in StyleConstants).
  //
  // We keep a static cache mapping SimpleFontSpecs to java.awt.Fonts, so
  // that we reuse Fonts between styles and style contexts.
  // 

  private static class SimpleFontSpec
  {
    String family;
    int style;
    int size;
    public SimpleFontSpec(String family,
                          int style,
                          int size)
    {
      this.family = family;
      this.style = style;
      this.size = size;
    }
    public boolean equals(Object obj)
    {
      return (obj != null)
        && (obj instanceof SimpleFontSpec)
        && (((SimpleFontSpec)obj).family.equals(this.family))
        && (((SimpleFontSpec)obj).style == this.style)
        && (((SimpleFontSpec)obj).size == this.size);
    }
    public int hashCode()
    {
      return family.hashCode() + style + size;
    }
  }
  
  public Font getFont(AttributeSet attr)
  {
    String family = StyleConstants.getFontFamily(attr);
    int style = Font.PLAIN;
    if (StyleConstants.isBold(attr))
      style += Font.BOLD;
    if (StyleConstants.isItalic(attr))
      style += Font.ITALIC;      
    int size = StyleConstants.getFontSize(attr);
    return getFont(family, style, size);
  }

  public Font getFont(String family, int style, int size)
  {
    SimpleFontSpec spec = new SimpleFontSpec(family, style, size);
    if (sharedFonts.containsKey(spec))
      return (Font) sharedFonts.get(spec);
    else
      {
        Font tmp = new Font(family, style, size);
        sharedFonts.put(spec, tmp);
        return tmp;
      }
  }
  
  public FontMetrics getFontMetrics(Font f)
  {
    return Toolkit.getDefaultToolkit().getFontMetrics(f);
  }

  public Color getForeground(AttributeSet a)
  {
    return StyleConstants.getForeground(a);
  }

  public Color getBackground(AttributeSet a)
  {
    return StyleConstants.getBackground(a);
  }

  protected int getCompressionThreshold() 
  {
    return compressionThreshold;
  }

  public static StyleContext getDefaultStyleContext()
  {
    if (defaultStyleContext == null)
      defaultStyleContext = new StyleContext();
    return defaultStyleContext;
  }

  public synchronized AttributeSet addAttribute(AttributeSet old, Object name,
                                                Object value)
  {
    AttributeSet ret;
    if (old.getAttributeCount() + 1 < getCompressionThreshold())
      {
        search.removeAttributes(search);
        search.addAttributes(old);
        search.addAttribute(name, value);
        reclaim(old);
        ret = searchImmutableSet();
      }
    else
      {
        MutableAttributeSet mas = getMutableAttributeSet(old);
        mas.addAttribute(name, value);
        ret = mas;
      }
    return ret;
  }

  public synchronized AttributeSet addAttributes(AttributeSet old,
                                                 AttributeSet attributes)
  {
    AttributeSet ret;
    if (old.getAttributeCount() + attributes.getAttributeCount()
        < getCompressionThreshold())
      {
        search.removeAttributes(search);
        search.addAttributes(old);
        search.addAttributes(attributes);
        reclaim(old);
        ret = searchImmutableSet();
      }
    else
      {
        MutableAttributeSet mas = getMutableAttributeSet(old);
        mas.addAttributes(attributes);
        ret = mas;
      }
    return ret;
  }

  public AttributeSet getEmptySet()
  {
    return SimpleAttributeSet.EMPTY;
  }

  public void reclaim(AttributeSet attributes)
  {
    cleanupPool();
  }

  public synchronized AttributeSet removeAttribute(AttributeSet old,
                                                   Object name)
  {
    AttributeSet ret;
    if (old.getAttributeCount() - 1 <= getCompressionThreshold())
      {
        search.removeAttributes(search);
        search.addAttributes(old);
        search.removeAttribute(name);
        reclaim(old);
        ret = searchImmutableSet();
      }
    else
      {
        MutableAttributeSet mas = getMutableAttributeSet(old);
        mas.removeAttribute(name);
        ret = mas;
      }
    return ret;
  }

  public synchronized AttributeSet removeAttributes(AttributeSet old,
                                                    AttributeSet attributes)
  {
    AttributeSet ret;
    if (old.getAttributeCount() <= getCompressionThreshold())
      {
        search.removeAttributes(search);
        search.addAttributes(old);
        search.removeAttributes(attributes);
        reclaim(old);
        ret = searchImmutableSet();
      }
    else
      {
        MutableAttributeSet mas = getMutableAttributeSet(old);
        mas.removeAttributes(attributes);
        ret = mas;
      }
    return ret;
  }

  public synchronized AttributeSet removeAttributes(AttributeSet old,
						    Enumeration<?> names)
  {
    AttributeSet ret;
    if (old.getAttributeCount() <= getCompressionThreshold())
      {
        search.removeAttributes(search);
        search.addAttributes(old);
        search.removeAttributes(names);
        reclaim(old);
        ret = searchImmutableSet();
      }
    else
      {
        MutableAttributeSet mas = getMutableAttributeSet(old);
        mas.removeAttributes(names);
        ret = mas;
      }
    return ret;
  }

  /**
   * Gets the object previously registered with registerStaticAttributeKey.
   * 
   * @param key - the key that was registered.
   * @return the object previously registered with registerStaticAttributeKey.
   */
  public static Object getStaticAttribute(Object key)
  {
    if (key == null)
      return null;
    return readAttributeKeys.get(key);
  }
  
  /**
   * Returns the String that key will be registered with
   * registerStaticAttributeKey.
   * 
   * @param key - the key that will be registered.
   * @return the string the key will be registered with.
   */
  public static Object getStaticAttributeKey(Object key)
  {
    return key.getClass().getName() + "." + key.toString();
  }

  /**
   * Reads a set of attributes from the given object input stream. This will
   * attempt to restore keys that were static objects by considering only the
   * keys that have were registered with registerStaticAttributeKey. The
   * attributes retrieved will be placed into the given set.
   * 
   * @param in - the stream to read from
   * @param a - the set of attributes
   * @throws ClassNotFoundException - may be encountered when reading from
   *           stream
   * @throws IOException - any I/O error
   */
  public static void readAttributeSet(ObjectInputStream in,
                                      MutableAttributeSet a)
    throws ClassNotFoundException, IOException
  {
    int count = in.readInt();
    for (int i = 0; i < count; i++)
      {
        Object key = in.readObject();
        Object val = in.readObject();
        if (readAttributeKeys != null)
          {
            Object staticKey = readAttributeKeys.get(key);
            if (staticKey != null)
              key = staticKey;
            Object staticVal = readAttributeKeys.get(val);
            if (staticVal != null)
              val = staticVal;
          }
        a.addAttribute(key, val);
      }
  }
  
  /**
   * Serialize an attribute set in a way that is compatible with it
   * being read in again by {@link #readAttributeSet(ObjectInputStream, MutableAttributeSet)}.
   * In particular registered static keys are transformed properly.
   * 
   * @param out - stream to write to
   * @param a - the attribute set
   * @throws IOException - any I/O error
   */
  public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a)
    throws IOException
  {
    int count = a.getAttributeCount();
    out.writeInt(count);
    Enumeration e = a.getAttributeNames();
    while (e.hasMoreElements())
      {
        Object key = e.nextElement();
        // Write key.
        if (key instanceof Serializable)
          out.writeObject(key);
        else
          {
            Object io = writeAttributeKeys.get(key);
            if (io == null)
              throw new NotSerializableException(key.getClass().getName()
                                                 + ", key: " + key);
            out.writeObject(io);
          }
        // Write value.
        Object val = a.getAttribute(key);
        Object io = writeAttributeKeys.get(val);
        if (val instanceof Serializable)
          out.writeObject(io != null ? io : val);
        else
          {
            if (io == null)
              throw new NotSerializableException(val.getClass().getName());
            out.writeObject(io);
          }
      }
  }

  /**
   * Handles reading in the attributes. 
   * @see #readAttributeSet(ObjectInputStream, MutableAttributeSet)
   * 
   * @param in - the stream to read from
   * @param a - the set of attributes
   * @throws ClassNotFoundException - may be encountered when reading from stream
   * @throws IOException - any I/O error
   */
  public void readAttributes(ObjectInputStream in, MutableAttributeSet a)
    throws ClassNotFoundException, IOException
  {
    readAttributeSet(in, a);
  }

  /**
   * Handles writing of the given attributes.
   * @see #writeAttributeSet(ObjectOutputStream, AttributeSet)
   * 
   * @param out - stream to write to
   * @param a - the attribute set
   * @throws IOException - any I/O error
   */
  public void writeAttributes(ObjectOutputStream out, AttributeSet a)
    throws IOException
  {
    writeAttributeSet(out, a);
  }

  /**
   * Registers an attribute key as a well-known keys. When an attribute with
   * such a key is written to a stream, a special syntax is used so that it
   * can be recognized when it is read back in. All attribute keys defined
   * in <code>StyleContext</code> are registered as static keys. If you define
   * additional attribute keys that you want to exist as nonreplicated objects,
   * then you should register them using this method.
   *
   * @param key the key to register as static attribute key
   */
  public static void registerStaticAttributeKey(Object key)
  {
    String io = key.getClass().getName() + "." + key.toString();
    if (writeAttributeKeys == null)
      writeAttributeKeys = new Hashtable();
    if (readAttributeKeys == null)
      readAttributeKeys = new Hashtable();
    writeAttributeKeys.put(key, io);
    readAttributeKeys.put(io, key);
  }

  /**
   * Returns a string representation of this StyleContext.
   *
   * @return a string representation of this StyleContext
   */
  public String toString()
  {
    cleanupPool();
    StringBuilder b = new StringBuilder();
    Iterator i = attributeSetPool.keySet().iterator();
    while (i.hasNext())
      {
        Object att = i.next();
        b.append(att);
        b.append('\n');
      }
    return b.toString();
  }

  /**
   * Searches the AttributeSet pool and returns a pooled instance if available,
   * or pool a new one.
   *
   * @return an immutable attribute set that equals the current search key
   */
  private AttributeSet searchImmutableSet()
  {
    SmallAttributeSet k = createSmallAttributeSet(search);
    WeakReference ref = (WeakReference) attributeSetPool.get(k);
    SmallAttributeSet a;
    if (ref == null || (a = (SmallAttributeSet) ref.get()) == null)
      {
        a = k;
        attributeSetPool.put(a, new WeakReference(a));
      }
    return a;
  }

  /**
   * Cleans up the attribute set pool from entries that are no longer
   * referenced.
   */
  private void cleanupPool()
  {
    // TODO: How else can we force cleaning up the WeakHashMap?
    attributeSetPool.size();
  }

  /**
   * Returns a MutableAttributeSet that holds a. If a itself is mutable,
   * this returns a itself, otherwise it creates a new SimpleAtttributeSet
   * via {@link #createLargeAttributeSet(AttributeSet)}.
   *
   * @param a the AttributeSet to create a mutable set for
   *
   * @return a mutable attribute set that corresponds to a
   */
  private MutableAttributeSet getMutableAttributeSet(AttributeSet a)
  {
    MutableAttributeSet mas;
    if (a instanceof MutableAttributeSet)
      mas = (MutableAttributeSet) a;
    else
      mas = createLargeAttributeSet(a);
    return mas;
  }
}
