1 /* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.bind.v2.runtime; 27 28 import java.util.HashSet; 29 import java.util.IdentityHashMap; 30 import java.util.Map; 31 import java.util.Set; 32 33 /** 34 * Bi-directional map between elements, inner peers, 35 * and outer peers. 36 * 37 * <p> 38 * TODO: this should be rewritten for efficiency. 39 * 40 * @since 2.0 41 * 42 * @author 43 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 44 */ 45 public final class AssociationMap<XmlNode> { 46 final static class Entry<XmlNode> { 47 /** XML element. */ 48 private XmlNode element; 49 /** inner peer, or null. */ 50 private Object inner; 51 /** outer peer, or null. */ 52 private Object outer; 53 54 public XmlNode element() { 55 return element; 56 } 57 public Object inner() { 58 return inner; 59 } 60 public Object outer() { 61 return outer; 62 } 63 } 64 65 private final Map<XmlNode,Entry<XmlNode>> byElement = new IdentityHashMap<XmlNode,Entry<XmlNode>>(); 66 private final Map<Object,Entry<XmlNode>> byPeer = new IdentityHashMap<Object,Entry<XmlNode>>(); 67 private final Set<XmlNode> usedNodes = new HashSet<XmlNode>(); 68 69 /** Records the new {@code element <->inner} peer association. */ 70 public void addInner( XmlNode element, Object inner ) { 71 Entry<XmlNode> e = byElement.get(element); 72 if(e!=null) { 73 if(e.inner!=null) 74 byPeer.remove(e.inner); 75 e.inner = inner; 76 } else { 77 e = new Entry<XmlNode>(); 78 e.element = element; 79 e.inner = inner; 80 } 81 82 byElement.put(element,e); 83 84 Entry<XmlNode> old = byPeer.put(inner,e); 85 if(old!=null) { 86 if(old.outer!=null) 87 byPeer.remove(old.outer); 88 if(old.element!=null) 89 byElement.remove(old.element); 90 } 91 } 92 93 /** Records the new {@code element <-> outer} peer association. */ 94 public void addOuter( XmlNode element, Object outer ) { 95 Entry<XmlNode> e = byElement.get(element); 96 if(e!=null) { 97 if(e.outer!=null) 98 byPeer.remove(e.outer); 99 e.outer = outer; 100 } else { 101 e = new Entry<XmlNode>(); 102 e.element = element; 103 e.outer = outer; 104 } 105 106 byElement.put(element,e); 107 108 Entry<XmlNode> old = byPeer.put(outer,e); 109 if(old!=null) { 110 old.outer=null; 111 112 if(old.inner==null) 113 // remove this entry 114 byElement.remove(old.element); 115 } 116 } 117 118 public void addUsed( XmlNode n ) { 119 usedNodes.add(n); 120 } 121 122 public Entry<XmlNode> byElement( Object e ) { 123 return byElement.get(e); 124 } 125 126 public Entry<XmlNode> byPeer( Object o ) { 127 return byPeer.get(o); 128 } 129 130 public Object getInnerPeer( XmlNode element ) { 131 Entry e = byElement(element); 132 if(e==null) return null; 133 else return e.inner; 134 } 135 136 public Object getOuterPeer( XmlNode element ) { 137 Entry e = byElement(element); 138 if(e==null) return null; 139 else return e.outer; 140 } 141 }