/******************************************************************************* * Copyright (c) 2004, 2011 Tasktop Technologies 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: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.monitor.core; import java.util.Calendar; import java.util.Date; import org.eclipse.core.runtime.Assert; /** * Immutable. Encapsulates interaction made by the user or on behalf of the user. Also see: * http://wiki.eclipse.org/index.php/Mylyn_Integrator_Reference#Monitor_API * * @author Mik Kersten * @since 2.0 */ public class InteractionEvent { /** * Determines the type of interaction that took place, either initiated by the user or done on behalf of the user. */ public enum Kind { /** * User selection of elements, issued by the Eclipse post-selection mechanism. */ SELECTION, /** * Edit events that are created by text selections in an editor. */ EDIT, /** * Commands and actions invoked via buttons, menus, and keyboard shortcuts. */ COMMAND, /** * Workbench preference changes, sometimes made by the user, sometimes automatically on behalf of the user. */ PREFERENCE, /** * Candidates for future interaction. */ PREDICTION, /** * Indirect user interaction with elements (e.g. parent gets implicitly selected when element is selected). */ PROPAGATION, /** * Direct manipulation of interest via actions such as "Mark as Landmark" and "Mark Less Interesting". */ MANIPULATION, /** * Capture interaction with tasks, the workbench, and lifecycle events that define where the user's attention is * directed. */ ATTENTION; /** * TODO: add PREFERENCE? */ public boolean isUserEvent() { return this == SELECTION || this == EDIT || this == COMMAND || this == PREFERENCE; } /** * @return Simple string representation of the event kind or "null" if no such kind. */ @Override public String toString() { switch (this) { case SELECTION: return "selection"; //$NON-NLS-1$ case EDIT: return "edit"; //$NON-NLS-1$ case COMMAND: return "command"; //$NON-NLS-1$ case PREFERENCE: return "preference"; //$NON-NLS-1$ case PREDICTION: return "prediction"; //$NON-NLS-1$ case PROPAGATION: return "propagation"; //$NON-NLS-1$ case MANIPULATION: return "manipulation"; //$NON-NLS-1$ case ATTENTION: return "attention"; //$NON-NLS-1$ default: return "null"; //$NON-NLS-1$ } } /** * @return The corresponding event based on the string provided, or null if no such STring. */ public static Kind fromString(String string) { if (string == null) { return null; } if (string.equals("selection")) { //$NON-NLS-1$ return SELECTION; } if (string.equals("edit")) { //$NON-NLS-1$ return EDIT; } if (string.equals("command")) { //$NON-NLS-1$ return COMMAND; } if (string.equals("preference")) { //$NON-NLS-1$ return PREFERENCE; } if (string.equals("prediction")) { //$NON-NLS-1$ return PREDICTION; } if (string.equals("propagation")) { //$NON-NLS-1$ return PROPAGATION; } if (string.equals("manipulation")) { //$NON-NLS-1$ return MANIPULATION; } if (string.equals("attention")) { //$NON-NLS-1$ return ATTENTION; } return null; } } private final Kind kind; private final Date date; private final Date endDate; private final String originId; private final String structureKind; private final String structureHandle; private final String navigation; private final String delta; private final float interestContribution; /** * Use to specify an uknown identifier, e.g. for an originId. */ public static final String ID_UNKNOWN = "?"; //$NON-NLS-1$ /** * For parameter description see this class's getters. */ public InteractionEvent(Kind kind, String structureKind, String handle, String originId) { this(kind, structureKind, handle, originId, 1f); } /** * For parameter description see this class's getters. */ public InteractionEvent(Kind kind, String structureKind, String handle, String originId, String navigatedRelation) { this(kind, structureKind, handle, originId, navigatedRelation, "null", 1f); //$NON-NLS-1$ } /** * For parameter description see this class's getters. */ public InteractionEvent(Kind kind, String structureKind, String handle, String originId, String navigatedRelation, float interestContribution) { this(kind, structureKind, handle, originId, navigatedRelation, "null", interestContribution); //$NON-NLS-1$ } /** * For parameter description see this class's getters. */ public static InteractionEvent makeCommand(String originId, String delta) { return new InteractionEvent(InteractionEvent.Kind.COMMAND, "null", "null", originId, "null", delta, 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } /** * For parameter description see this class's getters. */ public static InteractionEvent makeCopy(InteractionEvent originalEvent, float newInterestContribution) { return new InteractionEvent(originalEvent.getKind(), originalEvent.getStructureKind(), originalEvent.getStructureHandle(), originalEvent.getOriginId(), originalEvent.getNavigation(), originalEvent.getDelta(), newInterestContribution, originalEvent.getDate(), originalEvent.getEndDate()); } /** * For parameter description see this class's getters. */ public static InteractionEvent makePreference(String originId, String delta) { return new InteractionEvent(InteractionEvent.Kind.PREFERENCE, "null", "null", originId, "null", delta, 1); // default //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // contribution } /** * For parameter description see this class's getters. */ public InteractionEvent(Kind kind, String structureKind, String handle, String originId, float interestContribution) { this(kind, structureKind, handle, originId, "null", "null", interestContribution); // default //$NON-NLS-1$ //$NON-NLS-2$ // contribution } /** * For parameter description see this class's getters. */ public InteractionEvent(Kind kind, String structureKind, String handle, String originId, String navigatedRelation, String delta, float interestContribution) { this(kind, structureKind, handle, originId, navigatedRelation, delta, interestContribution, Calendar.getInstance().getTime()); } private InteractionEvent(Kind kind, String structureKind, String handle, String originId, String navigatedRelation, String delta, float interestContribution, Date startDate) { this(kind, structureKind, handle, originId, navigatedRelation, delta, interestContribution, startDate, startDate); } /** * For parameter description see this class's getters. */ public InteractionEvent(Kind kind, String structureKind, String handle, String originId, String navigatedRelation, String delta, float interestContribution, Date startDate, Date endDate) { Assert.isNotNull(kind); Assert.isNotNull(originId); Assert.isNotNull(startDate); Assert.isNotNull(endDate); this.kind = kind; this.structureKind = (structureKind != null) ? structureKind.intern() : null; this.structureHandle = (handle != null) ? handle.intern() : null; this.originId = originId.intern(); this.navigation = (navigatedRelation != null) ? navigatedRelation.intern() : null; this.delta = (delta != null) ? delta.intern() : null; this.interestContribution = interestContribution; this.date = startDate; this.endDate = endDate; } @Override public boolean equals(Object object) { if (object == null || !(object instanceof InteractionEvent)) { return false; } InteractionEvent event = (InteractionEvent) object; return (date == null ? event.date == null : date.equals(event.date)) && (endDate == null ? event.endDate == null : endDate.equals(event.endDate)) && (kind == null ? event.kind == null : kind.equals(event.kind)) && (structureKind == null ? event.structureKind == null : structureKind.equals(event.structureKind)) && (structureHandle == null ? event.structureHandle == null : structureHandle.equals(event.structureHandle)) && (originId == null ? event.originId == null : originId.equals(event.originId)) && (navigation == null ? event.navigation == null : navigation.equals(event.navigation)) && (delta == null ? event.delta == null : delta.equals(event.delta)) && interestContribution == event.interestContribution; } @Override public int hashCode() { int hashCode = 0; if (date != null) { hashCode += date.hashCode(); } if (endDate != null) { hashCode += endDate.hashCode(); } if (kind != null) { hashCode += kind.hashCode(); } if (structureKind != null) { hashCode += structureKind.hashCode(); } if (structureHandle != null) { hashCode += structureHandle.hashCode(); } if (originId != null) { hashCode += originId.hashCode(); } if (navigation != null) { hashCode += navigation.hashCode(); } if (delta != null) { hashCode += delta.hashCode(); } // TODO: could this lose precision? hashCode += new Float(interestContribution).hashCode(); return hashCode; } @Override public String toString() { return "(date: " + date + ", kind: " + kind + ", sourceHandle: " + structureHandle + ", origin: " + originId //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + ", delta: " + delta + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } public boolean isValidStructureHandle() { return structureHandle != null && !structureHandle.equals("null") && !structureHandle.trim().equals(ID_UNKNOWN); //$NON-NLS-1$ } // TODO 4.0 change to getHandleIdentifier() public String getStructureHandle() { return structureHandle; } /** * @return The content type of the element being interacted with. */ public String getStructureKind() { return structureKind; } /** * @return Time stamp for the occurrence of the event. */ public Date getDate() { return date; } /** * Can be used for extensibility, e.g. by adding an XML-encoded String. * * @return Additional information relevant to interaction monitoring. */ public String getDelta() { return delta; } /** * @return Defines the kind of interaction that took place. */ public Kind getKind() { return kind; } /** * @return The UI affordance that the event was issued from. */ public String getOriginId() { return originId; } /** * @return If an aggregate event, amount of interest of all contained events. */ // TODO: consider refactoring in order to de-couple events from interest. public float getInterestContribution() { return interestContribution; } /** * @return If an aggregate event, time stamp of the last occurrence. */ public Date getEndDate() { return endDate; } /** * @return An identifier for the kind of relation that corresponds to the navigation to this element. */ public String getNavigation() { return navigation; } }