alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

// $Id: WizAssocComposite.java,v 1.16 2004/09/27 18:31:27 mvw Exp $
// Copyright (c) 1996-2004 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.uml.cognitive.critics;

import java.util.Iterator;
import java.util.Vector;
import javax.swing.JPanel;
import org.apache.log4j.Logger;

import org.argouml.cognitive.ui.WizStepChoice;
import org.argouml.kernel.Wizard;
import org.argouml.model.ModelFacade;
import org.tigris.gef.util.VectorSet;

/**
 * A non-modal wizard to assist the user in changing aggregation of an
 * association.

* * Earlier version always imposed composite aggregation. This version * allows the user to choose.

* * Note. This only applies to binary associations. A separate * wizard is needed for 3-way (or more) associations.

* * @see * ArgoUML User Manual: Two Aggregate ends (roles) in binary Association * * @author jrobbins@ics.uci.edu */ public class WizAssocComposite extends Wizard { /** * Logger. */ private static final Logger LOG = Logger.getLogger(WizAssocComposite.class); /** * The initial instructions on the Step 1 screen. May be set to a * different string through {@link #setInstructions(String)}.

*/ private String instructions = "Please select one of the following aggregation options:"; /** * Contains the {@link WizStepChoice} that is used to get the user's * desired options. Not created until we get to that step.

*/ private WizStepChoice step1Choice = null; /** * The {@link ru.novosoft.uml.foundation.core.MAssociation * MAssociation} {@link WizStepChoice} that triggered the * critic. Null until set when it is first needed.

*/ private Object triggerAssociation = null; /** * Constructor for the wizard. Currently does nothing.

*/ public WizAssocComposite() { } /** * Returns the number of steps in this wizard.

* * @return The number of steps (excluding the initial explanation) in this * wizard (1). * * @see Wizard */ public int getNumSteps() { return 1; } /** * Tries to identify the {@link * ru.novosoft.uml.foundation.core.MAssociation MAssociation} that * triggered the critic.

* * The first time it is called, it will initialise the trigger * from the ToDoItem. If there, it is assumed to be the first * trigger of the ToDoItem and to be an association. If found, the * value is stored in the private field {@link #triggerAssociation}.

* * On all subsequent calls, if a non-null value is found in {@link * #triggerAssociation} that is returned.

* * @return the {@link ru.novosoft.uml.foundation.core.MAssociation * MAssociation} that triggered the critic, or null * if there was none. */ private Object getTriggerAssociation() { // If we don't have it, find the trigger. If this fails it will keep // its default value of null if ((triggerAssociation == null) && (getToDoItem() != null)) { VectorSet offs = getToDoItem().getOffenders(); if (offs.size() >= 1) { triggerAssociation = offs.elementAt(0); } } return triggerAssociation; } /** * Returns a vector of options to be used in creating a {@link * WizStepChoice} that will exercise the options.

* * We provide five options, shared aggregation in each direction, * composite aggregation in each direction and no aggregation at * all.

* * It is possible that a very malicious user could delete the * triggering association just before we get to this point. For * now we don't bother to trap this. It will raise an exception, * and then everything will carry on happily.

* * @return A {@link Vector} of the options or null if the * association that triggered the critic is no longer there. */ private Vector buildOptions() { // The association that triggered the critic. Its just possible the // association is no longer there, in which case we return null Object asc = getTriggerAssociation(); if (asc == null) { return null; } // A vector in which to build the result Vector res = new Vector(); // Get the ends from the association (we know there are two), and the // types associated with them. Iterator iter = ModelFacade.getConnections(asc).iterator(); Object ae0 = iter.next(); Object ae1 = iter.next(); Object cls0 = ModelFacade.getType(ae0); Object cls1 = ModelFacade.getType(ae1); // Get the names of the two ends. If there are none (i.e they are // currently anonymous), use the ArgoUML convention of "(anon)" for the // names String start = "(anon)"; String end = "(anon)"; if ((cls0 != null) && (ModelFacade.getName(cls0) != null) && (!(ModelFacade.getName(cls0).equals("")))) { start = ModelFacade.getName(cls0); } if ((cls1 != null) && (ModelFacade.getName(cls1) != null) && (!(ModelFacade.getName(cls1).equals("")))) { end = ModelFacade.getName(cls1); } // Now create the five options res.addElement (start + " is a composite aggregation of " + end); res.addElement (start + " is a shared aggregation of " + end); res.addElement (end + " is a composite aggregation of " + start); res.addElement (end + " is a shared aggregation of " + start); res.addElement ("No aggregation"); return res; } /** * Set the initial instruction string for the choice. May be * called by the creator of the wizard to override the default.

* * @param s The new instructions. */ public void setInstructions(String s) { instructions = s; } /** * Create a {@link JPanel} for the given step.

* * We use a {@link WizStepChoice} to handle the choice selection * for the user. We only create the panel once, saving it in a * private field (_step1Choice) for subsequent * use.

* * Note. If the association has been deleted, then we may * not be able to create a vector of options. Under these * circumstances we also return null.

* * @param newStep The index of the step for which a panel is needed. * * @return The created {@link JPanel} or null if no * options were available. * * @see Wizard */ public JPanel makePanel(int newStep) { switch (newStep) { case 1: // First step. Create the panel if not already done and options are // available. Otherwise it retains its default value of null. if (step1Choice == null) { Vector opts = buildOptions(); if (opts != null) { step1Choice = new WizStepChoice(this, instructions, opts); step1Choice.setTarget(getToDoItem()); } } return step1Choice; default: } // Default (any other step) is to return nothing return null; } /** * Take action at the completion of a step.

* * The guideline for ArgoUML non-modal wizards is to act * immediately, not wait for the finish. This method may also be * invoked when finish is triggered for any steps whose panels * didn't get created.

* * The observation is that this seems to be trigged when there is * any change on the panel (e.g choosing an option), not just when * "next" is pressed. Coded accordingly

* * We allow for the association that caused the problem having by * now been deleted, and hence an exception may be raised. We * catch this politely.

* * @param oldStep The index of the step just completed (0 for the first * information panel) * * @see Wizard */ public void doAction(int oldStep) { switch (oldStep) { case 1: // Just completed the first step where we make our choices. First // see if we have a choice. We always should, so print a rude // message if we don't int choice = -1; if (step1Choice != null) { choice = step1Choice.getSelectedIndex(); } if (choice == -1) { LOG.warn("WizAssocComposite: nothing selected, " + "should not get here"); return; } // It is quite possible that the cause of the problem has by now // been deleted, in which case we will throw an exception if we try // to change things. Catch this tidily. try { // Set the appropriate aggregation on each end Iterator iter = ModelFacade.getConnections(getTriggerAssociation()) .iterator(); Object ae0 = iter.next(); Object ae1 = iter.next(); switch (choice) { case 0: // Start is a composite aggregation of end ModelFacade.setAggregation( ae0, ModelFacade.COMPOSITE_AGGREGATIONKIND); ModelFacade.setAggregation( ae1, ModelFacade.NONE_AGGREGATIONKIND); break; case 1: // Start is a shared aggregation of end ModelFacade.setAggregation( ae0, ModelFacade.AGGREGATE_AGGREGATIONKIND); ModelFacade.setAggregation( ae1, ModelFacade.NONE_AGGREGATIONKIND); break; case 2: // End is a composite aggregation of start ModelFacade.setAggregation( ae0, ModelFacade.NONE_AGGREGATIONKIND); ModelFacade.setAggregation( ae1, ModelFacade.COMPOSITE_AGGREGATIONKIND); break; case 3: // End is a shared aggregation of start ModelFacade.setAggregation( ae0, ModelFacade.NONE_AGGREGATIONKIND); ModelFacade.setAggregation( ae1, ModelFacade.AGGREGATE_AGGREGATIONKIND); break; case 4: // No aggregation ModelFacade.setAggregation( ae0, ModelFacade.NONE_AGGREGATIONKIND); ModelFacade.setAggregation( ae1, ModelFacade.NONE_AGGREGATIONKIND); break; default: } } catch (Exception pve) { // Someone took our association away. LOG.error("WizAssocComposite: could not set " + "aggregation.", pve); } default: } } /** * Determine if we have sufficient information to finish.

* * We can't finish if our parent {@link Wizard} can't finish.

* * We can finish if we're on step 0.

* * We can finish if we're on step 1 and have made a choice.

* * @return true if we can finish, otherwise * false. * * @see Wizard */ public boolean canFinish() { // Can't finish if our parent can't if (!super.canFinish()) { return false; } // Can finish if it's step 0 if (getStep() == 0) { return true; } // Can finish if we're on step1 and have actually made a choice if ((getStep() == 1) && (step1Choice != null) && (step1Choice.getSelectedIndex() != -1)) { return true; } // Otherwise we can't finish return false; } } /* end class WizAssocComposite */

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.