// $Id: ProfileConfigurationFilePersister.java 14814 2008-05-28 05:34:43Z tfmorris $
// Copyright (c) 2007-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.persistence;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.argouml.application.helpers.ApplicationVersion;
import org.argouml.configuration.Configuration;
import org.argouml.kernel.ProfileConfiguration;
import org.argouml.kernel.Project;
import org.argouml.kernel.ProjectMember;
import org.argouml.model.Model;
import org.argouml.model.UmlException;
import org.argouml.model.XmiWriter;
import org.argouml.profile.Profile;
import org.argouml.profile.ProfileFacade;
import org.argouml.profile.ProfileManager;
import org.argouml.profile.UserDefinedProfile;
/**
* Persister for project's profile configuration.
*
* @author maurelio1234
*/
public class ProfileConfigurationFilePersister extends MemberFilePersister {
private static final Logger LOG =
Logger.getLogger(ProfileConfigurationFilePersister.class);
/*
* @see org.argouml.persistence.MemberFilePersister#getMainTag()
*/
public String getMainTag() {
return "profile";
}
/*
* @see org.argouml.persistence.MemberFilePersister#load(org.argouml.kernel.Project, java.io.InputStream)
*/
public void load(Project project, InputStream inputStream)
throws OpenException {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
inputStream));
String line = null;
while (true) {
line = br.readLine();
if (line.trim().equals("<profile>")) {
break;
}
}
Collection<Profile> profiles = new ArrayList<Profile>();
while (true) {
line = br.readLine().trim();
if (line.equals("</profile>")) {
break;
}
Profile profile = null;
if (line.equals("<userDefined>")) {
profile = handleUserDefinedProfile(br);
// consumes the </userDefined>
br.readLine();
} else if (line.equals("<plugin>")) {
profile = handlePluginProfile(br);
// consumes closing tag
br.readLine();
}
if (profile != null) {
profiles.add(profile);
}
}
ProfileConfiguration pc = new ProfileConfiguration(project,
profiles);
project.setProfileConfiguration(pc);
} catch (Exception e) {
if (e instanceof OpenException) {
throw (OpenException) e;
}
throw new OpenException(e);
}
}
private static Profile handlePluginProfile(BufferedReader br)
throws IOException, XmiReferenceException {
Profile profile;
String className = br.readLine().trim();
profile = ProfileFacade.getManager().getProfileForClass(
className);
if (profile == null)
throw new XmiReferenceException(
"Plugin profile \"" + className
+ "\" is not available in installation.", null);
return profile;
}
private static Profile handleUserDefinedProfile(BufferedReader br)
throws IOException, XmiReferenceException {
String line;
Profile profile;
line = br.readLine().trim();
String fileName = line.substring(line.indexOf(">") + 1,
line.indexOf("</")).trim();
// consumes the <model> tag
br.readLine();
StringBuffer xmi = new StringBuffer();
while (true) {
line = br.readLine();
if (line == null || line.contains("</model>")) {
break;
}
xmi.append(line + "\n");
}
ProfileManager profileManager = ProfileFacade.getManager();
profile = getMatchingUserDefinedProfile(fileName,
profileManager);
if (profile == null) {
throw new XmiReferenceException(
"User defined profile \"" + fileName
+ "\" isn't available in the current configuration.",
null);
// Use XMI as a fall back alternative when the
// file for the user defined profile isn't found by the
// profile manager.
// TODO: work in progress, see issue 5039
// addUserDefinedProfile(fileName, xmi, profileManager);
// profile = getMatchingUserDefinedProfile(fileName,
// profileManager);
// assert profile != null
// : "Profile should have been found now.";
}
return profile;
}
/**
* Register a user defined profile in the profileManager, using the backup
* XMI file from the project being loaded.
* <p>
* <em>NOTE:</em> This has the side effect of permanently registering the
* profile which may not be what the user wants.
*
* @param fileName name of original XMI file that the author of the project
* used when creating the UserDefinedProfile.
* @param xmi the contents of the XMI file.
* @param profileManager the {@link ProfileManager}.
* @throws IOException on any i/o error
*/
private void addUserDefinedProfile(String fileName, StringBuffer xmi,
ProfileManager profileManager) throws IOException {
File profilesDirectory = getProfilesDirectory(profileManager);
File profileFile = new File(profilesDirectory, fileName);
FileWriter writer = new FileWriter(profileFile);
writer.write(xmi.toString());
writer.close();
LOG.info("Wrote user defined profile \"" + profileFile
+ "\", with size " + xmi.length() + ".");
if (isSomeProfileDirectoryConfigured(profileManager))
profileManager.refreshRegisteredProfiles();
else
profileManager.addSearchPathDirectory(
profilesDirectory.getAbsolutePath());
}
private static Profile getMatchingUserDefinedProfile(String fileName,
ProfileManager profileManager) {
for (Profile candidateProfile
: profileManager.getRegisteredProfiles()) {
if (candidateProfile instanceof UserDefinedProfile) {
UserDefinedProfile userProfile =
(UserDefinedProfile) candidateProfile;
if (userProfile.getDisplayName().equals(fileName)) {
return userProfile;
}
}
}
return null;
}
private static File getProfilesDirectory(ProfileManager profileManager) {
if (isSomeProfileDirectoryConfigured(profileManager)) {
List<String> directories =
profileManager.getSearchPathDirectories();
return new File(directories.get(0));
} else {
File userSettingsFile = new File(
Configuration.getFactory().getConfigurationHandler().
getDefaultPath());
return userSettingsFile.getParentFile();
}
}
private static boolean isSomeProfileDirectoryConfigured(
ProfileManager profileManager) {
return profileManager.getSearchPathDirectories().size() > 0;
}
/*
* @see org.argouml.persistence.MemberFilePersister#save(org.argouml.kernel.ProjectMember, java.io.Writer, boolean)
*/
@Override
@Deprecated
@SuppressWarnings("deprecation")
public void save(ProjectMember member, Writer writer, boolean xmlFragment)
throws SaveException {
PrintWriter w = new PrintWriter(writer);
saveProjectMember(member, w);
}
/*
* @see org.argouml.persistence.MemberFilePersister#save(org.argouml.kernel.ProjectMember, java.io.OutputStream)
*/
public void save(ProjectMember member, OutputStream stream)
throws SaveException {
PrintWriter w = new PrintWriter(stream);
saveProjectMember(member, w);
w.flush();
}
private void saveProjectMember(ProjectMember member, PrintWriter w)
throws SaveException {
try {
if (member instanceof ProfileConfiguration) {
ProfileConfiguration pc = (ProfileConfiguration) member;
w.println("<?xml version = \"1.0\" encoding = \"UTF-8\" ?>");
w.println("<!DOCTYPE profile SYSTEM \"profile.dtd\" >");
w.println("<profile>");
Iterator it = pc.getProfiles().iterator();
while (it.hasNext()) {
Profile profile = (Profile) it.next();
if (profile instanceof UserDefinedProfile) {
UserDefinedProfile uprofile =
(UserDefinedProfile) profile;
w.println("\t\t<userDefined>");
w.println("\t\t\t<filename>"
+ uprofile.getModelFile().getName()
+ "</filename>");
w.println("\t\t\t<model>");
printModelXMI(w, uprofile.getProfilePackages());
w.println("\t\t\t</model>");
w.println("\t\t</userDefined>");
} else {
w.println("\t\t<plugin>");
w.println("\t\t\t" + profile.getClass().getName());
w.println("\t\t</plugin>");
}
}
w.println("</profile>");
}
} catch (Exception e) {
e.printStackTrace();
throw new SaveException(e);
}
}
private void printModelXMI(PrintWriter w, Collection profileModels)
throws UmlException {
// TODO: Why is this not executed? Remove if not needed - tfm
if (true) return;
StringWriter myWriter = new StringWriter();
for (Object model : profileModels) {
XmiWriter xmiWriter = Model.getXmiWriter(model,
(OutputStream) null, //myWriter,
ApplicationVersion.getVersion() + "("
+ UmlFilePersister.PERSISTENCE_VERSION + ")");
xmiWriter.write();
}
myWriter.flush();
w.println("" + myWriter.toString());
}
@Override
public void load(Project project, URL url) throws OpenException {
try {
load(project, url.openStream());
} catch (IOException e) {
throw new OpenException(e);
}
}
}