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.io.File;
018: import java.io.IOException;
019: import java.util.Collection;
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.Map;
023:
024: import javax.jmi.reflect.RefObject;
025: import javax.jmi.reflect.RefPackage;
026: import javax.jmi.xmi.MalformedXMIException;
027:
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.netbeans.api.xmi.XMIInputConfig;
031: import org.netbeans.api.xmi.XMIReader;
032: import org.netbeans.api.xmi.XMIReaderFactory;
033: import org.netbeans.api.xmi.XMIReferenceResolver;
034:
035: /** Implementation of the XMIReferenceResolver, which takes care of partitioning. */
036: public class XMIReferenceResolverImpl implements XMIReferenceResolver {
037: // Commons Logging instance.
038: private static final Log sLogger = LogFactory
039: .getLog(XMIReferenceResolverImpl.class);
040: private String mModelRootDirectoryURIPrefix;
041: private XmiIdGenerator mXmiIdGenerator;
042: private Map mObjectsMap = new HashMap(); // Key - proper HRef, Value - actual object
043:
044: /**
045: * @param pModelRootDirectory - file representing the root directory of the model we use it to look for files
046: * @param pObjectsInPartitionsMap - map of xmiIds stored in each systemId we register each resolved xmi id with it
047: * @param pXmiIdGenerator - utility xmiId generator we put known ids to it so they do not get reused
048: */
049: public XMIReferenceResolverImpl(File pModelRootDirectory,
050: XmiIdGenerator pXmiIdGenerator) {
051: String lModelRootDirectoryAbsolutePath = pModelRootDirectory
052: .getAbsolutePath();
053: String lModelRootDirectoryURIString = new File(
054: lModelRootDirectoryAbsolutePath).toURI().toString();
055: mModelRootDirectoryURIPrefix = lModelRootDirectoryURIString
056: .substring(0, lModelRootDirectoryURIString.length() - 1);
057: mXmiIdGenerator = pXmiIdGenerator;
058: }
059:
060: /** Registers an object that can be resolved. This method should be called by
061: * XMI consumer each time it successfuly deserializes an object from XMI, given that the object
062: * was assigned an xmiId (for objects that do not have xmiId defined in XMI file
063: * this method should not be called).<p>
064: * Implementation of this interface should remember all the registered objects and
065: * use them for resolving hrefs.
066: * @param pSystemId URI of the document that called this method (the URI is essential for
067: * correct resolution of cyclic and relative references).
068: * @param pXmiId XMI ID of the object deserialized from XMI. If XMI ID for the object
069: * is not available, this method should not be called.
070: * @param object Object deserialized from XMI.
071: */
072: public void register(String pSystemId, String pXmiId,
073: RefObject pRefObject) {
074: String lURIString = getURIFromSystemId(pSystemId);
075: String lProperHref = lURIString + "#" + pXmiId;
076: mObjectsMap.put(lProperHref, pRefObject);
077: mXmiIdGenerator.registerExistingObject(pRefObject, pXmiId);
078: }
079:
080: /**
081: * Resolves external references and calls
082: * {@link XMIReferenceResolver.Client#resolvedReference} for each.
083: * Before returning from this method (only in case of outermost call to it - i.e. this
084: * does not hold for nested recursive calls from XMI consumers created from within this
085: * method) the instance of this class should be restored to its initial state (all
086: * registered references should be forgotten).
087: *
088: * @param client Implementation of callback method used for reference resolving notifications.
089: * @param extent Target package (for resolved objects).
090: * @param systemId URI of the document where href is used. This parameter is provided only
091: * if it is known by XMI consumer, otherwise <code>null</code> is passed.
092: * @param configuration Configuration to be used for XMI consumer used for reading
093: * external XMI document to resolve the href (if needed).
094: * @param hrefs References to be resolved.
095: *
096: * @throws MalformedXMIException Thrown
097: * to indicate an error (element cannot be resolved, etc.)
098: * @throws IOException I/O error during XMI reading.
099: */
100: public void resolve(Client client, RefPackage extent,
101: String systemId, XMIInputConfig configuration,
102: Collection hrefs) throws MalformedXMIException, IOException {
103: for (Iterator lIter = hrefs.iterator(); lIter.hasNext();) {
104: String lHrefToResolve = (String) lIter.next();
105: int lHashPos = lHrefToResolve.indexOf("#");
106: if (lHashPos <= 0)
107: throw new MalformedXMIException("Invalid href value: "
108: + lHrefToResolve);
109: String lURIString = getURIFromSystemId(lHrefToResolve
110: .substring(0, lHashPos));
111: String lXmiIdString = lHrefToResolve
112: .substring(lHashPos + 1);
113: String lProperHref = lURIString + "#" + lXmiIdString;
114: // sLogger.debug("Attempting to resolve " + lProperHref);
115: RefObject lResolvedRefObject = (RefObject) mObjectsMap
116: .get(lProperHref);
117: if (lResolvedRefObject == null) {
118: // Need to resolve this object by reading the file
119: XMIReader lXMIReader = XMIReaderFactory.getDefault()
120: .createXMIReader(configuration);
121: lXMIReader.read(lURIString, extent);
122: if ((lResolvedRefObject = (RefObject) mObjectsMap
123: .get(lProperHref)) == null)
124: throw new MalformedXMIException(
125: "Unable to resolve XMI Element referred to as "
126: + lProperHref);
127: }
128: client
129: .resolvedReference(lHrefToResolve,
130: lResolvedRefObject);
131: }
132: }
133:
134: // Constructs URI from the supplied systemId
135: private String getURIFromSystemId(String pSystemId) {
136: String lURIString = pSystemId;
137: // Some times XMI / SAX throws at us malformed system id (may be due to how we format system ids)
138: // We need to deal with it here
139: int lAbsoluteSplit = lURIString.indexOf("//");
140: if (lAbsoluteSplit >= 0)
141: lURIString = mModelRootDirectoryURIPrefix
142: + lURIString.substring(lAbsoluteSplit + 1);
143: return lURIString;
144: }
145: }
|