Java tutorial
/* * Copyright 2004-2012 the Seasar Foundation and the Others. * * 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 org.seasar.mayaa.impl.engine.specification; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.seasar.mayaa.engine.specification.Namespace; import org.seasar.mayaa.engine.specification.PrefixMapping; import org.seasar.mayaa.engine.specification.URI; import org.seasar.mayaa.impl.CONST_IMPL; import org.seasar.mayaa.impl.util.ReferenceCache; import org.seasar.mayaa.impl.util.StringUtil; import org.seasar.mayaa.impl.util.collection.NullIterator; /** * @author Masataka Kurihara (Gluegent, Inc.) */ public class NamespaceImpl implements Namespace { private static final long serialVersionUID = -3738362040016319461L; private static final Log LOG = LogFactory.getLog(NamespaceImpl.class); private static ReferenceCache/*<Namespace>*/ _cache = new ReferenceCache(Namespace.class); public static Namespace getInstance(Namespace namespace) { return getInstance(serialize(namespace)); } public static Namespace getInstance(String serializeKey) { synchronized (_cache) { // ??? for (Iterator it = _cache.iterator(); it.hasNext();) { NamespaceImpl space = (NamespaceImpl) it.next(); if (space.getSerializeKey().equals(serializeKey)) { return space; } } Namespace namespace = deserialize(serializeKey); if (_cache.contains(namespace) == false) { _cache.add(namespace); } return namespace; } } public static Namespace copyOf(Namespace namespace) { if (namespace == null) { return namespace; } Namespace parent = namespace.getParentSpace(); if (parent != null) { String key = serialize(parent); parent = getInstance(key); } NamespaceImpl result = new NamespaceImpl(); result.setParentSpace(parent); for (Iterator it = namespace.iteratePrefixMapping(false); it.hasNext();) { PrefixMapping mapping = (PrefixMapping) it.next(); result.addPrefixMapping(mapping.getPrefix(), mapping.getNamespaceURI()); } result.setDefaultNamespaceURI(namespace.getDefaultNamespaceURI()); if (namespace instanceof NamespaceImpl) { result._serializeKey = ((NamespaceImpl) namespace)._serializeKey; } return result; } private transient Namespace _parentSpace; private transient Set/*<PrefixMapping>*/ _mappings; private transient PrefixMapping _defaultNamespaceMapping; private String _serializeKey; private transient boolean _needDeserialize; public void setParentSpace(Namespace parent) { /* if (parent == null) { throw new IllegalArgumentException(); } */ if (parent != null) { if (_parentSpace == parent || parent.equals(_parentSpace)) { return; } } _parentSpace = parent; _serializeKey = null; } public Namespace getParentSpace() { doDeserialize(); return _parentSpace; } public void addPrefixMapping(String prefix, URI namespaceURI) { if (prefix == null || StringUtil.isEmpty(namespaceURI)) { throw new IllegalArgumentException(); } synchronized (this) { doDeserialize(); if (_mappings == null) { // ???xmlns????????? // ????????? _mappings = new TreeSet(_prefixMappingComparator); } PrefixMapping mapping = SpecificationUtil.createPrefixMapping(prefix, namespaceURI); if (_mappings.contains(mapping) == false) { _mappings.add(mapping); _serializeKey = null; } else { if (LOG.isWarnEnabled()) { LOG.warn(StringUtil.getMessage(NamespaceImpl.class, 0, mapping.toString())); } } } } public void setDefaultNamespaceURI(URI namespaceURI) { doDeserialize(); if (namespaceURI == null) { if (_defaultNamespaceMapping != null) { _defaultNamespaceMapping = null; _serializeKey = null; } return; } for (Iterator it = iteratePrefixMapping(true); it.hasNext();) { PrefixMapping mapping = (PrefixMapping) it.next(); if (mapping.getNamespaceURI().equals(namespaceURI)) { if (mapping.equals(_defaultNamespaceMapping) == false) { _defaultNamespaceMapping = mapping; _serializeKey = null; } return; } } if (namespaceURI.equals(CONST_IMPL.URI_HTML)) { if (SpecificationUtil.HTML_DEFAULT_PREFIX_MAPPING.equals(_defaultNamespaceMapping) == false) { _defaultNamespaceMapping = SpecificationUtil.HTML_DEFAULT_PREFIX_MAPPING; _serializeKey = null; } return; } if (namespaceURI.equals(CONST_IMPL.URI_XHTML)) { if (SpecificationUtil.XHTML_DEFAULT_PREFIX_MAPPING.equals(_defaultNamespaceMapping) == false) { _defaultNamespaceMapping = SpecificationUtil.XHTML_DEFAULT_PREFIX_MAPPING; _serializeKey = null; } return; } _defaultNamespaceMapping = SpecificationUtil.createPrefixMapping("", namespaceURI); _serializeKey = null; } protected void setDefaultNamespaceMapping(PrefixMapping defaultNamespaceMapping) { _defaultNamespaceMapping = defaultNamespaceMapping; } protected PrefixMapping getDefaultNamespaceMapping() { doDeserialize(); return _defaultNamespaceMapping; } public URI getDefaultNamespaceURI() { doDeserialize(); if (_defaultNamespaceMapping == null) { return null; } return _defaultNamespaceMapping.getNamespaceURI(); } protected PrefixMapping getMapping(boolean fromPrefix, String test, boolean all) { if (test == null) { throw new IllegalArgumentException(); } doDeserialize(); if (_defaultNamespaceMapping != null) { if (fromPrefix) { if ("".equals(test) || _defaultNamespaceMapping.getPrefix().equals(test)) { return _defaultNamespaceMapping; } } else { if (_defaultNamespaceMapping.getNamespaceURI().equals(test)) { return _defaultNamespaceMapping; } } } for (Iterator it = iteratePrefixMapping(all); it.hasNext();) { PrefixMapping mapping = (PrefixMapping) it.next(); String value = fromPrefix ? mapping.getPrefix() : mapping.getNamespaceURI().getValue(); if (test.equals(value)) { return mapping; } } if (CONST_IMPL.URI_XML.equals(test)) { return SpecificationUtil.XML_DEFAULT_PREFIX_MAPPING; } return null; } public PrefixMapping getMappingFromPrefix(String prefix, boolean all) { if (prefix == null) { prefix = ""; } return getMapping(true, prefix, all); } public PrefixMapping getMappingFromURI(URI namespaceURI, boolean all) { if (StringUtil.isEmpty(namespaceURI)) { throw new IllegalArgumentException(); } return getMapping(false, namespaceURI.getValue(), all); } public Iterator iteratePrefixMapping(boolean all) { if (all && getParentSpace() != null) { return new AllNamespaceIterator(this); } doDeserialize(); if (_mappings != null) { return _mappings.iterator(); } return NullIterator.getInstance(); } public boolean addedMapping() { doDeserialize(); if (_mappings == null) { return false; } synchronized (_mappings) { return _mappings.size() > 0; } } protected String getSerializeKey() { doDeserialize(); serialize(this); return _serializeKey; } protected static String serialize(Namespace instance) { if (instance instanceof NamespaceImpl == false) { throw new IllegalStateException(); } NamespaceImpl impl = (NamespaceImpl) instance; if (impl._serializeKey != null) { return impl._serializeKey; } List spaces = new ArrayList(); Namespace parent = instance.getParentSpace(); while (parent != null) { spaces.add(parent); parent = parent.getParentSpace(); } StringBuffer buffer = new StringBuffer(); for (int i = spaces.size() - 1; i >= 0; i--) { Namespace current = (Namespace) spaces.get(i); if (current instanceof NamespaceImpl) { NamespaceImpl currentImpl = (NamespaceImpl) current; buffer.append(currentImpl.namespaceToString()); } else { throw new IllegalStateException(); } } buffer.append(impl.namespaceToString()); String result = buffer.toString(); impl._serializeKey = result; return result; } protected static NamespaceImpl deserialize(String serializeData) { String[] lines = serializeData.split("\n"); Namespace parent = null; NamespaceImpl current = null; for (int i = 0; i < lines.length; i++) { String line = lines[i]; if (line.startsWith("/")) { line = line.substring("/".length()); if (current != null) { synchronized (_cache) { if (_cache.contains(current) == false) { _cache.add(current); } } parent = current; } current = new NamespaceImpl(); if (String.valueOf((Object) null).equals(line) == false) { current._defaultNamespaceMapping = SpecificationUtil.createPrefixMapping(line); } if (parent != null) { current.setParentSpace(parent); } } else if (line.startsWith("\t") && current != null) { line = line.substring("\t".length()); // ?????addPrefixMapping??? if (current._mappings == null) { current._mappings = new TreeSet(_prefixMappingComparator); } current._mappings.add(SpecificationUtil.createPrefixMapping(line)); } } return current; } private String namespaceToString() { StringBuffer sb = new StringBuffer(); sb.append("/").append(_defaultNamespaceMapping).append("\n"); for (Iterator it = iteratePrefixMapping(false); it.hasNext();) { sb.append("\t").append(it.next()).append("\n"); } return sb.toString(); } public String toString() { return namespaceToString(); } public boolean equals(Object obj) { if (obj != null && obj.getClass().equals(NamespaceImpl.class)) { NamespaceImpl other = (NamespaceImpl) obj; String otherKey = other.getSerializeKey(); return getSerializeKey().equals(otherKey); } return false; } // TODO hashCode? private void writeObject(java.io.ObjectOutputStream out) throws IOException { if (getClass() == NamespaceImpl.class) { getSerializeKey(); out.defaultWriteObject(); } } protected void doDeserialize() { if (_needDeserialize) { _needDeserialize = false; NamespaceImpl current = deserialize(getSerializeKey()); _parentSpace = current._parentSpace; _defaultNamespaceMapping = current._defaultNamespaceMapping; _mappings = new TreeSet(_prefixMappingComparator); for (Iterator it = current.iteratePrefixMapping(false); it.hasNext();) { _mappings.add(it.next()); } } } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { if (getClass() == NamespaceImpl.class) { in.defaultReadObject(); _needDeserialize = true; } } // support class ------------------------------------------------- protected static class AllNamespaceIterator implements Iterator { private Namespace _current; private Iterator _it; public AllNamespaceIterator(Namespace current) { if (current == null) { throw new IllegalArgumentException(); } _current = current; _it = current.iteratePrefixMapping(false); } public boolean hasNext() { while (_it != null) { boolean ret = _it.hasNext(); if (ret) { return true; } if (_current != null && (_current = _current.getParentSpace()) != null) { _it = _current.iteratePrefixMapping(false); } else { _it = null; } } return false; } public Object next() { if (hasNext()) { return _it.next(); } throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } } protected static final Comparator _prefixMappingComparator = new Comparator() { public int compare(Object o1, Object o2) { if (o1 instanceof PrefixMapping && o2 instanceof PrefixMapping) { PrefixMapping mapping1 = (PrefixMapping) o1; PrefixMapping mapping2 = (PrefixMapping) o2; URI ns1 = mapping1.getNamespaceURI(); URI ns2 = mapping2.getNamespaceURI(); int result = 0; if (ns1 == null) { if (ns2 != null) { result = -1; } } else if (ns2 == null) { result = 1; } else { result = ns1.compareTo(ns2); } if (result == 0) { String prefix1 = mapping1.getPrefix(); String prefix2 = mapping2.getPrefix(); if (prefix1 == null) { prefix1 = ""; } if (prefix2 == null) { prefix2 = ""; } result = prefix1.compareTo(prefix2); } return result; } throw new IllegalStateException(); } public boolean equals(Object obj) { return obj == this; } public int hashCode() { return super.hashCode(); } }; }