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:
037: package com.sun.xml.ws.api.pipe;
038:
039: import java.util.HashMap;
040: import java.util.Map;
041:
042: /**
043: * Clones the whole pipeline.
044: *
045: * <p>
046: * Since {@link Tube}s may form an arbitrary directed graph, someone needs
047: * to keep track of isomorphism for a clone to happen correctly. This class
048: * serves that role.
049: *
050: * @author Kohsuke Kawaguchi
051: */
052: public class TubeCloner {
053: // Pipe to pipe, or tube to tube
054: protected final Map<Object, Object> master2copy = new HashMap<Object, Object>();
055:
056: /*package*/TubeCloner() {
057: }
058:
059: /**
060: * Invoked by a client of a tube to clone the whole pipeline.
061: *
062: * <p>
063: * {@link Tube}s implementing the {@link Tube#copy(TubeCloner)} method
064: * shall use {@link #copy(Tube)} method.
065: *
066: * @param p
067: * The entry point of a pipeline to be copied. must not be null.
068: * @return
069: * The cloned pipeline. Always non-null.
070: */
071: public static Tube clone(Tube p) {
072: // we often want to downcast TubeCloner to PipeCloner,
073: // so let's create PipeCloner to make that possible
074: return new PipeCloner().copy(p);
075: }
076:
077: /**
078: * Invoked by a {@link Tube#copy(TubeCloner)} implementation
079: * to copy a reference to another pipe.
080: *
081: * <p>
082: * This method is for {@link Tube} implementations, not for users.
083: *
084: * <p>
085: * If the given tube is already copied for this cloning episode,
086: * this method simply returns that reference. Otherwise it copies
087: * a tube, make a note, and returns a copied tube. This additional
088: * step ensures that a graph is cloned isomorphically correctly.
089: *
090: * <p>
091: * (Think about what happens when a graph is A->B, A->C, B->D, and C->D
092: * if you don't have this step.)
093: *
094: * @param t
095: * The tube to be copied.
096: * @return
097: * The cloned tube. Always non-null.
098: */
099: public <T extends Tube> T copy(T t) {
100: Tube r = (Tube) master2copy.get(t);
101: if (r == null) {
102: r = t.copy(this );
103: // the pipe must puts its copy to the map by itself
104: assert master2copy.get(t) == r : "the tube must call the add(...) method to register itself before start copying other pipes, but "
105: + t + " hasn't done so";
106: }
107: return (T) r;
108: }
109:
110: /**
111: * This method must be called from within the copy constructor
112: * to notify that the copy was created.
113: *
114: * <p>
115: * When your pipe has references to other pipes,
116: * it's particularly important to call this method
117: * before you start copying the pipes you refer to,
118: * or else there's a chance of inifinite loop.
119: */
120: public void add(Tube original, Tube copy) {
121: assert !master2copy.containsKey(original);
122: assert original != null && copy != null;
123: master2copy.put(original, copy);
124: }
125: }
|