/** * Copyright 2005 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.common; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.ArrayList; import java.util.List; /** * Upon instantiation the EqualityKey caches the first Object's hashCode * this can never change. The EqualityKey has an internal datastructure * which references all the handles which are equal. It also records * Whether the referenced facts are JUSTIFIED or STATED * * @author <a href="mailto:mark.proctor@jboss.com">Mark Proctor</a> * */ public class EqualityKey implements Externalizable { public final static int STATED = 1; public final static int JUSTIFIED = 2; /** this is an optimisation so single stated equalities can tracked without the overhead of an ArrayList */ private InternalFactHandle handle; /** this is always lazily maintainned and deleted when empty to minimise memory consumption */ private List<InternalFactHandle> instances; /** This is cached in the constructor from the first added Object */ private int hashCode; /** Tracks whether this Fact is Stated or Justified */ private int status; public EqualityKey() { } public EqualityKey(final InternalFactHandle handle) { this.handle = handle; this.hashCode = handle.getObjectHashCode(); } public EqualityKey(final InternalFactHandle handle, final int status) { this.handle = handle; this.hashCode = handle.getObjectHashCode(); this.status = status; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { handle = (InternalFactHandle)in.readObject(); instances = (List)in.readObject(); hashCode = in.readInt(); status = in.readInt(); } public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(handle); out.writeObject(instances); out.writeInt(hashCode); out.writeInt(status); } public InternalFactHandle getFactHandle() { return this.handle; } public List<InternalFactHandle> getOtherFactHandle() { return this.instances; } public void addFactHandle(final InternalFactHandle handle) { if ( this.instances == null ) { this.instances = new ArrayList<InternalFactHandle>(); } this.instances.add( handle ); } public void removeFactHandle(final InternalFactHandle handle) { if ( this.handle == handle ) { if ( this.instances == null ) { this.handle = null; } else { this.handle = (InternalFactHandle) this.instances.remove( 0 ); if ( this.instances.isEmpty() ) { this.instances = null; } } } else { this.instances.remove( handle ); if ( this.instances.isEmpty() ) { this.instances = null; } } } /** * @return the status */ public int getStatus() { return this.status; } /** * @param status the status to set */ public void setStatus(final int status) { this.status = status; } public int size() { if ( this.instances != null ) { return this.instances.size() + 1; } else { return (this.handle != null) ? 1 : 0; } } public boolean isEmpty() { return (this.handle == null); } public String toString() { String str = null; switch ( this.status ) { case 1 : str = "STATED"; break; case 2 : str = "JUSTIFIED"; break; } return "[FactStatus status=" + this.status + "]"; } /** * Returns the cached hashCode * @see java.lang.Object#hashCode() */ public int hashCode() { return this.hashCode; } /** * Equality for the EqualityKey means two things. It returns * true if the object is also an EqualityKey the of the same * the same identity as this. It also returns true if the object * is equal to the head FactHandle's referenced Object. */ public boolean equals(final Object object) { if ( object == null ) { return false; } if ( object instanceof EqualityKey ) { return this == object; } return (this.handle.getObject().equals( object )); } }