aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/GenericPatternMatch.java
blob: b4de2b7010c3efb5e4bd0495984a8ba3eaf5a151 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*******************************************************************************
 * Copyright (c) 2004-2010 Gabor Bergmann and Daniel Varro
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-v20.html.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/

package tools.refinery.viatra.runtime.api;

import java.util.Arrays;

import tools.refinery.viatra.runtime.api.impl.BasePatternMatch;

/**
 * Generic signature object implementation. 
 *
 * See also the generated matcher and signature of the pattern, with pattern-specific API simplifications.
 *
 * @author Bergmann Gábor
 * @since 0.9
 *
 */
public abstract class GenericPatternMatch extends BasePatternMatch {

    private final GenericQuerySpecification<? extends GenericPatternMatcher> specification;
    private final Object[] array;

    private GenericPatternMatch(GenericQuerySpecification<? extends GenericPatternMatcher> specification, Object[] array) {
        super();
        this.specification = specification;
        this.array = array;
    }

    @Override
    public Object get(String parameterName) {
        Integer index = specification.getPositionOfParameter(parameterName);
        return index == null ? null : array[index];
    }

    @Override
    public Object get(int position) {
        return array[position];
    }

    @Override
    public boolean set(String parameterName, Object newValue) {
        if (!isMutable()) throw new UnsupportedOperationException();
        Integer index = specification.getPositionOfParameter(parameterName);
        if (index == null)
            return false;
        array[index] = newValue;
        return true;
    }

    @Override
    public Object[] toArray() {
        return Arrays.copyOf(array, array.length);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        for (int i = 0; i < array.length; ++i)
            result = prime * result + ((array[i] == null) ? 0 : array[i].hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!(obj instanceof GenericPatternMatch)) { // this should be infrequent
            if (obj == null)
                return false;
            if (!(obj instanceof IPatternMatch))
                return false;
            IPatternMatch other = (IPatternMatch) obj;
            if (!specification().equals(other.specification()))
                return false;
            return Arrays.deepEquals(array, other.toArray());
        }
        final GenericPatternMatch other = (GenericPatternMatch) obj;
        return specification().equals(other.specification()) && Arrays.deepEquals(array, other.array);
    }

    @Override
    public String prettyPrint() {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < array.length; ++i) {
            if (i != 0)
                result.append(", ");
            result.append("\"" + parameterNames().get(i) + "\"=" + prettyPrintValue(array[i]));
        }
        return result.toString();
    }

    @Override
    public GenericQuerySpecification<? extends GenericPatternMatcher> specification() {
        return specification;
    }
    
    /**
     * Returns an empty, mutable match. 
     * Fields of the mutable match can be filled to create a partial match, usable as matcher input. 
     * 
     * @return the empty match
     */
    public static GenericPatternMatch newEmptyMatch(GenericQuerySpecification<? extends GenericPatternMatcher> specification) {
        return new Mutable(specification, new Object[specification.getParameters().size()]);
    }

    /**
     * Returns a mutable (partial) match. 
     * Fields of the mutable match can be filled to create a partial match, usable as matcher input. 
     * 
     * @param parameters
     *            the fixed value of pattern parameters, or null if not bound.
     * @return the new, mutable (partial) match object.
     */
    public static GenericPatternMatch newMutableMatch(GenericQuerySpecification<? extends GenericPatternMatcher> specification, Object... parameters) {
        return new Mutable(specification, parameters);
    }

    /**
     * Returns a new (partial) match. 
     * This can be used e.g. to call the matcher with a partial match. 
     * 
     * <p>The returned match will be immutable. Use {@link #newEmptyMatch(GenericQuerySpecification)} to obtain a mutable match object.
     * 
     * @param parameters
     *            the fixed value of pattern parameters, or null if not bound.
     * @return the (partial) match object.
     */
    public static GenericPatternMatch newMatch(GenericQuerySpecification<? extends GenericPatternMatcher> specification, Object... parameters) {
        return new Immutable(specification, Arrays.copyOf(parameters, parameters.length));
    }
    
    @Override
    public IPatternMatch toImmutable() {
        return isMutable() ? newMatch(specification, array) : this;
    }

    static final class Mutable extends GenericPatternMatch {
        Mutable(GenericQuerySpecification<? extends GenericPatternMatcher> specification, Object[] array) {
            super(specification, array);
        }

        @Override
        public boolean isMutable() {
            return true;
        }
    }
    static final class Immutable extends GenericPatternMatch {
        Immutable(GenericQuerySpecification<? extends GenericPatternMatcher> specification, Object[] array) {
            super(specification, array);
        }

        @Override
        public boolean isMutable() {
            return false;
        }
    }
}