| /******************************************************************************* |
| * Copyright (c) 2001, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jem.internal.beaninfo.vm; |
| /* |
| |
| |
| */ |
| |
| import java.beans.*; |
| import java.util.*; |
| import java.lang.reflect.*; |
| /** |
| * This object is used to test for semantic equality (equals()) |
| * between feature objects. It is needed because Feature's don't |
| * provide a semantic equality, only an identity equality. Need |
| * semantic equality so that keys in map can be found equal |
| * semantically. |
| */ |
| |
| public class FeatureDescriptorEquality { |
| protected FeatureDescriptor fFeature; |
| |
| private HashMap fValues; // The key/values for this feature. We grab them out |
| // so that we don't have to keep re-getting them for equality |
| // compares. This is done the first time needed in the equals |
| // statement. |
| |
| private int fHashCode = 0; // Hashcode of this equality object. The hashcode for the feature is expensive |
| // so we will calculate it once (the assumption is that |
| // features once created aren't changed, which for our |
| // purposes here in beaninfo land is good). |
| |
| protected static HashMap MAP_EQUALITY = new HashMap(10); // Map from descriptor to equality type. |
| static { |
| try { |
| MAP_EQUALITY.put(FeatureDescriptor.class, (FeatureDescriptorEquality.class).getConstructor(new Class[] {FeatureDescriptor.class})); |
| } catch (NoSuchMethodException e) { |
| } |
| // Need to set up the others. |
| BeanDescriptorEquality.INIT(); |
| EventSetDescriptorEquality.INIT(); |
| IndexedPropertyDescriptorEquality.INIT(); |
| MethodDescriptorEquality.INIT(); |
| ParameterDescriptorEquality.INIT(); |
| } |
| |
| /** |
| * Create the appropriate descriptor equality for this object. |
| */ |
| public static FeatureDescriptorEquality createEquality(FeatureDescriptor descr) { |
| try { |
| return (FeatureDescriptorEquality) ((Constructor) MAP_EQUALITY.get(descr.getClass())).newInstance(new Object[] {descr}); |
| } catch (IllegalAccessException e) { |
| } catch (InstantiationException e) { |
| } catch (InvocationTargetException e) { |
| e.printStackTrace(); |
| } |
| return null; |
| } |
| |
| public FeatureDescriptorEquality() { |
| } |
| |
| /** |
| * NOTE: Every subclass needs to implement an override for the methods: |
| * calculateHashCode |
| * equals |
| * clearFeature - if it has any cache values |
| */ |
| |
| public FeatureDescriptorEquality(FeatureDescriptor feature) { |
| setFeature(feature); |
| } |
| |
| public final void setFeature(FeatureDescriptor feature) { |
| clearFeature(); |
| fFeature = feature; |
| } |
| |
| /** |
| * A new feature is being set into this object, |
| * clear any cache members so that they can be reconstructed. |
| * |
| * NOTE: Subclasses - remember to call super.clearFeature(); |
| */ |
| protected void clearFeature() { |
| fValues = null; |
| fHashCode = 0; |
| } |
| |
| public final int hashCode() { |
| if (fHashCode == 0) |
| fHashCode = calculateHashCode(); |
| return fHashCode; |
| } |
| |
| protected final HashMap values() { |
| if (fValues == null) { |
| fValues = new HashMap(5); |
| |
| Enumeration keys = fFeature.attributeNames(); |
| while (keys.hasMoreElements()) { |
| String key = (String) keys.nextElement(); |
| fValues.put(key, fFeature.getValue(key)); |
| } |
| } |
| return fValues; |
| } |
| |
| /** |
| * Calculate the hashcode for the current feature, add this |
| * to the hashcode received from super.calculateHashCode |
| * and return the new value. |
| * |
| * NOTE: for subclasses, it is MANDITORY that the first line be: |
| * int hashcode = super.calculateHashCode(); |
| * and the last line be: |
| * return hashcode*31 + (your calculated hashcode for just this subclass); |
| */ |
| protected int calculateHashCode() { |
| int hashcode = 0; |
| if (fFeature.getName() != null) |
| hashcode += fFeature.getName().hashCode(); |
| |
| if (fFeature.getDisplayName() != fFeature.getName()) |
| hashcode += fFeature.getDisplayName().hashCode(); |
| if (fFeature.getShortDescription() != fFeature.getDisplayName()) |
| hashcode += fFeature.getShortDescription().hashCode(); |
| |
| hashcode += (fFeature.isExpert() ? Boolean.TRUE : Boolean.FALSE).hashCode(); |
| hashcode += (fFeature.isHidden() ? Boolean.TRUE : Boolean.FALSE).hashCode(); |
| hashcode += (fFeature.isPreferred() ? Boolean.TRUE : Boolean.FALSE).hashCode(); |
| |
| hashcode += values().hashCode(); |
| return hashcode; |
| } |
| |
| /** |
| * equals: See if this is equal semantically. |
| * |
| * NOTE: Every subclass needs to implement this and |
| * the first few lines should be: |
| * if (identityTest()) |
| * return true; |
| * if (!super.equals(obj)) |
| * return false; |
| */ |
| |
| public boolean equals(Object obj) { |
| if (identityTest(obj)) |
| return true; |
| if (!(obj instanceof FeatureDescriptorEquality)) |
| return false; |
| |
| FeatureDescriptorEquality ofe = (FeatureDescriptorEquality) obj; |
| FeatureDescriptor of = ofe.fFeature; |
| |
| if (fFeature.getClass() != of.getClass()) |
| return false; |
| |
| if (!fFeature.getName().equals(of.getName())) |
| return false; |
| if (!fFeature.getDisplayName().equals(of.getDisplayName())) |
| return false; |
| if (!fFeature.getShortDescription().equals(of.getShortDescription())) |
| return false; |
| if (fFeature.isExpert() != of.isExpert() || |
| fFeature.isHidden() != of.isHidden() || |
| fFeature.isPreferred() != of.isPreferred()) |
| return false; |
| |
| if (!values().equals(ofe.values())) |
| return false; |
| return true; |
| } |
| |
| /* |
| * Identity test: Tests for quick identity of |
| * descriptors. If this returns true, then |
| * no other tests required. |
| */ |
| protected boolean identityTest(Object obj) { |
| if (!(obj instanceof FeatureDescriptorEquality)) |
| return false; |
| if (this == obj) |
| return true; |
| |
| if (((FeatureDescriptorEquality) obj).fFeature == fFeature) |
| return true; |
| |
| return false; |
| } |
| } |