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: CrOperNameConflict.java,v 1.15 2004/09/21 19:03:26 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.Icon;
import org.argouml.cognitive.Designer;
import org.argouml.cognitive.critics.Critic;
import org.argouml.model.ModelFacade;

// Use Model through ModelFacade

/**
 * A critic to detect when a class has operations with two matching
 * signatures.

* * Takes each operation in turn and compares its signature with all * earlier operations. This version corrects and earlier bug, which * checked for matching names as well as types in the parameter * list.

* * Warning. The algorithm in is quadratic in the number of * operations. It could be computationally demanding on a design where * classes have a lot of operations. See the {@link #predicate2} * method for possible solutions.

* * @see * ArgoUML User Manual: Change Names or Signatures in <artifact> * * @author jrobbins@ics.uci.edu */ public class CrOperNameConflict extends CrUML { /** * Constructor for the critic.

* * Sets up the resource name, which will allow headline and * description to found for the current locale. Provides design * issue categories (METHODS, NAMING), sets a knowledge type * (SYNTAX) and adds triggers for metaclasses "behaviouralFeature" * and feature_name".

*/ public CrOperNameConflict() { setResource("CrOperNameConflict"); addSupportedDecision(CrUML.DEC_METHODS); addSupportedDecision(CrUML.DEC_NAMING); setKnowledgeTypes(Critic.KT_SYNTAX); // These may not actually make any difference at present (the code // behind addTrigger needs more work). addTrigger("behavioralFeature"); addTrigger("feature_name"); } /** * The trigger for the critic.

* * Finds all the operations for the given classifier. Takes each * operation in turn and compares its signature with all earlier * operations. This version corrects an earlier bug, which checked * for matching names as well as types in the parameter list.

* * Note. The signature ignores any return parameters in * looking for a match. This is in line with Java/C++.

* * We do not need to worry about signature clashes that are * inherited (overloading). This is something encouraged in many * OO environments to facilitate polymorphism.

* * This algorithm is quadratic in the number of operations. If * this became a problem, we would have to consider sorting the * operations vector and comparing only adjacent pairs * (potentially O(n log n) performance).

* * @param dm the {@link Object} to be checked against the critic. * * @param dsgr the {@link Designer} creating the model. Not used, * this is for future development of ArgoUML. * * @return {@link #PROBLEM_FOUND PROBLEM_FOUND} if the critic is * triggered, otherwise {@link #NO_PROBLEM NO_PROBLEM}. */ public boolean predicate2(Object dm, Designer dsgr) { // Only do this for classifiers if (!(ModelFacade.isAClassifier(dm))) { return NO_PROBLEM; } Iterator ops = ModelFacade.getOperations(dm).iterator(); // Get all the features (giving up if there are none). Then loop // through finding all operations. Each time we find one, we compare // its signature with all previous (held in vector operSeen), and then // if it doesn't match add it to the vector. Vector operSeen = new Vector(); while (ops.hasNext()) { Object op = ops.next(); // Compare against all earlier operations. If there's a match we've // found the problem int size = operSeen.size(); for (int i = 0; i < size; i++) { if (signaturesMatch(op, operSeen.get(i))) { return PROBLEM_FOUND; } } // Add to the vector and round to look at the next one operSeen.addElement(op); } // If we drop out here, there was no match and we have no problem return NO_PROBLEM; } /** * Return the icon to be used for the clarifier for this critic.

* * A clarifier is the graphical highlight used to show the * presence of a critique. For example wavy colored underlines * beneath operations.

* * In this case it will be a wavy line under the second of the * clashing operations.

* * @return The {@link javax.swing.Icon Icon} to use. */ public Icon getClarifier() { return ClOperationCompartment.getTheInstance(); } /** * Sees if the signatures of two Operations are the same.

* * Checks for matching operation name, and list of parameter * types. The order of the parameters is significant. * * This version also checks for the parameter kind, since * otherwise, "op(int a)" and "op():int" appear to have the same * signature. Purists would probably suggest that the kind should * match exactly. However we only differentiate the return * parameter(s). It is unlikely that any practical OO language * would be able to distinguish instantiation of in from out from * inout parameters.

* * We ignore return parameters completely. This is in line with * Java/C++ which regard int x(int, int) and * double x(int, int) as having the same * signature.

* * If you need to modify this method, take care, since there are * numerous "telegraph pole" problems involved in working through * pairs of mixed lists.

* * @param op1 the first operation whose signature is being compared. * @param op2 the second operation whose signature is being compared. * * @return true if the signatures match, false * otherwise. */ private boolean signaturesMatch(Object op1, Object op2) { // Check that the names match. String name1 = ModelFacade.getName(op1); if (name1 == null) return false; String name2 = ModelFacade.getName(op2); if (name2 == null) return false; if (!name1.equals(name2)) return false; // Check that the parameter lists match. Iterator params1 = ModelFacade.getParameters(op1).iterator(); Iterator params2 = ModelFacade.getParameters(op2).iterator(); while (params1.hasNext() && params2.hasNext()) { // Get the next non-return parameter. Null if non left. Object p1 = null; while (p1 == null && params1.hasNext()) { p1 = params1.next(); if (ModelFacade.isReturn(p1)) p1 = null; } Object p2 = null; while (p2 == null && params1.hasNext()) { p2 = params1.next(); if (ModelFacade.isReturn(p2)) p2 = null; } if (p1 == null && p2 == null) return true; // Both lists have the same length // Different lengths: if (p1 == null) return false; if (p2 == null) return false; // Compare the type of the parameters. If any of the types is // null, then we have a match. Object p1type = ModelFacade.getType(p1); if (p1type == null) continue; Object p2type = ModelFacade.getType(p2); if (p2type == null) continue; if (!p1type.equals(p2type)) return false; // This pair of params where the same. Lets check the next pair. } if (!params1.hasNext() && !params2.hasNext()) { // Both lists have the same length. return true; } return false; } } /* end class CrOperNameConflict.java */

... 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.