// // $Id: UserDefinedProfile.java 132 2010-09-26 23:32:33Z marcusvnac $ // 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.profile; import java.awt.Image; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import javax.swing.ImageIcon; //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Import import org.apache.log4j.Logger; //#endif //#if defined(COGNITIVE) //@#$LPS-COGNITIVE:GranularityType:Import import org.argouml.cognitive.Critic; import org.argouml.cognitive.Decision; import org.argouml.cognitive.ToDoItem; import org.argouml.cognitive.Translator; //#endif import org.argouml.model.Model; //#if defined(COGNITIVE) //@#$LPS-COGNITIVE:GranularityType:Import import org.argouml.profile.internal.ocl.CrOCL; //#endif import org.argouml.profile.internal.ocl.InvalidOclException; //#if defined(COGNITIVE) //@#$LPS-COGNITIVE:GranularityType:Import import org.argouml.uml.cognitive.UMLDecision; //#endif /** * Represents a profile defined by the user * * @author maurelio1234 */ public class UserDefinedProfile extends Profile { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Field /** * Logger. */ private static final Logger LOG = Logger .getLogger(UserDefinedProfile.class); //#endif private String displayName; private File modelFile; private Collection profilePackages; private UserDefinedFigNodeStrategy figNodeStrategy = new UserDefinedFigNodeStrategy(); private class UserDefinedFigNodeStrategy implements FigNodeStrategy { private Map<String, Image> images = new HashMap<String, Image>(); public Image getIconForStereotype(Object stereotype) { return images.get(Model.getFacade().getName(stereotype)); } /** * Adds a new descriptor to this strategy * * @param fnd */ public void addDesrciptor(FigNodeDescriptor fnd) { images.put(fnd.stereotype, fnd.img); } } private class FigNodeDescriptor { private String stereotype; private Image img; private String src; private int length; /** * @return if this descriptor ir valid */ public boolean isValid() { return stereotype != null && src != null && length > 0; } } /** * The default constructor for this class * * @param file the file from where the model should be read * @throws ProfileException if the profile could not be loaded */ public UserDefinedProfile(File file) throws ProfileException { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:StartMethod LOG.info("load " + file); //#endif displayName = file.getName(); modelFile = file; ProfileReference reference = null; try { reference = new UserProfileReference(file.getPath()); } catch (MalformedURLException e) { throw new ProfileException( "Failed to create the ProfileReference.", e); } profilePackages = new FileModelLoader().loadModel(reference); finishLoading(); } /** * A constructor that reads a file from an URL * * @param url the URL * @throws ProfileException if the profile can't be read or is not valid */ public UserDefinedProfile(URL url) throws ProfileException { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:StartMethod LOG.info("load " + url); //#endif ProfileReference reference = null; reference = new UserProfileReference(url.getPath(), url); profilePackages = new URLModelLoader().loadModel(reference); finishLoading(); } /** * A constructor that reads a file from an URL associated with some profiles * * @param dn the display name of the profile * @param url the URL of the profile mode * @param critics the Critics defined by this profile * @param dependencies the dependencies of this profile * @throws ProfileException if the model cannot be loaded */ public UserDefinedProfile(String dn, URL url, //#if defined(COGNITIVE) //@#$LPS-COGNITIVE:GranularityType:MethodSignature Set<Critic> critics, //#endif Set<String> dependencies) throws ProfileException { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:StartMethod LOG.info("load " + url); //#endif this.displayName = dn; if (url != null) { ProfileReference reference = null; reference = new UserProfileReference(url.getPath(), url); profilePackages = new URLModelLoader().loadModel(reference); } else { profilePackages = new ArrayList(0); } //#if defined(COGNITIVE) //@#$LPS-COGNITIVE:GranularityType:Statement this.setCritics(critics); //#endif for (String profileID : dependencies) { addProfileDependency(profileID); } finishLoading(); } /** * Reads the informations defined as TaggedValues */ private void finishLoading() { Collection packagesInProfile = filterPackages(); for (Object obj : packagesInProfile) { // if there is only one package in the model, we should suppose it's // the profile model, if there is more than one, we take the ones // marked as <<profile>> if (Model.getFacade().isAModelElement(obj) && (Model.getExtensionMechanismsHelper().hasStereotype(obj, "profile") || (packagesInProfile.size() == 1))) { // load profile name String name = Model.getFacade().getName(obj); if (name != null) { displayName = name; } //#if defined(COGNITIVE) //@#$LPS-COGNITIVE:GranularityType:Statement //@#$LPS-COGNITIVE:Localization:NestedStatement else { if (displayName == null) { displayName = Translator .localize("misc.profile.unnamed"); } } //#endif //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:NestedStatement LOG.info("profile " + displayName); //#endif // load profile dependencies String dependencyListStr = Model.getFacade() .getTaggedValueValue(obj, "Dependency"); StringTokenizer st = new StringTokenizer(dependencyListStr, " ,;:"); String profile = null; while (st.hasMoreTokens()) { profile = st.nextToken(); if (profile != null) { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:NestedStatement LOG.debug("AddingDependency " + profile); //#endif this.addProfileDependency(ProfileFacade.getManager() .lookForRegisteredProfile(profile)); } } } } // load fig nodes Collection allStereotypes = Model.getExtensionMechanismsHelper() .getStereotypes(packagesInProfile); for (Object stereotype : allStereotypes) { Collection tags = Model.getFacade().getTaggedValuesCollection( stereotype); for (Object tag : tags) { String tagName = Model.getFacade().getTag(tag); if (tagName == null) { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:NestedStatement LOG.debug("profile package with stereotype " + Model.getFacade().getName(stereotype) + " contains a null tag definition"); //#endif } else if (tagName.toLowerCase().equals("figure")) { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:NestedStatement LOG.debug("AddFigNode " + Model.getFacade().getName(stereotype)); //#endif String value = Model.getFacade().getValueOfTag(tag); File f = new File(value); FigNodeDescriptor fnd = null; try { fnd = loadImage(Model.getFacade().getName(stereotype) .toString(), f); figNodeStrategy.addDesrciptor(fnd); } catch (IOException e) { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement //@#$LPS-LOGGING:Localization:NestedStatement LOG.error("Error loading FigNode", e); //#endif } } } } //#if defined(COGNITIVE) // load critiques //@#$LPS-COGNITIVE:GranularityType:Statement Set<Critic> myCritics = this.getCritics(); myCritics.addAll(getAllCritiquesInModel()); this.setCritics(myCritics); //#endif } /** * @return the packages in the <code>profilePackages</code> */ private Collection filterPackages() { Collection ret = new ArrayList(); for (Object object : profilePackages) { if (Model.getFacade().isAPackage(object)) { ret.add(object); } } return ret; } //#if defined(COGNITIVE) //@#$LPS-COGNITIVE:GranularityType:Method private CrOCL generateCriticFromComment(Object critique) { String ocl = "" + Model.getFacade().getBody(critique); String headline = null; String description = null; int priority = ToDoItem.HIGH_PRIORITY; List<Decision> supportedDecisions = new ArrayList<Decision>(); List<String> knowledgeTypes = new ArrayList<String>(); String moreInfoURL = null; Collection tags = Model.getFacade().getTaggedValuesCollection(critique); boolean i18nFound = false; for (Object tag : tags) { if (Model.getFacade().getTag(tag).toLowerCase().equals("i18n")) { i18nFound = true; String i18nSource = Model.getFacade().getValueOfTag(tag); headline = Translator.localize(i18nSource + "-head"); description = Translator.localize(i18nSource + "-desc"); moreInfoURL = Translator.localize(i18nSource + "-moreInfoURL"); } else if (!i18nFound && Model.getFacade().getTag(tag).toLowerCase().equals( "headline")) { headline = Model.getFacade().getValueOfTag(tag); } else if (!i18nFound && Model.getFacade().getTag(tag).toLowerCase().equals( "description")) { description = Model.getFacade().getValueOfTag(tag); } else if (Model.getFacade().getTag(tag).toLowerCase().equals( "priority")) { priority = str2Priority(Model.getFacade().getValueOfTag(tag)); } else if (Model.getFacade().getTag(tag).toLowerCase().equals( "supporteddecision")) { String decStr = Model.getFacade().getValueOfTag(tag); StringTokenizer st = new StringTokenizer(decStr, ",;:"); while (st.hasMoreTokens()) { Decision decision = str2Decision(st.nextToken().trim() .toLowerCase()); if (decision != null) { supportedDecisions.add(decision); } } } else if (Model.getFacade().getTag(tag).toLowerCase().equals( "knowledgetype")) { String ktStr = Model.getFacade().getValueOfTag(tag); StringTokenizer st = new StringTokenizer(ktStr, ",;:"); while (st.hasMoreTokens()) { String knowledge = str2KnowledgeType(st.nextToken().trim() .toLowerCase()); if (knowledge != null) { knowledgeTypes.add(knowledge); } } } else if (!i18nFound && Model.getFacade().getTag(tag).toLowerCase().equals( "moreinfourl")) { moreInfoURL = Model.getFacade().getValueOfTag(tag); } } //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement LOG.debug("OCL-Critic: " + ocl); //#endif try { return new CrOCL(ocl, headline, description, priority, supportedDecisions, knowledgeTypes, moreInfoURL); } catch (InvalidOclException e) { //#if defined(LOGGING) //@#$LPS-LOGGING:GranularityType:Statement LOG.error("Invalid OCL in XMI!", e); //#endif return null; } } private String str2KnowledgeType(String token) { String knowledge = null; if (token.equals("completeness")) { knowledge = Critic.KT_COMPLETENESS; } if (token.equals("consistency")) { knowledge = Critic.KT_CONSISTENCY; } if (token.equals("correctness")) { knowledge = Critic.KT_CORRECTNESS; } if (token.equals("designers")) { knowledge = Critic.KT_DESIGNERS; } if (token.equals("experiencial")) { knowledge = Critic.KT_EXPERIENCIAL; } if (token.equals("optimization")) { knowledge = Critic.KT_OPTIMIZATION; } if (token.equals("organizational")) { knowledge = Critic.KT_ORGANIZATIONAL; } if (token.equals("presentation")) { knowledge = Critic.KT_PRESENTATION; } if (token.equals("semantics")) { knowledge = Critic.KT_SEMANTICS; } if (token.equals("syntax")) { knowledge = Critic.KT_SYNTAX; } if (token.equals("tool")) { knowledge = Critic.KT_TOOL; } return knowledge; } private int str2Priority(String prioStr) { int prio = ToDoItem.MED_PRIORITY; if (prioStr.toLowerCase().equals("high")) { prio = ToDoItem.HIGH_PRIORITY; } else if (prioStr.toLowerCase().equals("med")) { prio = ToDoItem.MED_PRIORITY; } else if (prioStr.toLowerCase().equals("low")) { prio = ToDoItem.LOW_PRIORITY; } else if (prioStr.toLowerCase().equals("interruptive")) { prio = ToDoItem.INTERRUPTIVE_PRIORITY; } return prio; } private Decision str2Decision(String token) { Decision decision = null; if (token.equals("behavior")) { decision = UMLDecision.BEHAVIOR; } if (token.equals("containment")) { decision = UMLDecision.CONTAINMENT; } if (token.equals("classselection")) { decision = UMLDecision.CLASS_SELECTION; } if (token.equals("codegen")) { decision = UMLDecision.CODE_GEN; } if (token.equals("expectedusage")) { decision = UMLDecision.EXPECTED_USAGE; } if (token.equals("inheritance")) { decision = UMLDecision.INHERITANCE; } if (token.equals("instantiation")) { decision = UMLDecision.INSTANCIATION; } if (token.equals("methods")) { decision = UMLDecision.METHODS; } if (token.equals("modularity")) { decision = UMLDecision.MODULARITY; } if (token.equals("naming")) { decision = UMLDecision.NAMING; } if (token.equals("patterns")) { decision = UMLDecision.PATTERNS; } if (token.equals("plannedextensions")) { decision = UMLDecision.PLANNED_EXTENSIONS; } if (token.equals("relationships")) { decision = UMLDecision.RELATIONSHIPS; } if (token.equals("statemachines")) { decision = UMLDecision.STATE_MACHINES; } if (token.equals("stereotypes")) { decision = UMLDecision.STEREOTYPES; } if (token.equals("storage")) { decision = UMLDecision.STORAGE; } return decision; } private List<CrOCL> getAllCritiquesInModel() { List<CrOCL> ret = new ArrayList<CrOCL>(); Collection<Object> comments = getAllCommentsInModel(profilePackages); for (Object comment : comments) { if (Model.getExtensionMechanismsHelper().hasStereotype(comment, "Critic")) { CrOCL cr = generateCriticFromComment(comment); if (cr != null) { ret.add(cr); } } } return ret; } //#endif @SuppressWarnings("unchecked") private Collection<Object> getAllCommentsInModel(Collection objs) { Collection<Object> col = new ArrayList<Object>(); for (Object obj : objs) { if (Model.getFacade().isAComment(obj)) { col.add(obj); } else if (Model.getFacade().isANamespace(obj)) { Collection contents = Model .getModelManagementHelper().getAllContents(obj); if (contents != null) { col.addAll(contents); } } } return col; } /** * @return the string that should represent this profile in the GUI. */ public String getDisplayName() { return displayName; } /** * Returns null. This profile has no formatting strategy. * * @return null. */ @Override public FormatingStrategy getFormatingStrategy() { return null; } /** * Returns null. This profile has no figure strategy. * * @return null. */ @Override public FigNodeStrategy getFigureStrategy() { return figNodeStrategy; } /** * @return the file passed at the constructor */ public File getModelFile() { return modelFile; } /** * @return the name of the model and the file name */ @Override public String toString() { File str = getModelFile(); return super.toString() + (str != null ? " [" + str + "]" : ""); } @Override public Collection getProfilePackages() { return profilePackages; } private FigNodeDescriptor loadImage(String stereotype, File f) throws IOException { FigNodeDescriptor descriptor = new FigNodeDescriptor(); descriptor.length = (int) f.length(); descriptor.src = f.getPath(); descriptor.stereotype = stereotype; BufferedInputStream bis = new BufferedInputStream( new FileInputStream(f)); byte[] buf = new byte[descriptor.length]; try { bis.read(buf); } catch (IOException e) { e.printStackTrace(); } descriptor.img = new ImageIcon(buf).getImage(); return descriptor; } }