001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.metaboss.sdlctools.models.impl;
016:
017: import java.util.HashMap;
018: import java.util.HashSet;
019: import java.util.Map;
020: import java.util.Set;
021:
022: import javax.jmi.reflect.RefObject;
023:
024: import com.metaboss.util.ByteUtils;
025:
026: /** Implementation of the XmiIdGenerator seeded with machine's IP address and timestamp. */
027: public class XmiIdGeneratorImpl implements XmiIdGenerator {
028: private Set mRefObjects = new HashSet();
029: private Map mRefObjectToXmiId = new HashMap(); // Map of XMIIds indexed by RefObjects
030: private Map mXmiIdToRefObject = new HashMap(); // Map of RefObjects ---> indexed by XMIIds
031: private String mXmiIdPrefix = ""; // Prefix provides stronger chance for uniqueness of the xmi id
032: private long mNextXmiId = System.currentTimeMillis();
033:
034: public XmiIdGeneratorImpl() {
035: // Use machine ip address to provide stronger chance for uniqueness of the xmi ids
036: try {
037: java.net.InetAddress lThisHost = java.net.InetAddress
038: .getLocalHost();
039: mXmiIdPrefix = ByteUtils
040: .bytesToText(lThisHost.getAddress()).toUpperCase()
041: + "-";
042: } catch (java.net.UnknownHostException e) {
043: // Ignore. This will produce no prefix, xmi id still have some change to be unique
044: }
045: }
046:
047: // Registers an existing object with its XMI id
048: public void registerExistingObject(RefObject pRefObject,
049: String pXmiId) {
050: if (mRefObjects.add(pRefObject)) {
051: mRefObjectToXmiId.put(pRefObject, pXmiId);
052: Object lRefObject = mXmiIdToRefObject.put(pXmiId,
053: pRefObject);
054: if (lRefObject != null
055: && lRefObject.equals(pRefObject) == false)
056: throw new IllegalArgumentException(
057: "XmiId "
058: + pXmiId
059: + " has already been associated with different RefObject.");
060: } else if (!pXmiId.equals(mRefObjectToXmiId.get(pRefObject)))
061: throw new IllegalArgumentException(
062: "RefObject with MofId "
063: + pRefObject.refMofId()
064: + " has already been associated with different XmiId.");
065:
066: }
067:
068: // Returns a RefObject corresponding to the given xmi id or null if none registered
069: public RefObject getRefObject(String pXmiId) {
070: return (RefObject) mXmiIdToRefObject.get(pXmiId);
071: }
072:
073: // Returns an XmiId for the given object. Returns an existing one or creates a new one
074: public String getXmiId(RefObject pRefObject) {
075: String lXmiId = (String) mRefObjectToXmiId.get(pRefObject);
076: if (lXmiId == null) {
077: // Generate a new Id
078: do {
079: lXmiId = mXmiIdPrefix
080: + Long.toString(mNextXmiId++,
081: Character.MAX_RADIX).toUpperCase();
082: } while (mXmiIdToRefObject.containsKey(lXmiId));
083:
084: // Safe registration
085: if (mRefObjects.add(pRefObject)) {
086: mRefObjectToXmiId.put(pRefObject, lXmiId);
087: Object lRefObject = mXmiIdToRefObject.put(lXmiId,
088: pRefObject);
089: if (lRefObject != null
090: && lRefObject.equals(pRefObject) == false)
091: throw new RuntimeException(
092: "XmiId "
093: + lXmiId
094: + " has already been associated with different RefObject.");
095: } else {
096: // Someone else has already added it
097: if ((lXmiId = (String) mRefObjectToXmiId
098: .get(pRefObject)) == null) {
099: // Allow for a bit of a delay
100: Thread.yield();
101: if ((lXmiId = (String) mRefObjectToXmiId
102: .get(pRefObject)) == null)
103: throw new RuntimeException(
104: "Registered RefObject does not have associated XmiId.");
105: }
106: }
107: }
108: return lXmiId;
109: }
110: }
|