001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: package com.sun.xml.bind.v2.runtime;
037:
038: import java.util.HashSet;
039: import java.util.IdentityHashMap;
040: import java.util.Map;
041: import java.util.Set;
042:
043: /**
044: * Bi-directional map between elements, inner peers,
045: * and outer peers.
046: *
047: * <p>
048: * TODO: this should be rewritten for efficiency.
049: *
050: * @since 2.0
051: *
052: * @author
053: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
054: */
055: public final class AssociationMap<XmlNode> {
056: final static class Entry<XmlNode> {
057: /** XML element. */
058: private XmlNode element;
059: /** inner peer, or null. */
060: private Object inner;
061: /** outer peer, or null. */
062: private Object outer;
063:
064: public XmlNode element() {
065: return element;
066: }
067:
068: public Object inner() {
069: return inner;
070: }
071:
072: public Object outer() {
073: return outer;
074: }
075: }
076:
077: private final Map<XmlNode, Entry<XmlNode>> byElement = new IdentityHashMap<XmlNode, Entry<XmlNode>>();
078: private final Map<Object, Entry<XmlNode>> byPeer = new IdentityHashMap<Object, Entry<XmlNode>>();
079: private final Set<XmlNode> usedNodes = new HashSet<XmlNode>();
080:
081: /** Records the new element<->inner peer association. */
082: public void addInner(XmlNode element, Object inner) {
083: Entry<XmlNode> e = byElement.get(element);
084: if (e != null) {
085: if (e.inner != null)
086: byPeer.remove(e.inner);
087: e.inner = inner;
088: } else {
089: e = new Entry<XmlNode>();
090: e.element = element;
091: e.inner = inner;
092: }
093:
094: byElement.put(element, e);
095:
096: Entry<XmlNode> old = byPeer.put(inner, e);
097: if (old != null) {
098: if (old.outer != null)
099: byPeer.remove(old.outer);
100: if (old.element != null)
101: byElement.remove(old.element);
102: }
103: }
104:
105: /** Records the new element<->outer peer association. */
106: public void addOuter(XmlNode element, Object outer) {
107: Entry<XmlNode> e = byElement.get(element);
108: if (e != null) {
109: if (e.outer != null)
110: byPeer.remove(e.outer);
111: e.outer = outer;
112: } else {
113: e = new Entry<XmlNode>();
114: e.element = element;
115: e.outer = outer;
116: }
117:
118: byElement.put(element, e);
119:
120: Entry<XmlNode> old = byPeer.put(outer, e);
121: if (old != null) {
122: old.outer = null;
123:
124: if (old.inner == null)
125: // remove this entry
126: byElement.remove(old.element);
127: }
128: }
129:
130: public void addUsed(XmlNode n) {
131: usedNodes.add(n);
132: }
133:
134: public Entry<XmlNode> byElement(Object e) {
135: return byElement.get(e);
136: }
137:
138: public Entry<XmlNode> byPeer(Object o) {
139: return byPeer.get(o);
140: }
141:
142: public Object getInnerPeer(XmlNode element) {
143: Entry e = byElement(element);
144: if (e == null)
145: return null;
146: else
147: return e.inner;
148: }
149:
150: public Object getOuterPeer(XmlNode element) {
151: Entry e = byElement(element);
152: if (e == null)
153: return null;
154: else
155: return e.outer;
156: }
157: }
|