Java tutorial
/******************************************************************************* * Copyright (c) 2004-2008 Akos Horvath, Gergely Varro and Daniel Varro * 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: * Akos Horvath, Gergely Varro - initial API and implementation from the VIATRA2 project * Zoltan Ujhelyi - update used in VIATRA Query API *******************************************************************************/ package org.eclipse.viatra.query.runtime.localsearch; import java.util.Arrays; import org.eclipse.viatra.query.runtime.localsearch.matcher.LocalSearchMatcher; import org.eclipse.viatra.query.runtime.localsearch.plan.SearchPlanExecutor; import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; import com.google.common.base.Preconditions; /** * MatchingFrame represents the actual mappings of variables to constants. A MatchingFrame maintains a reference to its * corresponding Pattern (or possibly flattened pattern). * * The following mappings are used by the interpreted engine: * <ul> * <li>VariableType => PatternVariable</li> * <li>ValueType => AnyModelElement</li> * </ul> */ public class MatchingFrame extends Tuple implements Cloneable { private static final String KEYS_ARRAY_SETUP_MISSING_MESSAGE = "A non-null key array has to be set up before getElements() is called."; private static final String KEYS_ARRAY_MUST_NOT_BE_NULL_MESSAGE = "Argument keys must not be null."; /** * The pattern variant for which this MatchingFrame is a * matching. */ private Object pattern; /** * The array that physically holds the values. */ private Object[] frame; private int[] keys; private Object[] parameterValues; public MatchingFrame(Object pattern, int frameSize) { this.pattern = pattern; this.frame = new Object[frameSize]; } private MatchingFrame(Object pattern, int[] keyMap, int frameSize) { this(pattern, frameSize); Preconditions.checkArgument(keyMap != null, KEYS_ARRAY_MUST_NOT_BE_NULL_MESSAGE); this.keys = Arrays.copyOf(keyMap, keyMap.length); } /** * The keys describes which elements of the frame corresponds to the parameters. The parameters are identified by * the index, and a value might be added to multiple indexes in case of parameters made equal with a == constraint. * As this array is different for each body instance, this method is called by the {@link SearchPlanExecutor} class * later than initialization (done by the {@link LocalSearchMatcher}. * * @param keys * @see {@linkplain #setParameterValues(Object[])} for setting the initial parameter */ public void setKeys(int[] keys) { Preconditions.checkArgument(keys != null, KEYS_ARRAY_MUST_NOT_BE_NULL_MESSAGE); this.keys = Arrays.copyOf(keys, keys.length); if (parameterValues != null) { for (int i = 0; i < parameterValues.length; i++) { frame[keys[i]] = parameterValues[i]; } } } /** * Returns the value stored inside the matching frame. * * @param position * @return the element stored in the selected position in the frame, or null if it is not yet set * @throws IndexOutOfBoundsException * if position is negative * @throws IllegalArgumentException * if the position is larger then the length of the frame */ public Object getValue(int position) { Preconditions.checkElementIndex(position, frame.length); return frame[position]; } /** * Sets the value of the variable at the given position. For internal use in LS matching only. * * @param position the position of the variable within the frame * @param value the value to be set for the variable */ public void setValue(int position, Object value) { Preconditions.checkElementIndex(position, frame.length); frame[position] = value; } /** * Call for setting the parameter values (or null if a value is unspecified). The values will only be visible in the * MatchingFrame instance after {@link #setKeys(int[])} is called. * * @param parameterValues a non-null array of values; a value might be null if it is not specified early */ public void setParameterValues(Object[] parameterValues) { //Cannot write precondition checking here, as required information is not always available this.parameterValues = Arrays.copyOf(parameterValues, parameterValues.length); } public boolean testAndSetValue(Integer position, Object value) { Preconditions.checkElementIndex(position, frame.length); if (frame[position] == null) { frame[position] = value; return true; } else { return frame[position].equals(value); } } /** * @return the pattern this frame is attached to */ public Object getPattern() { return pattern; } public MatchingKey getKey() { Object[] key = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { key[i] = frame[keys[i]]; } return new MatchingKey(key); } public MatchingFrame clone() { MatchingFrame clone = (keys == null) ? new MatchingFrame(pattern, frame.length) : new MatchingFrame(pattern, keys, frame.length); clone.frame = Arrays.copyOf(frame, frame.length); clone.parameterValues = this.parameterValues; return clone; } public String toString() { StringBuilder builder = new StringBuilder(); for (int i = 0; i < frame.length; i++) { builder.append("frame[" + i + "]\t" + (frame[i] == null ? "null" : frame[i]).toString() + "\n"); } return builder.toString(); } @Override public int getSize() { return frame.length; } @Override public Object get(int index) { return getValue(index); } @Override public Object[] getElements() { Preconditions.checkState(keys != null, KEYS_ARRAY_SETUP_MISSING_MESSAGE); //Redefining to trim the results to keySize Object[] allElements = new Object[keys.length]; for (int i = 0; i < keys.length; ++i) allElements[i] = get(keys[i]); return allElements; } }