diff options
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/common/JavaTransitiveInstancesKey.java')
-rw-r--r-- | subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/common/JavaTransitiveInstancesKey.java | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/common/JavaTransitiveInstancesKey.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/common/JavaTransitiveInstancesKey.java new file mode 100644 index 00000000..eb972c2d --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/common/JavaTransitiveInstancesKey.java | |||
@@ -0,0 +1,165 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Bergmann Gabor, Istvan Rath and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.context.common; | ||
10 | |||
11 | |||
12 | |||
13 | /** | ||
14 | * Instance tuples are of form (x), where object x is an instance of the given Java class or its subclasses. | ||
15 | * <p> Fine print 1: classes with the same name are considered equivalent. | ||
16 | * Can be instantiated with class name, even if the class itself is not loaded yet; but if the class is available, passing it in the constructor is beneficial to avoid classloading troubles. | ||
17 | * <p> Fine print 2: primitive types (char, etc.) are transparently treated as their wrapper class (Character, etc.). | ||
18 | * <p> Non-enumerable type, can only be checked. | ||
19 | * <p> Stateless type (objects can't change their type) | ||
20 | * @author Bergmann Gabor | ||
21 | * | ||
22 | */ | ||
23 | public class JavaTransitiveInstancesKey extends BaseInputKeyWrapper<String> { | ||
24 | |||
25 | /** | ||
26 | * The actual Class whose (transitive) instances this relation contains. Can be null at compile time, if only the name is available. | ||
27 | * Can be a primitive. | ||
28 | */ | ||
29 | private Class<?> cachedOriginalInstanceClass; | ||
30 | |||
31 | /** | ||
32 | * Same as {@link #cachedOriginalInstanceClass}, but primitive classes are replaced with their wrapper classes (e.g. int --> java.lang.Integer). | ||
33 | */ | ||
34 | private Class<?> cachedWrapperInstanceClass; | ||
35 | |||
36 | /** | ||
37 | * Preferred constructor. | ||
38 | */ | ||
39 | public JavaTransitiveInstancesKey(Class<?> instanceClass) { | ||
40 | this(primitiveTypeToWrapperClass(instanceClass).getName()); | ||
41 | this.cachedOriginalInstanceClass = instanceClass; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * Call this constructor only in contexts where the class itself is not available for loading, e.g. it has not yet been compiled. | ||
46 | */ | ||
47 | public JavaTransitiveInstancesKey(String className) { | ||
48 | super(className); | ||
49 | } | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Returns null if class cannot be loaded. | ||
54 | */ | ||
55 | private Class<?> getOriginalInstanceClass() { | ||
56 | if (cachedOriginalInstanceClass == null) { | ||
57 | try { | ||
58 | resolveClassInternal(); | ||
59 | } catch (ClassNotFoundException e) { | ||
60 | // class not yet available at this point | ||
61 | } | ||
62 | } | ||
63 | return cachedOriginalInstanceClass; | ||
64 | } | ||
65 | |||
66 | |||
67 | /** | ||
68 | * @return non-null instance class | ||
69 | * @throws ClassNotFoundException | ||
70 | */ | ||
71 | private Class<?> forceGetOriginalInstanceClass() throws ClassNotFoundException { | ||
72 | if (cachedOriginalInstanceClass == null) { | ||
73 | resolveClassInternal(); | ||
74 | } | ||
75 | return cachedOriginalInstanceClass; | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * @return non-null instance class, wrapped if primitive class | ||
80 | * @throws ClassNotFoundException | ||
81 | */ | ||
82 | public Class<?> forceGetWrapperInstanceClass() throws ClassNotFoundException { | ||
83 | forceGetOriginalInstanceClass(); | ||
84 | return getWrapperInstanceClass(); | ||
85 | } | ||
86 | /** | ||
87 | * @return non-null instance class, wrapped if primitive class | ||
88 | * @throws ClassNotFoundException | ||
89 | */ | ||
90 | public Class<?> forceGetInstanceClass() throws ClassNotFoundException { | ||
91 | return forceGetWrapperInstanceClass(); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * @return instance class, wrapped if primitive class, null if class cannot be loaded | ||
96 | */ | ||
97 | public Class<?> getWrapperInstanceClass() { | ||
98 | if (cachedWrapperInstanceClass == null) { | ||
99 | cachedWrapperInstanceClass = primitiveTypeToWrapperClass(getOriginalInstanceClass()); | ||
100 | } | ||
101 | return cachedWrapperInstanceClass; | ||
102 | } | ||
103 | /** | ||
104 | * @return instance class, wrapped if primitive class, null if class cannot be loaded | ||
105 | */ | ||
106 | public Class<?> getInstanceClass() { | ||
107 | return getWrapperInstanceClass(); | ||
108 | } | ||
109 | |||
110 | private void resolveClassInternal() throws ClassNotFoundException { | ||
111 | cachedOriginalInstanceClass = Class.forName(wrappedKey); | ||
112 | } | ||
113 | |||
114 | @Override | ||
115 | public String getPrettyPrintableName() { | ||
116 | getWrapperInstanceClass(); | ||
117 | return cachedWrapperInstanceClass == null ? wrappedKey == null ? "<null>" : wrappedKey : cachedWrapperInstanceClass.getName(); | ||
118 | } | ||
119 | |||
120 | @Override | ||
121 | public String getStringID() { | ||
122 | return "javaClass#"+ getPrettyPrintableName(); | ||
123 | } | ||
124 | |||
125 | @Override | ||
126 | public int getArity() { | ||
127 | return 1; | ||
128 | } | ||
129 | |||
130 | @Override | ||
131 | public boolean isEnumerable() { | ||
132 | return false; | ||
133 | } | ||
134 | |||
135 | @Override | ||
136 | public String toString() { | ||
137 | return this.getPrettyPrintableName(); | ||
138 | } | ||
139 | |||
140 | private static Class<?> primitiveTypeToWrapperClass(Class<?> instanceClass) { | ||
141 | if (instanceClass != null && instanceClass.isPrimitive()) { | ||
142 | if (Void.TYPE.equals(instanceClass)) | ||
143 | return Void.class; | ||
144 | if (Boolean.TYPE.equals(instanceClass)) | ||
145 | return Boolean.class; | ||
146 | if (Character.TYPE.equals(instanceClass)) | ||
147 | return Character.class; | ||
148 | if (Byte.TYPE.equals(instanceClass)) | ||
149 | return Byte.class; | ||
150 | if (Short.TYPE.equals(instanceClass)) | ||
151 | return Short.class; | ||
152 | if (Integer.TYPE.equals(instanceClass)) | ||
153 | return Integer.class; | ||
154 | if (Long.TYPE.equals(instanceClass)) | ||
155 | return Long.class; | ||
156 | if (Float.TYPE.equals(instanceClass)) | ||
157 | return Float.class; | ||
158 | if (Double.TYPE.equals(instanceClass)) | ||
159 | return Double.class; | ||
160 | } | ||
161 | return instanceClass; | ||
162 | } | ||
163 | |||
164 | |||
165 | } | ||