svn commit: r14275 - trunk/src: app/src/org/argouml/profile app/src/org/argouml/profile/internal app/tests/org/argouml/kernel app/tests/org/argouml/profile model-mdr/src/org/argouml/model/mdr

[email protected]
Newsgroups gmane.comp.lang.uml.argouml.cvs
Message-ID <[email protected]>
Author: euluis
Date: 2008-04-01 16:43:57-0700
New Revision: 14275

Added:
   trunk/src/app/src/org/argouml/profile/CoreProfileReference.java   (contents, props changed)
   trunk/src/app/src/org/argouml/profile/ProfileReference.java   (contents, props changed)
   trunk/src/app/src/org/argouml/profile/UserProfileReference.java   (contents, props changed)
   trunk/src/app/tests/org/argouml/profile/TestCoreProfileReference.java   (contents, props changed)
   trunk/src/app/tests/org/argouml/profile/TestProfileReference.java   (contents, props changed)
   trunk/src/app/tests/org/argouml/profile/TestUserProfileReference.java   (contents, props changed)
Modified:
   trunk/src/app/src/org/argouml/profile/FileModelLoader.java
   trunk/src/app/src/org/argouml/profile/ProfileModelLoader.java
   trunk/src/app/src/org/argouml/profile/ReaderModelLoader.java
   trunk/src/app/src/org/argouml/profile/ResourceModelLoader.java
   trunk/src/app/src/org/argouml/profile/StreamModelLoader.java
   trunk/src/app/src/org/argouml/profile/URLModelLoader.java
   trunk/src/app/src/org/argouml/profile/UserDefinedProfile.java
   trunk/src/app/src/org/argouml/profile/ZipModelLoader.java
   trunk/src/app/src/org/argouml/profile/internal/ProfileJava.java
   trunk/src/app/src/org/argouml/profile/internal/ProfileUML.java
   trunk/src/app/tests/org/argouml/kernel/TestProjectWithProfiles.java
   trunk/src/app/tests/org/argouml/profile/ProfileMother.java
   trunk/src/app/tests/org/argouml/profile/TestProfileFacade.java
   trunk/src/app/tests/org/argouml/profile/TestReaderModelLoader.java
   trunk/src/model-mdr/src/org/argouml/model/mdr/MDRModelImplementation.java
   trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReaderImpl.java
   trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReferenceResolverImpl.java

Log:
issue 4946: uses the new ProfileReference idea which enables a more flexible way to have public references in the profiles

Added: trunk/src/app/src/org/argouml/profile/CoreProfileReference.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/CoreProfileReference.java?view=auto&rev=14275
==============================================================================
--- (empty file)
+++ trunk/src/app/src/org/argouml/profile/CoreProfileReference.java	2008-04-01 16:43:57-0700
@@ -0,0 +1,60 @@
+// $Id$
+// Copyright (c) 2008 The Regents of the University of California. All
+// Rights Reserved. Permission to use, copy, modify, and distribute this
+// software and its documentation without fee, and without a written
+// agreement is hereby granted, provided that the above copyright notice
+// and this paragraph appear in all copies. This software program and
+// documentation are copyrighted by The Regents of the University of
+// California. The software program and documentation are supplied "AS
+// IS", without any accompanying services from The Regents. The Regents
+// does not warrant that the operation of the program will be
+// uninterrupted or error-free. The end-user understands that the program
+// was developed for research purposes and is advised not to rely
+// exclusively on the program for any reason. IN NO EVENT SHALL THE
+// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
+// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+package org.argouml.profile;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * This class provides the base referencing and URL for ArgoUML core profiles.
+ *
+ * @author Luis Sergio Oliveira (euluis)
+ */
+public class CoreProfileReference extends ProfileReference {
+    
+    static final String PROFILES_RESOURCE_PATH = 
+        "/org/argouml/profile/profiles/";
+    
+    static final String PROFILES_BASE_URL = 
+        "http://argouml.org/profiles/uml14/";
+
+    /**
+     * Constructor, which builds a ProfileReference for ArgoUML core profiles 
+     * by: 
+     * <li>prefixing the fileName with {@link #PROFILES_RESOURCE_PATH} and 
+     * using this as the path;</li>
+     * <li>and prefixing the fileName with {@link #PROFILES_BASE_URL} and 
+     * using this as the publicReference.</li>
+     * 
+     * @param fileName the profile file name.
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public CoreProfileReference(String fileName) throws MalformedURLException {
+        super(PROFILES_RESOURCE_PATH + fileName, 
+            new URL(PROFILES_BASE_URL + fileName));
+        assert fileName != null 
+            : "null isn't acceptable as the profile file name.";
+    }
+}

Modified: trunk/src/app/src/org/argouml/profile/FileModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/FileModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/FileModelLoader.java&p2=trunk/src/app/src/org/argouml/profile/FileModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/FileModelLoader.java	(original)
+++ trunk/src/app/src/org/argouml/profile/FileModelLoader.java	2008-04-01 16:43:57-0700
@@ -40,13 +40,31 @@
 
     private static final Logger LOG = Logger.getLogger(FileModelLoader.class);
 
-    
+    @Deprecated
     public Collection loadModel(String modelFilename) throws ProfileException {
         LOG.info("Loading profile from file'" + modelFilename + "'");
         try {
             File modelFile = new File(modelFilename);
             URL url = modelFile.toURI().toURL();
-            return super.loadModel(url, modelFile.getName());
+            URL url2 = null;
+            try {
+                url2 = new URL(modelFile.getName());
+            } catch (MalformedURLException e) {
+                LOG.error("Exception", e);
+            }
+            return super.loadModel(url, url2);
+        } catch (MalformedURLException e) {
+            throw new ProfileException("Model file not found!");
+        }
+    }
+
+    public Collection loadModel(ProfileReference reference) 
+        throws ProfileException {
+        LOG.info("Loading profile from file'" + reference.getPath() + "'");
+        try {
+            File modelFile = new File(reference.getPath());
+            URL url = modelFile.toURI().toURL();
+            return super.loadModel(url, reference.getPublicReference());
         } catch (MalformedURLException e) {
             throw new ProfileException("Model file not found!");
         }

Modified: trunk/src/app/src/org/argouml/profile/ProfileModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/ProfileModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/ProfileModelLoader.java&p2=trunk/src/app/src/org/argouml/profile/ProfileModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/ProfileModelLoader.java	(original)
+++ trunk/src/app/src/org/argouml/profile/ProfileModelLoader.java	2008-04-01 16:43:57-0700
@@ -41,6 +41,20 @@
      * @return the set of defined packages
      * @throws ProfileException if the profile could not be loaded for some
      *                 reason
+     * @deprecated for 0.25.5 by euluis. 
+     * Use {@link #loadModel(ProfileReference)} instead.
      */
+    @Deprecated
     Collection loadModel(String path) throws ProfileException;  
+    
+    /**
+     * Load a model from the specified path.
+     * 
+     * @param reference the reference to the profile file, which contains the 
+     * path where the profile file can be found.
+     * @return the set of defined packages.
+     * @throws ProfileException if the profile could not be loaded for some
+     * reason.
+     */
+    Collection loadModel(ProfileReference reference) throws ProfileException;  
 }

Added: trunk/src/app/src/org/argouml/profile/ProfileReference.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/ProfileReference.java?view=auto&rev=14275
==============================================================================
--- (empty file)
+++ trunk/src/app/src/org/argouml/profile/ProfileReference.java	2008-04-01 16:43:57-0700
@@ -0,0 +1,76 @@
+// $Id$
+// Copyright (c) 2008 The Regents of the University of California. All
+// Rights Reserved. Permission to use, copy, modify, and distribute this
+// software and its documentation without fee, and without a written
+// agreement is hereby granted, provided that the above copyright notice
+// and this paragraph appear in all copies. This software program and
+// documentation are copyrighted by The Regents of the University of
+// California. The software program and documentation are supplied "AS
+// IS", without any accompanying services from The Regents. The Regents
+// does not warrant that the operation of the program will be
+// uninterrupted or error-free. The end-user understands that the program
+// was developed for research purposes and is advised not to rely
+// exclusively on the program for any reason. IN NO EVENT SHALL THE
+// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
+// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+package org.argouml.profile;
+
+import java.io.File;
+import java.net.URL;
+
+/**
+ * Support for the profile reference which internally to Argo implies having 
+ * both a public profile reference and the path to the profile file. 
+ * 
+ * @author Luis Sergio Oliveira (euluis)
+ */
+public class ProfileReference {
+
+    private String path;
+    private URL url;
+
+    /**
+     * Constructor. Note that this checks if the file name in path and in 
+     * publicReference are the same.
+     * 
+     * @param thePath the system path to the profile file.
+     * @param publicReference see {@link #getPublicReference()}.
+     */
+    public ProfileReference(String thePath, URL publicReference) {
+        File file = new File(thePath);
+        File fileFromPublicReference = new File(publicReference.getPath());
+        assert file.getName().equals(fileFromPublicReference.getName()) 
+            : "File name in path and in publicReference are different.";
+        path = thePath;
+        url = publicReference;
+    }
+
+    /**
+     * @return the path to the profile, being in principle this path the 
+     * system path to the profile file.
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * @return the public reference by which the profile will 
+     * be known in models that depend on it. I.e., this reference will prefix 
+     * the IDs of the profile model elements referred in the XMI of models 
+     * that depend on the profile for which the constructed ProfileReference 
+     * is used.
+     */
+    public URL getPublicReference() {
+        return url;
+    }
+
+}

Modified: trunk/src/app/src/org/argouml/profile/ReaderModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/ReaderModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/ReaderModelLoader.java&p2=trunk/src/app/src/org/argouml/profile/ReaderModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/ReaderModelLoader.java	(original)
+++ trunk/src/app/src/org/argouml/profile/ReaderModelLoader.java	2008-04-01 16:43:57-0700
@@ -34,7 +34,10 @@
 import org.xml.sax.InputSource;
 
 /**
- *
+ * TODO: this doesn't need a full ProfileReference since it uses the 
+ * reader handed in the constructor. It doesn't make much sense to make 
+ * its callers init the path to some name which it doesn't need... 
+ * 
  * @author Luis Sergio Oliveira (euluis)
  */
 public class ReaderModelLoader implements ProfileModelLoader {
@@ -53,12 +56,9 @@
         this.reader = theReader;
     }
 
-    /**
-     * @param path
-     * @return
-     * @throws ProfileException
-     * @see org.argouml.profile.ProfileModelLoader#loadModel(java.lang.String)
+    /* @see ProfileModelLoader#loadModel(String)
      */
+    @Deprecated
     public Collection loadModel(String path) throws ProfileException {
         if (reader != null) {
             try {
@@ -76,4 +76,26 @@
         throw new ProfileException("Profile not found!");
     }
 
+    /* @see ProfileModelLoader#loadModel(ProfileReference)
+     */
+    public Collection loadModel(ProfileReference reference) 
+        throws ProfileException {
+        if (reader != null) {
+            try {
+                XmiReader xmiReader = Model.getXmiReader();
+                InputSource inputSource = new InputSource(reader);
+                inputSource.setSystemId(reference.getPath());
+                inputSource.setPublicId(
+                        reference.getPublicReference().toString());
+                Collection elements = xmiReader.parse(inputSource, true);
+                return elements;
+            } catch (UmlException e) {
+                LOG.error("Exception while loading profile ", e);
+                throw new ProfileException("Invalid XMI data!");
+            }
+        }
+        LOG.error("Profile not found");
+        throw new ProfileException("Profile not found!");
+    }
+
 }

Modified: trunk/src/app/src/org/argouml/profile/ResourceModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/ResourceModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/ResourceModelLoader.java&p2=trunk/src/app/src/org/argouml/profile/ResourceModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/ResourceModelLoader.java	(original)
+++ trunk/src/app/src/org/argouml/profile/ResourceModelLoader.java	2008-04-01 16:43:57-0700
@@ -24,6 +24,8 @@
 
 package org.argouml.profile;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.Collection;
 
 import org.apache.log4j.Logger;
@@ -63,9 +65,23 @@
     /*
      * @see org.argouml.profile.ProfileModelLoader#loadModel(java.lang.String)
      */
+    @Deprecated
     public Collection loadModel(String path) throws ProfileException {
         LOG.info("Loading profile from resource'" + path + "'");
-        return super.loadModel(clazz.getResource(path), path);
+        URL url = null;
+        try {
+            url = new URL(path);
+        } catch (MalformedURLException e) {
+            LOG.error("Exception", e);
+        }
+        return super.loadModel(clazz.getResource(path), url);
+    }
+    
+    public Collection loadModel(ProfileReference reference) 
+        throws ProfileException {
+        LOG.info("Loading profile from resource'" + reference.getPath() + "'");
+        return super.loadModel(clazz.getResource(reference.getPath()), 
+            reference.getPublicReference());
     }
 
 }

Modified: trunk/src/app/src/org/argouml/profile/StreamModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/StreamModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/StreamModelLoader.java&p2=trunk/src/app/src/org/argouml/profile/StreamModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/StreamModelLoader.java	(original)
+++ trunk/src/app/src/org/argouml/profile/StreamModelLoader.java	2008-04-01 16:43:57-0700
@@ -25,6 +25,7 @@
 package org.argouml.profile;
 
 import java.io.InputStream;
+import java.net.URL;
 import java.util.Collection;
 
 import org.apache.log4j.Logger;
@@ -47,7 +48,8 @@
      * @return the model
      * @throws ProfileException if the XMIReader couldn't read the input stream
      */
-    public Collection loadModel(InputStream inputStream)
+    @Deprecated
+    public Collection loadModel(InputStream inputStream) 
         throws ProfileException {
         
         if (inputStream != null) {
@@ -64,4 +66,30 @@
         LOG.error("Profile not found");
         throw new ProfileException("Profile not found!");
     }
+
+    /**
+     * @param inputStream the stream from where the model should be loaded
+     * @param publicReference the URL to be used as the public reference of 
+     * the profile that will be loaded.
+     * @return the model
+     * @throws ProfileException if the XMIReader couldn't read the input stream
+     */
+    public Collection loadModel(InputStream inputStream, URL publicReference)
+        throws ProfileException {
+        
+        if (inputStream != null) {
+            try {
+                XmiReader xmiReader = Model.getXmiReader();
+                InputSource inputSource = new InputSource(inputStream);
+                inputSource.setPublicId(publicReference.toString());
+                Collection elements = xmiReader.parse(inputSource, true);
+                return elements;
+            } catch (UmlException e) {
+                LOG.error("Exception while loading profile ", e);
+                throw new ProfileException("Invalid XMI data!");
+            }
+        }
+        LOG.error("Profile not found");
+        throw new ProfileException("Profile not found!");
+    }
 }

Modified: trunk/src/app/src/org/argouml/profile/URLModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/URLModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/URLModelLoader.java&p2=trunk/src/app/src/org/argouml/profile/URLModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/URLModelLoader.java	(original)
+++ trunk/src/app/src/org/argouml/profile/URLModelLoader.java	2008-04-01 16:43:57-0700
@@ -45,12 +45,11 @@
     /**
      * @param url the url/system id to load
      * @param publicId the publicId for which the model will be known - must be 
-     *        equal in different machines in order to be possible to load the 
-     *        model
+     * equal in different machines in order to be possible to load the model.
      * @return the model
      * @throws ProfileException if the XMIReader couldn't read the profile
      */
-    public Collection loadModel(URL url, String publicId) 
+    public Collection loadModel(URL url, URL publicId) 
         throws ProfileException {
         if (url == null) {
             throw new ProfileException("Null profile URL");
@@ -58,7 +57,7 @@
         try {
             XmiReader xmiReader = Model.getXmiReader();
             InputSource inputSource = new InputSource(url.toExternalForm());
-            inputSource.setPublicId(publicId);
+            inputSource.setPublicId(publicId.toString());
             Collection elements = xmiReader.parse(inputSource, true);
             return elements;
         } catch (UmlException e) {

Modified: trunk/src/app/src/org/argouml/profile/UserDefinedProfile.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/UserDefinedProfile.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/UserDefinedProfile.java&p2=trunk/src/app/src/org/argouml/profile/UserDefinedProfile.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/UserDefinedProfile.java	(original)
+++ trunk/src/app/src/org/argouml/profile/UserDefinedProfile.java	2008-04-01 16:43:57-0700
@@ -26,6 +26,7 @@
 
 import java.io.File;
 import java.io.Reader;
+import java.net.MalformedURLException;
 import java.util.Collection;
 
 /**
@@ -49,15 +50,39 @@
     public UserDefinedProfile(File file) throws ProfileException {
         displayName = file.getName();
         modelFile = file;
-        model = new FileModelLoader().loadModel(modelFile.getPath());
+        ProfileReference reference = null;
+        try {
+            reference = new UserProfileReference(file.getPath());
+        } catch (MalformedURLException e) {
+            throw new ProfileException(
+                "Failed to create the ProfileReference.", e);
+        }
+        model = new FileModelLoader().loadModel(reference);
         fromZargo = false;
     }
 
     
+    /**
+     * A constructor that takes a file name and a reader, being the reader the 
+     * input method to get the profile model.
+     * 
+     * @param fileName name of the profile model file.
+     * @param reader a reader opened from where the profile model will be 
+     * loaded. 
+     * @throws ProfileException if something goes wrong in initializing the 
+     * profile.
+     */
     public UserDefinedProfile(String fileName, Reader reader) 
         throws ProfileException {
         displayName = fileName;
-        model = new ReaderModelLoader(reader).loadModel(fileName);
+        ProfileReference reference = null;
+        try {
+            reference = new UserProfileReference(fileName);
+        } catch (MalformedURLException e) {
+            throw new ProfileException(
+                "Failed to create the ProfileReference.", e);
+        }
+        model = new ReaderModelLoader(reader).loadModel(reference);
         fromZargo = true;
     }
 

Added: trunk/src/app/src/org/argouml/profile/UserProfileReference.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/UserProfileReference.java?view=auto&rev=14275
==============================================================================
--- (empty file)
+++ trunk/src/app/src/org/argouml/profile/UserProfileReference.java	2008-04-01 16:43:57-0700
@@ -0,0 +1,66 @@
+// $Id$
+// Copyright (c) 2008 The Regents of the University of California. All
+// Rights Reserved. Permission to use, copy, modify, and distribute this
+// software and its documentation without fee, and without a written
+// agreement is hereby granted, provided that the above copyright notice
+// and this paragraph appear in all copies. This software program and
+// documentation are copyrighted by The Regents of the University of
+// California. The software program and documentation are supplied "AS
+// IS", without any accompanying services from The Regents. The Regents
+// does not warrant that the operation of the program will be
+// uninterrupted or error-free. The end-user understands that the program
+// was developed for research purposes and is advised not to rely
+// exclusively on the program for any reason. IN NO EVENT SHALL THE
+// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
+// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+package org.argouml.profile;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * This class provides the base URL for user defined profiles.
+ *
+ * @author Luis Sergio Oliveira (euluis)
+ */
+public class UserProfileReference extends ProfileReference {
+
+    static final String DEFAULT_USER_PROFILE_BASE_URL = 
+        "http://argouml.org/user-profiles/";
+
+    /**
+     * Constructor that simply delegates to super.
+     * 
+     * @param thePath see thePath documentation in 
+     * {@link ProfileReference#ProfileReference(String, URL)}.
+     * @param publicReference see publicReference documentation in 
+     * {@link ProfileReference#ProfileReference(String, URL)}.
+     */
+    public UserProfileReference(String thePath, URL publicReference) {
+        super(thePath, publicReference);
+    }
+
+    /**
+     * Constructor, which builds a ProfileReference for a user defined profile 
+     * by prefixing the fileName with {@link #DEFAULT_USER_PROFILE_BASE_URL} 
+     * and using this as the publicReference.
+     * 
+     * @param path the profile absolute file name.
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public UserProfileReference(String path) throws MalformedURLException {
+        super(path, 
+            new URL(DEFAULT_USER_PROFILE_BASE_URL + new File(path).getName()));
+    }
+
+}

Modified: trunk/src/app/src/org/argouml/profile/ZipModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/ZipModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/ZipModelLoader.java&p2=trunk/src/app/src/org/argouml/profile/ZipModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/ZipModelLoader.java	(original)
+++ trunk/src/app/src/org/argouml/profile/ZipModelLoader.java	2008-04-01 16:43:57-0700
@@ -44,7 +44,7 @@
 
     private static final Logger LOG = Logger.getLogger(ZipModelLoader.class);
 
-
+    @Deprecated
     public Collection loadModel(String modelFilename) throws ProfileException {
         LOG.info("Loading profile from ZIP '" + modelFilename + "'");
 
@@ -82,6 +82,45 @@
         
         throw new ProfileException("Profile could not be loaded!");
     }
+    
+    public Collection loadModel(ProfileReference reference) 
+        throws ProfileException {
+        LOG.info("Loading profile from ZIP '" + reference.getPath() + "'");
+
+        InputStream is = null;
+        File modelFile = new File(reference.getPath());
+        // TODO: This is in the wrong place.  It's not profile specific.
+        // It needs to be moved to main XMI reading code. - tfm 20060326
+        if (reference.getPath().endsWith("zip")) {
+            String filename = modelFile.getName();
+            String extension = filename.substring(filename.indexOf('.'),
+                    filename.lastIndexOf('.'));
+            String path = modelFile.getParent();
+            // Add the path of the model to the search path, so we can
+            // read dependent models
+            if (path != null) {
+                System.setProperty("org.argouml.model.modules_search_path",
+                        path);
+            }
+            try {
+                is = openZipStreamAt(modelFile.toURI().toURL(), extension);
+            } catch (MalformedURLException e) {
+                LOG.error("Exception while loading profile '" + reference.getPath()
+                        + "'", e);
+                throw new ProfileException(e);
+            } catch (IOException e) {
+                LOG.error("Exception while loading profile '" + reference.getPath()
+                        + "'", e);
+                throw new ProfileException(e);
+            }
+
+            if (is != null) {
+                return super.loadModel(is, reference.getPublicReference());
+            }
+        }
+        
+        throw new ProfileException("Profile could not be loaded!");
+    }
 
     /**
      * Open a ZipInputStream to the first file found with a given extension.

Modified: trunk/src/app/src/org/argouml/profile/internal/ProfileJava.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/internal/ProfileJava.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/internal/ProfileJava.java&p2=trunk/src/app/src/org/argouml/profile/internal/ProfileJava.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/internal/ProfileJava.java	(original)
+++ trunk/src/app/src/org/argouml/profile/internal/ProfileJava.java	2008-04-01 16:43:57-0700
@@ -24,15 +24,18 @@
 
 package org.argouml.profile.internal;
 
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collection;
 
 import org.argouml.model.Model;
+import org.argouml.profile.CoreProfileReference;
 import org.argouml.profile.DefaultTypeStrategy;
 import org.argouml.profile.Profile;
 import org.argouml.profile.ProfileException;
 import org.argouml.profile.ProfileFacade;
 import org.argouml.profile.ProfileModelLoader;
+import org.argouml.profile.ProfileReference;
 import org.argouml.profile.ResourceModelLoader;
 
 /**
@@ -42,8 +45,7 @@
  */
 public class ProfileJava extends Profile {
 
-    private static final String PROFILE_FILE = 
-        PROFILE_DIR + "default-java.xmi";
+    private static final String PROFILE_FILE = "default-java.xmi";
     static final String NAME = "Java";
     
     private ProfileModelLoader profileModelLoader;
@@ -56,7 +58,14 @@
     @SuppressWarnings("unchecked")
     ProfileJava(Profile uml) throws ProfileException {
         profileModelLoader = new ResourceModelLoader();
-        model = profileModelLoader.loadModel(PROFILE_FILE);
+        ProfileReference profileReference = null;
+        try {
+            profileReference = new CoreProfileReference(PROFILE_FILE);
+        } catch (MalformedURLException e) {
+            throw new ProfileException(
+                "Exception while creating profile reference.", e);
+        }
+        model = profileModelLoader.loadModel(profileReference);
 
         if (model == null) {
             model = new ArrayList();

Modified: trunk/src/app/src/org/argouml/profile/internal/ProfileUML.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/src/org/argouml/profile/internal/ProfileUML.java?view=diff&rev=14275&p1=trunk/src/app/src/org/argouml/profile/internal/ProfileUML.java&p2=trunk/src/app/src/org/argouml/profile/internal/ProfileUML.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/src/org/argouml/profile/internal/ProfileUML.java	(original)
+++ trunk/src/app/src/org/argouml/profile/internal/ProfileUML.java	2008-04-01 16:43:57-0700
@@ -24,15 +24,18 @@
 
 package org.argouml.profile.internal;
 
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collection;
 
 import org.argouml.model.Model;
+import org.argouml.profile.CoreProfileReference;
 import org.argouml.profile.DefaultTypeStrategy;
 import org.argouml.profile.FormatingStrategy;
 import org.argouml.profile.Profile;
 import org.argouml.profile.ProfileException;
 import org.argouml.profile.ProfileModelLoader;
+import org.argouml.profile.ProfileReference;
 import org.argouml.profile.ResourceModelLoader;
 
 /**
@@ -42,8 +45,7 @@
  */
 public class ProfileUML extends Profile {
     
-    private static final String PROFILE_FILE = 
-        PROFILE_DIR + "default-uml14.xmi";
+    private static final String PROFILE_FILE = "default-uml14.xmi";
 
     static final String NAME = "UML 1.4";
     
@@ -59,7 +61,14 @@
     ProfileUML() throws ProfileException {
         formatingStrategy = new JavaFormatingStrategy();
         profileModelLoader = new ResourceModelLoader();
-        model = profileModelLoader.loadModel(PROFILE_FILE);
+        ProfileReference profileReference = null;
+        try {
+            profileReference = new CoreProfileReference(PROFILE_FILE);
+        } catch (MalformedURLException e) {
+            throw new ProfileException(
+                "Exception while creating profile reference.", e);
+        }
+        model = profileModelLoader.loadModel(profileReference);
 
         if (model == null) {
             model = new ArrayList();

Modified: trunk/src/app/tests/org/argouml/kernel/TestProjectWithProfiles.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/tests/org/argouml/kernel/TestProjectWithProfiles.java?view=diff&rev=14275&p1=trunk/src/app/tests/org/argouml/kernel/TestProjectWithProfiles.java&p2=trunk/src/app/tests/org/argouml/kernel/TestProjectWithProfiles.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/tests/org/argouml/kernel/TestProjectWithProfiles.java	(original)
+++ trunk/src/app/tests/org/argouml/kernel/TestProjectWithProfiles.java	2008-04-01 16:43:57-0700
@@ -181,7 +181,11 @@
         assertNotNull(returnParam);
         // Return type was java.util.List from Java profile - should be gone
         returnParamType = getFacade().getType(returnParam);
-        assertNull(returnParamType);
+        // TODO: with new reference resolving scheme, the model sub-system will
+        // cache the systemId of the profile, open it and resolve the profile 
+        // on its own. Thus, the java.util.List will be found and the return 
+        // value will be present again...
+        assertNotNull(returnParamType);
     }
 
     private void checkJavaListTypeExistsAndMatchesReturnParamType(
@@ -330,14 +334,18 @@
         profileManager.removeProfile(userDefinedProfile);
         profileManager.removeSearchPathDirectory(testCaseDir.getAbsolutePath());
         // load the project
-        // FIXME: the next statement fails because the zargo's XMI model is 
-        // being loaded before the profile file, therefore it doesn't have a 
-        // chance to resolve the dependencies in the model.
+        // TODO: the following now does not throw since we the nre reference 
+        // resolving scheme, the model sub-system caches the system ID 
+        // references and resolves it on its own without the help of the 
+        // project.
         project = persister.doLoad(file);
         project.postLoad();
         // assert that the model element that depends on the profile is 
         // consistent
         fooClass = project.findType("Foo", false);
+        // FIXME: this will fail because the project does not have knowledge 
+        // of the loaded profile and doesn't include it on the models to 
+        // search for the type.
         assertNotNull(fooClass);
         Collection fooStereotypes = getFacade().getStereotypes(fooClass);
         assertEquals(1, fooStereotypes.size());

Modified: trunk/src/app/tests/org/argouml/profile/ProfileMother.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/tests/org/argouml/profile/ProfileMother.java?view=diff&rev=14275&p1=trunk/src/app/tests/org/argouml/profile/ProfileMother.java&p2=trunk/src/app/tests/org/argouml/profile/ProfileMother.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/tests/org/argouml/profile/ProfileMother.java	(original)
+++ trunk/src/app/tests/org/argouml/profile/ProfileMother.java	2008-04-01 16:43:57-0700
@@ -64,6 +64,12 @@
      */
     public static final String STEREOTYPE_NAME_ST = "st";
 
+    /**
+     * Create a simple profile model with a class named "foo" and with a 
+     * stereotype named "st".
+     * 
+     * @return the profile model.
+     */
     public Object createSimpleProfileModel() {
         Object model = getModelManagementFactory().createModel();
         Object profileStereotype = getProfileStereotype();
@@ -108,6 +114,13 @@
         return umlProfileModel;
     }
 
+    /**
+     * Save the profile model into the given file.
+     * 
+     * @param model the profile model.
+     * @param file the file into which to save the profile model.
+     * @throws IOException if IO goes wrong.
+     */
     public void saveProfileModel(Object model, File file) throws IOException {
         FileOutputStream fileOut = new FileOutputStream(file);
         try {

Added: trunk/src/app/tests/org/argouml/profile/TestCoreProfileReference.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/tests/org/argouml/profile/TestCoreProfileReference.java?view=auto&rev=14275
==============================================================================
--- (empty file)
+++ trunk/src/app/tests/org/argouml/profile/TestCoreProfileReference.java	2008-04-01 16:43:57-0700
@@ -0,0 +1,83 @@
+// $Id$
+// Copyright (c) 2008 The Regents of the University of California. All
+// Rights Reserved. Permission to use, copy, modify, and distribute this
+// software and its documentation without fee, and without a written
+// agreement is hereby granted, provided that the above copyright notice
+// and this paragraph appear in all copies. This software program and
+// documentation are copyrighted by The Regents of the University of
+// California. The software program and documentation are supplied "AS
+// IS", without any accompanying services from The Regents. The Regents
+// does not warrant that the operation of the program will be
+// uninterrupted or error-free. The end-user understands that the program
+// was developed for research purposes and is advised not to rely
+// exclusively on the program for any reason. IN NO EVENT SHALL THE
+// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
+// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+package org.argouml.profile;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests of the {@link CoreProfileReference} class.
+ * 
+ * @author Luis Sergio Oliveira (euluis)
+ */
+public class TestCoreProfileReference extends TestCase {
+    
+    /**
+     * Tests {@link CoreProfileReference#CoreProfileReference(String)}.
+     * 
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public void testCtorHappyPath() throws MalformedURLException {
+        String fileName = "profileName.xmi";
+        ProfileReference reference = new CoreProfileReference(fileName);
+        assertEquals(CoreProfileReference.PROFILES_RESOURCE_PATH + fileName, 
+            reference.getPath());
+        assertEquals(
+            new URL(CoreProfileReference.PROFILES_BASE_URL + fileName), 
+            reference.getPublicReference());
+    }
+    
+    /**
+     * Tests that the constructor checks for empty file name.
+     * 
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public void testCtorFailsWhenFileNameIsEmpty() 
+        throws MalformedURLException {
+        try {
+            new CoreProfileReference("");
+            fail("Expecting AssertionError due to empty file name.");
+        } catch (AssertionError e) {
+            // expected
+        }
+    }
+    
+    /**
+     * Tests that the constructor checks for null file name.
+     * 
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public void testCtorFailsWhenFileNameIsNull() 
+        throws MalformedURLException {
+        try {
+            new CoreProfileReference(null);
+            fail("Expecting AssertionError due to null file name.");
+        } catch (AssertionError e) {
+            // expected
+        }
+    }
+}

Modified: trunk/src/app/tests/org/argouml/profile/TestProfileFacade.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/tests/org/argouml/profile/TestProfileFacade.java?view=diff&rev=14275&p1=trunk/src/app/tests/org/argouml/profile/TestProfileFacade.java&p2=trunk/src/app/tests/org/argouml/profile/TestProfileFacade.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/tests/org/argouml/profile/TestProfileFacade.java	(original)
+++ trunk/src/app/tests/org/argouml/profile/TestProfileFacade.java	2008-04-01 16:43:57-0700
@@ -54,6 +54,9 @@
         super.tearDown();
     }
 
+    /**
+     * Test {@link ProfileFacade#getManager()} before initialization.
+     */
     public void testGetManagerBeforeInitialisationThrows() {
         ProfileFacade.reset();
         try {
@@ -64,6 +67,9 @@
         }
     }
     
+    /**
+     * Test {@link ProfileFacade#register(Profile)}.
+     */
     public void testRegister() {
         manager.registerProfile(null);
         managerCtrl.replay();
@@ -72,6 +78,9 @@
         managerCtrl.verify();
     }
 
+    /**
+     * Test {@link ProfileFacade#remove(Profile)}.
+     */
     public void testRemove() {
         manager.removeProfile(null);
         managerCtrl.replay();

Added: trunk/src/app/tests/org/argouml/profile/TestProfileReference.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/tests/org/argouml/profile/TestProfileReference.java?view=auto&rev=14275
==============================================================================
--- (empty file)
+++ trunk/src/app/tests/org/argouml/profile/TestProfileReference.java	2008-04-01 16:43:57-0700
@@ -0,0 +1,95 @@
+// $Id$
+// Copyright (c) 2008 The Regents of the University of California. All
+// Rights Reserved. Permission to use, copy, modify, and distribute this
+// software and its documentation without fee, and without a written
+// agreement is hereby granted, provided that the above copyright notice
+// and this paragraph appear in all copies. This software program and
+// documentation are copyrighted by The Regents of the University of
+// California. The software program and documentation are supplied "AS
+// IS", without any accompanying services from The Regents. The Regents
+// does not warrant that the operation of the program will be
+// uninterrupted or error-free. The end-user understands that the program
+// was developed for research purposes and is advised not to rely
+// exclusively on the program for any reason. IN NO EVENT SHALL THE
+// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
+// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+package org.argouml.profile;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for the ProfileReference class.
+ *
+ * @author Luis Sergio Oliveira (euluis)
+ */
+public class TestProfileReference extends TestCase {
+    
+    /**
+     * Test correct call to constructor.
+     * 
+     * @throws MalformedURLException if the URL is incorrect.
+     */
+    public void testCtorHappyPath() throws MalformedURLException {
+        new ProfileReference("systemId/name.xmi", 
+                new URL("file:///publicId/name.xmi"));
+    }
+    
+    /**
+     * Test call to constructor with inconsistent file names in the path and 
+     * the publicReference arguments.
+     * 
+     * NOTE: to run successfully this test you'll have to enable assertions.
+     * 
+     * @throws MalformedURLException if the URL is incorrect.
+     */
+    public void testCtorInconsistentFileNameDetected() 
+        throws MalformedURLException {
+        try {
+            new ProfileReference("/org/argouml/language/x/profile/name.xmi", 
+                    new URL("http://argouml-x.tigris.org/iconsistentName.xmi"));
+            fail("Expected an AssertionError to be thrown!");
+        } catch (MalformedURLException e) {
+            throw e;
+        } catch (AssertionError e) {
+            // expected
+        }
+    }
+    
+    /**
+     * Checks that the path handed to the constructor is correctly returned by 
+     * {@link ProfileReference#getPath()}.
+     * 
+     * @throws MalformedURLException if the URL is incorrect.
+     */
+    public void testGetPath() throws MalformedURLException {
+        String path = "/org/argouml/language/x/profile/name.xmi";
+        ProfileReference profileReference = new ProfileReference(
+            path, new URL("http://x.org/name.xmi"));
+        assertEquals(path, profileReference.getPath());
+    }
+    
+    /**
+     * Checks that the publicReference handed to the constructor is correctly 
+     * returned by {@link ProfileReference#getPublicReference()}.
+     * 
+     * @throws MalformedURLException if the URL is incorrect.
+     */
+    public void testGetPublicReference() throws MalformedURLException {
+        URL publicReference = new URL("http://x.org/name.xmi");
+        ProfileReference profileReference = new ProfileReference(
+            "/org/argouml/language/x/profile/name.xmi", publicReference);
+        assertEquals(publicReference, profileReference.getPublicReference());
+    }
+}

Modified: trunk/src/app/tests/org/argouml/profile/TestReaderModelLoader.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/tests/org/argouml/profile/TestReaderModelLoader.java?view=diff&rev=14275&p1=trunk/src/app/tests/org/argouml/profile/TestReaderModelLoader.java&p2=trunk/src/app/tests/org/argouml/profile/TestReaderModelLoader.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/app/tests/org/argouml/profile/TestReaderModelLoader.java	(original)
+++ trunk/src/app/tests/org/argouml/profile/TestReaderModelLoader.java	2008-04-01 16:43:57-0700
@@ -42,11 +42,20 @@
  * @author Luis Sergio Oliveira (euluis)
  */
 public class TestReaderModelLoader extends TestCase {
+    /**
+     * Test the constructor.
+     */
     public void testCtor() {
         Reader reader = new StringReader("dummy string");
         new ReaderModelLoader(reader);
     }
     
+    /**
+     * Test {@link ReaderModelLoader#loadModel(ProfileReference)}.
+     * 
+     * @throws IOException upon IO errors.
+     * @throws ProfileException upon problems with profiles.
+     */
     public void testLoad() throws IOException, ProfileException {
         InitializeModel.initializeDefault();
         ProfileMother mother = new ProfileMother();
@@ -55,8 +64,10 @@
         File file = new File(testDir, "testSaveProfileModel.xmi");
         mother.saveProfileModel(model, file);
         Reader reader = new FileReader(file);
+        ProfileReference profileReference = new UserProfileReference(
+            file.getAbsolutePath());
         Collection models = new ReaderModelLoader(reader).
-            loadModel(file.getName());
+            loadModel(profileReference);
         assertNotNull(models);
         assertTrue(models.size() >= 1);
     }

Added: trunk/src/app/tests/org/argouml/profile/TestUserProfileReference.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/app/tests/org/argouml/profile/TestUserProfileReference.java?view=auto&rev=14275
==============================================================================
--- (empty file)
+++ trunk/src/app/tests/org/argouml/profile/TestUserProfileReference.java	2008-04-01 16:43:57-0700
@@ -0,0 +1,90 @@
+// $Id$
+// Copyright (c) 2008 The Regents of the University of California. All
+// Rights Reserved. Permission to use, copy, modify, and distribute this
+// software and its documentation without fee, and without a written
+// agreement is hereby granted, provided that the above copyright notice
+// and this paragraph appear in all copies. This software program and
+// documentation are copyrighted by The Regents of the University of
+// California. The software program and documentation are supplied "AS
+// IS", without any accompanying services from The Regents. The Regents
+// does not warrant that the operation of the program will be
+// uninterrupted or error-free. The end-user understands that the program
+// was developed for research purposes and is advised not to rely
+// exclusively on the program for any reason. IN NO EVENT SHALL THE
+// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
+// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+package org.argouml.profile;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for UserProfileReference class.
+ *
+ * @author Luis Sergio Oliveira (euluis)
+ */
+public class TestUserProfileReference extends TestCase {
+    
+    /**
+     * Tests {@link UserProfileReference#UserProfileReference(String)} in the 
+     * happy path.
+     * 
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public void testCtorHappyPath() throws MalformedURLException {
+        String fileName = "profileName.xmi";
+        // [euluis] Using Windows style initial path, don't know if this fails 
+        // in *nixes.
+        String path = "C:" + File.separatorChar + "userProfilesDir" 
+            + File.separatorChar + fileName;
+        ProfileReference reference = new UserProfileReference(path);
+        assertEquals(path, reference.getPath());
+        assertEquals(
+            new URL(UserProfileReference.DEFAULT_USER_PROFILE_BASE_URL 
+                + fileName), 
+            reference.getPublicReference());
+    }
+    
+    /**
+     * Tests that the constructor checks for empty file name.
+     * 
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public void testCtorFailsWhenFileNameIsEmpty() 
+        throws MalformedURLException {
+        try {
+            new UserProfileReference("");
+            fail("Expecting AssertionError due to empty file name.");
+        } catch (AssertionError e) {
+            // expected
+        }
+    }
+    
+    /**
+     * Tests that the constructor checks for null file name.
+     * 
+     * @throws MalformedURLException if the built URL is incorrect.
+     */
+    public void testCtorFailsWhenFileNameIsNull() 
+        throws MalformedURLException {
+        try {
+            new UserProfileReference(null);
+            fail("Expecting NullPointerException due to null path.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+    
+}

Modified: trunk/src/model-mdr/src/org/argouml/model/mdr/MDRModelImplementation.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/model-mdr/src/org/argouml/model/mdr/MDRModelImplementation.java?view=diff&rev=14275&p1=trunk/src/model-mdr/src/org/argouml/model/mdr/MDRModelImplementation.java&p2=trunk/src/model-mdr/src/org/argouml/model/mdr/MDRModelImplementation.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/model-mdr/src/org/argouml/model/mdr/MDRModelImplementation.java	(original)
+++ trunk/src/model-mdr/src/org/argouml/model/mdr/MDRModelImplementation.java	2008-04-01 16:43:57-0700
@@ -185,8 +185,8 @@
      * Set of known public IDs of models that could be used to resolve URLs 
      * from model element IDs.
      */
-    private Set<String> publicIds = 
-        Collections.synchronizedSet(new HashSet<String>());
+    private Map<String, String> public2SystemIds = 
+        Collections.synchronizedMap(new HashMap<String, String>());
 
     /**
      * @return Returns the root UML Factory package for user model.
@@ -669,8 +669,8 @@
         return objectToId;
     }
     
-    Set<String> getPublicIds() {
-        return publicIds;
+    Map<String, String> getPublic2SystemIds() {
+        return public2SystemIds;
     }
 
     public CommandStack getCommandStack() {

Modified: trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReaderImpl.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReaderImpl.java?view=diff&rev=14275&p1=trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReaderImpl.java&p2=trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReaderImpl.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReaderImpl.java	(original)
+++ trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReaderImpl.java	2008-04-01 16:43:57-0700
@@ -144,8 +144,8 @@
 
             resolver = new XmiReferenceResolverImpl(new RefPackage[] {extent},
                     config, modelImpl.getObjectToId(), 
-                    modelImpl.getPublicIds(), searchDirs, profile, 
-                    inputSource.getPublicId());
+                    modelImpl.getPublic2SystemIds(), searchDirs, profile, 
+                    inputSource.getPublicId(), inputSource.getSystemId());
             config.setReferenceResolver(resolver);
             
             XMIReader xmiReader =

Modified: trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReferenceResolverImpl.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReferenceResolverImpl.java?view=diff&rev=14275&p1=trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReferenceResolverImpl.java&p2=trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReferenceResolverImpl.java&r1=14274&r2=14275
==============================================================================
--- trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReferenceResolverImpl.java	(original)
+++ trunk/src/model-mdr/src/org/argouml/model/mdr/XmiReferenceResolverImpl.java	2008-04-01 16:43:57-0700
@@ -36,7 +36,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import javax.jmi.reflect.RefObject;
 import javax.jmi.reflect.RefPackage;
@@ -76,14 +75,6 @@
     private static final Logger LOG =
         Logger.getLogger(XmiReferenceResolverImpl.class);
     
-    private static final String PROFILE_RESOURCE_PATH = 
-        "/org/argouml/profile/profiles/";
-    private static final String PROFILE_BASE_URL = 
-        "http://argouml.org/profiles/uml14";
-
-    private static final String USER_PROFILE_BASE_URL = 
-        "http://argouml.org/user-profiles/";
-    
     private Map<String, Object> idToObjects = 
         Collections.synchronizedMap(new HashMap<String, Object>());
 
@@ -127,25 +118,36 @@
     
     private boolean profile;
 
-    private Set<String> modelsPublicIds;
+    private Map<String, String> public2SystemIds;
 
     private String modelPublicId;
     
     /**
      * Constructor.
+     * @param systemId 
      * @see org.netbeans.lib.jmi.xmi.XmiContext#XmiContext(javax.jmi.reflect.RefPackage[], org.netbeans.api.xmi.XMIInputConfig)
      * (see also {link org.netbeans.api.xmi.XMIReferenceResolver})
      */
     XmiReferenceResolverImpl(RefPackage[] extents, XMIInputConfig config,
-            Map<String, XmiReference> objectToIdMap, Set<String> publicIds, 
-            List<String> searchDirs, boolean isProfile, String publicId) {
+            Map<String, XmiReference> objectToIdMap, 
+            Map<String, String> publicIds, List<String> searchDirs, 
+            boolean isProfile, String publicId, String systemId) {
         super(extents, config);
         objectsToId = objectToIdMap;
         modulesPath = searchDirs;
         profile = isProfile;
-        modelsPublicIds = publicIds;
+        public2SystemIds = publicIds;
         modelPublicId = publicId;
-        if (isProfile) modelsPublicIds.add(publicId);
+        if (isProfile) {
+            if (public2SystemIds.containsKey(modelPublicId)) {
+                LOG.warn("Either an already loaded profile is being re-read " 
+                    + "or a profile with the same publicId is being loaded! " 
+                    + "publicId = \"" + publicId + "\"; existing systemId = \""
+                    + public2SystemIds.get(publicId) + "\"; new systemId = \"" 
+                    + systemId + "\".");
+            }
+            public2SystemIds.put(publicId, systemId);
+        }
     }
 
     /**
@@ -182,13 +184,7 @@
         }
 
         if (profile) {
-            if (systemId.contains(PROFILE_RESOURCE_PATH))
-                systemId = PROFILE_BASE_URL + getSuffix(systemId);
-            else if (systemId.contains("file:/")) {
-                // user defined profile - replace path with corresponding label
-                systemId = USER_PROFILE_BASE_URL + modelPublicId;
-            } else 
-                systemId = PROFILE_BASE_URL + modelPublicId;
+            systemId = modelPublicId;
         } else if (systemId == topSystemId) {
             systemId = null;
         } else if (reverseUrlMap.get(systemId) != null) {
@@ -276,8 +272,15 @@
 
         // Several tries to construct a URL that really exists.
         if (modelUrl == null) {
-            // If systemId is a valid URL, simply use it
-            modelUrl = getValidURL(fixupURL(systemId));
+            if (public2SystemIds.containsKey(systemId)) {
+                // If systemId is publicId previously mapped from a systemId, 
+                // try to use the systemId.
+                modelUrl = getValidURL(public2SystemIds.get(systemId));
+            }
+            if (modelUrl == null) {
+                // If systemId is a valid URL, simply use it.
+                modelUrl = getValidURL(fixupURL(systemId));
+            }
             if (modelUrl == null) {
                 // Try to find suffix in module list.
                 String modelUrlAsString = findModuleURL(suffix);
@@ -362,7 +365,7 @@
                 return fixupURL(urlString);
             }
         }
-        if (modelsPublicIds.contains(moduleName)) {
+        if (public2SystemIds.containsKey(moduleName)) {
             if (LOG.isDebugEnabled())
                 LOG.debug("Couldn't find user model (\"" + moduleName 
                     + "\") in modulesPath, attempt " 
@@ -416,13 +419,8 @@
     private URL findModelUrlOnClasspath(String systemId) {
         final String dot = ".";
         String modelName = systemId;
-        if (systemId.startsWith(PROFILE_BASE_URL)) {
-            String publicId = systemId.substring(PROFILE_BASE_URL.length());
-            if (modelsPublicIds.contains(publicId)) {
-                modelName = publicId;
-            } else { 
-                modelName = PROFILE_RESOURCE_PATH + publicId;
-            }
+        if (public2SystemIds.containsKey(systemId)) {
+            modelName = public2SystemIds.get(systemId);
         } else {
             int filenameIndex = systemId.lastIndexOf("/");
             if (filenameIndex > 0) {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.