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.Iterator;
019: import java.util.Map;
020: import java.util.Properties;
021:
022: import javax.jmi.reflect.RefObject;
023: import javax.naming.Context;
024: import javax.naming.InitialContext;
025: import javax.naming.NamingException;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.netbeans.api.xmi.XMIReferenceProvider;
030:
031: import com.metaboss.enterprise.bs.BSException;
032: import com.metaboss.sdlctools.models.ModelRepositoryException;
033: import com.metaboss.sdlctools.services.jdktools.BSVelocityTemplateProcessor;
034: import com.metaboss.sdlctools.services.jdktools.MergeResult;
035:
036: /** Implementation of the XMIReferenceProvider which takes care of file partitioning. */
037: public class XMIReferenceProviderImpl implements XMIReferenceProvider {
038: // Commons Logging instance.
039: private static final Log sLogger = LogFactory
040: .getLog(XMIReferenceProviderImpl.class);
041: // private class RefObjectExpressionResolver implements TemplateUtil.ExpressionResolver
042: // {
043: // private RefObject mRefObject;
044: //
045: // public RefObjectExpressionResolver(RefObject pRefObject)
046: // {
047: // mRefObject = pRefObject;
048: // }
049: //
050: // // Returns string to substitute given expression
051: // public String resolve(String pExpression) throws TemplateUtil.UnexpectedSyntaxException
052: // {
053: // return (String)mRefObject.refGetValue(pExpression);
054: // }
055: // }
056:
057: private String mModelRootURI;
058: private Map mModelPartitions = new HashMap();
059: private XmiIdGenerator mXmiIdGenerator;
060: private Map mAlreadyResolvedReferencesByRefObject = new HashMap();
061: private BSVelocityTemplateProcessor mTemplateProcessor = null;
062:
063: /** Constructs provider for particular set of storage partitioning properties
064: * @param pModelStorageProperties - properties class name --> partition path expression
065: * @throws ClassNotFoundException - if class, mentioned in properties is not found
066: */
067: public XMIReferenceProviderImpl(String pModelRootURI,
068: Properties pModelStorageProperties,
069: XmiIdGenerator pXmiIdGenerator)
070: throws ModelRepositoryException {
071: mModelRootURI = pModelRootURI;
072: mXmiIdGenerator = pXmiIdGenerator;
073: // Initialise partitions
074: Iterator lIter = pModelStorageProperties.entrySet().iterator();
075: while (lIter.hasNext()) {
076: Map.Entry lEntry = (Map.Entry) lIter.next();
077: try {
078: mModelPartitions.put(Class.forName((String) lEntry
079: .getKey()), lEntry.getValue());
080: } catch (ClassNotFoundException e) {
081: throw new ModelRepositoryException(
082: "Class "
083: + (String) lEntry.getKey()
084: + " mentioned in Model Storage Properties is not found",
085: e);
086: }
087: }
088: try {
089: // Connect to Velocity template processor
090: Context lContext = new InitialContext();
091: mTemplateProcessor = (BSVelocityTemplateProcessor) lContext
092: .lookup(BSVelocityTemplateProcessor.COMPONENT_URL);
093: } catch (NamingException e) {
094: throw new ModelRepositoryException(
095: "Unable to locate Velocity template processor.", e);
096: }
097: }
098:
099: // This method will return cached reference if there is one already in the cache and generate a new one if nothing is found in the cache.
100: // After this call cache will contain XMIReference for this object. This XMIReference may become invalid
101: // if containment path of the object has changed.
102: public XMIReferenceProvider.XMIReference getReference(
103: RefObject pRefObject) {
104: XMIReferenceProvider.XMIReference lReference = (XMIReferenceProvider.XMIReference) mAlreadyResolvedReferencesByRefObject
105: .get(pRefObject);
106: if (lReference == null) {
107: // Construct URI of the file this object should be written to
108: // The URI is constructed from immediate composite's URI (optional - there may not be
109: // a composite if this is a top level object) and optional own URI (if this object type
110: // is listed as a partition owner).
111:
112: // Find out if this object is itself an owner of the partition
113: String lPartitionURIString = null;
114: for (Iterator lIter = mModelPartitions.entrySet()
115: .iterator(); lIter.hasNext();) {
116: Map.Entry lEntry = (Map.Entry) lIter.next();
117: Class lEntryClass = (Class) lEntry.getKey();
118: if (lEntryClass.isInstance(pRefObject)) {
119: try {
120: java.util.Map lContextMap = new java.util.HashMap();
121: lContextMap.put("Instance", pRefObject);
122: MergeResult lResult = mTemplateProcessor
123: .mergeTemplate((String) lEntry
124: .getValue(), lEntryClass
125: .getName(), lContextMap);
126: if (!lResult.isSuccessful()) {
127: // We handle problems here by loging the problem and returning model URI
128: sLogger
129: .error("Error resolving partition path template for "
130: + lEntryClass.getName()
131: + " class. Instance will be written into the root partition. Template processor log :"
132: + lResult
133: .getMergeLogPrintout());
134: lPartitionURIString = mModelRootURI;
135: } else
136: lPartitionURIString = lResult
137: .getMergedOutput();
138: } catch (BSException e) {
139: sLogger
140: .error(
141: "Error resolving partition path template for "
142: + lEntryClass.getName()
143: + " class. Instance will be written into the root partition.",
144: e);
145: lPartitionURIString = mModelRootURI;
146: }
147: }
148: }
149: // If we have own partition URI string and it starts from '/' - we do not
150: // need to look at parent URI - because our URI is absolute
151: if (lPartitionURIString == null
152: || lPartitionURIString.startsWith("/") == false) {
153: // If we have a parent - call this method recursively to obtain parent's URI
154: RefObject lImmediateParent = (RefObject) pRefObject
155: .refImmediateComposite();
156: if (lImmediateParent != null) {
157: XMIReferenceProvider.XMIReference lParentReference = getReference(lImmediateParent);
158: // See if we need to merge and do it if we need to
159: if (lPartitionURIString != null) {
160: // Need to do merge of parent's URI and our relative URI
161: String lParentFullURIString = lParentReference
162: .getSystemId();
163: if (lParentFullURIString != null) {
164: String lParentDirectoryURIString = lParentFullURIString
165: .substring(0, lParentFullURIString
166: .lastIndexOf('/'));
167: lPartitionURIString = lParentDirectoryURIString
168: + '/' + lPartitionURIString;
169: }
170: } else {
171: // No need to do merge - parent's sysem id is also ours
172: lPartitionURIString = lParentReference
173: .getSystemId();
174: }
175: } else {
176: // Top level object. It should go into the model's root URI or under it
177: if (lPartitionURIString != null) {
178: if (mModelRootURI != null) {
179: // Need to do merge of parent's URI and our relative URI
180: String lParentDirectoryURIString = mModelRootURI
181: .substring(0, mModelRootURI
182: .lastIndexOf('/'));
183: lPartitionURIString = lParentDirectoryURIString
184: + '/' + lPartitionURIString;
185: }
186: } else {
187: lPartitionURIString = mModelRootURI;
188: }
189: }
190: }
191: lReference = new XMIReferenceProvider.XMIReference(
192: lPartitionURIString, mXmiIdGenerator
193: .getXmiId(pRefObject));
194: mAlreadyResolvedReferencesByRefObject.put(pRefObject,
195: lReference);
196: }
197: // sLogger.debug("Returning " + lReference.getSystemId() + " URI for " + pRefObject);
198: return lReference;
199: }
200: }
|