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 package io.github.prolobjectlink.prolog;
27
28 import java.lang.reflect.Array;
29 import java.lang.reflect.ParameterizedType;
30 import java.lang.reflect.Type;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.Map;
34 import java.util.Set;
35
36
37
38
39
40
41
42 public abstract class AbstractConverter<T> implements PrologConverter<T> {
43
44 public static final String SIMPLE_ATOM_REGEX = ".|[a-z][A-Za-z0-9_]*";
45 private static final String IMPOSIBLE_CONVERT = "Impossible convert '";
46 private static final String FROM = "' from '";
47 private static final String TO = "' to '";
48
49 protected final HashMap<String, PrologVariable> sharedVariables;
50 protected final HashMap<String, T> sharedPrologVariables;
51 protected final PrologProvider provider;
52
53 protected AbstractConverter() {
54 sharedVariables = new HashMap<String, PrologVariable>();
55 sharedPrologVariables = new HashMap<String, T>();
56 provider = createProvider();
57 }
58
59 protected final PrologLogger getLogger() {
60 return provider.getLogger();
61 }
62
63 private final boolean isQuoted(String functor) {
64 if (!functor.isEmpty()) {
65 char beginChar = functor.charAt(0);
66 char endChar = functor.charAt(functor.length() - 1);
67 return beginChar == '\'' && endChar == '\'';
68 }
69 return false;
70 }
71
72 public final String removeQuoted(String functor) {
73 if (isQuoted(functor)) {
74 String newFunctor = "";
75 newFunctor += functor.substring(1, functor.length() - 1);
76 return newFunctor;
77 }
78 return functor;
79 }
80
81 public final PrologTerm[] toTermArray(T[] terms) {
82 PrologTerm[] iTerms = new PrologTerm[terms.length];
83 for (int i = 0; i < terms.length; i++) {
84 iTerms[i] = toTerm(terms[i]);
85 }
86 return iTerms;
87 }
88
89 public final PrologTerm[][] toTermMatrix(T[][] terms) {
90 int n = terms.length;
91 int m = terms[0].length;
92 PrologTerm[][] iTerms = new PrologTerm[n][m];
93 for (int i = 0; i < n; i++) {
94 iTerms[i] = toTermArray(terms[i]);
95 }
96 return iTerms;
97 }
98
99 public final Map<String, PrologTerm> toTermMap(Map<String, T> map) {
100 Map<String, PrologTerm> solutionMap = new HashMap<String, PrologTerm>(map.size());
101 Set<String> keys = map.keySet();
102 for (String key : keys) {
103 solutionMap.put(key, toTerm(map.get(key)));
104 }
105 return solutionMap;
106 }
107
108 public final Map<String, PrologTerm>[] toTermMapArray(Map<String, T>[] map) {
109 Map<String, PrologTerm>[] solutions = new Map[map.length];
110 for (int i = 0; i < map.length; i++) {
111 solutions[i] = toTermMap(map[i]);
112 }
113 return solutions;
114 }
115
116 public final <K extends PrologTerm> K toTerm(Object o, Class<K> from) {
117 Class<T> clazz = getGenericClass();
118 if (clazz != null && clazz.isAssignableFrom(o.getClass())) {
119 PrologTerm term = toTerm((T) o);
120 if (from.isAssignableFrom(term.getClass())) {
121 return from.cast(term);
122 }
123 }
124 throw new PrologError(
125
126 IMPOSIBLE_CONVERT + o + FROM + from + "'"
127
128 );
129 }
130
131 public final <K extends PrologTerm> K[] toTermArray(Object[] os, Class<K[]> from) {
132 Class<T> clazz = getGenericClass();
133 Class<?> cType = os.getClass().getComponentType();
134 if (clazz != null && clazz.isAssignableFrom(cType)) {
135 PrologTerm[] terms = toTermArray((T[]) os);
136 if (from.isAssignableFrom(terms.getClass())) {
137 return from.cast(terms);
138 }
139 }
140 throw new PrologError(
141
142 IMPOSIBLE_CONVERT +
143
144 Arrays.toString(os) +
145
146 FROM + from + "'"
147
148 );
149 }
150
151 public final <K extends PrologTerm> K[][] toTermMatrix(Object[][] oss, Class<K[][]> from) {
152 Class<T> clazz = getGenericClass();
153 Class<?> cType = oss.getClass().getComponentType();
154 Class<?> c = Array.newInstance(clazz, 0).getClass();
155 if (c.isAssignableFrom(cType)) {
156 PrologTerm[][] terms = toTermMatrix((T[][]) oss);
157 if (from.isAssignableFrom(terms.getClass())) {
158 return from.cast(terms);
159 }
160 }
161 throw new PrologError(
162
163 IMPOSIBLE_CONVERT +
164
165 Arrays.toString(oss) +
166
167 FROM + from + "'"
168
169 );
170 }
171
172 public final <K extends PrologTerm, V extends Object> Map<String, PrologTerm> toTermMap(Map<String, V> map,
173 Class<K> from) {
174 Map<String, PrologTerm> solutionMap = new HashMap<String, PrologTerm>(map.size());
175 Set<String> keys = map.keySet();
176 for (String key : keys) {
177 Object o = map.get(key);
178 PrologTerm term = toTerm(o, from);
179 solutionMap.put(key, term);
180 }
181 return solutionMap;
182 }
183
184 public final <K extends PrologTerm, V extends Object> Map<String, PrologTerm>[] toTermMapArray(Map<String, V>[] map,
185 Class<K> from) {
186 Map<String, PrologTerm>[] solutions = new Map[map.length];
187 for (int i = 0; i < map.length; i++) {
188 solutions[i] = toTermMap(map[i], from);
189 }
190 return solutions;
191 }
192
193 public final <K> K fromTerm(PrologTerm term, Class<K> to) {
194 T t = fromTerm(term);
195 if (to.isAssignableFrom(t.getClass())) {
196 return to.cast(t);
197 }
198 throw new PrologError(
199
200 IMPOSIBLE_CONVERT + term + TO + to + "'"
201
202 );
203 }
204
205 public final <K> K[] fromTermArray(PrologTerm[] terms, Class<K[]> to) {
206 T[] ts = fromTermArray(terms);
207 if (to.isAssignableFrom(ts.getClass())) {
208 return to.cast(ts);
209 }
210 throw new PrologError(
211
212 IMPOSIBLE_CONVERT + Arrays.toString(terms) + TO + to + "'"
213
214 );
215 }
216
217 public final <K> K fromTerm(PrologTerm head, PrologTerm[] body, Class<K> to) {
218 T t = fromTerm(head, body);
219 if (to.isAssignableFrom(t.getClass())) {
220 return to.cast(t);
221 }
222 throw new PrologError(
223
224 IMPOSIBLE_CONVERT +
225
226 head + " and " + Arrays.toString(body) +
227
228 TO + to + "'"
229
230 );
231 }
232
233 public final Class<T> getGenericClass() {
234 Class<T> templateClass = null;
235 Type[] generics = getClass().getGenericInterfaces();
236 if (generics.length == 1 && generics[0] instanceof ParameterizedType) {
237 ParameterizedType parameterized = (ParameterizedType) generics[0];
238 Type type = parameterized.getActualTypeArguments()[0];
239 if (type instanceof Class<?>) {
240 templateClass = (Class<T>) type;
241 }
242 }
243 return templateClass;
244 }
245
246 @Override
247 public int hashCode() {
248 final int prime = 31;
249 int result = 1;
250 result = prime * result + ((sharedPrologVariables == null) ? 0 : sharedPrologVariables.hashCode());
251 result = prime * result + ((sharedVariables == null) ? 0 : sharedVariables.hashCode());
252 return result;
253 }
254
255 @Override
256 public boolean equals(Object obj) {
257 if (this == obj)
258 return true;
259 if (obj == null)
260 return false;
261 if (getClass() != obj.getClass())
262 return false;
263 AbstractConverter<?> other = (AbstractConverter<?>) obj;
264 if (sharedPrologVariables == null) {
265 if (other.sharedPrologVariables != null)
266 return false;
267 } else if (!sharedPrologVariables.equals(other.sharedPrologVariables)) {
268 return false;
269 }
270 if (sharedVariables == null) {
271 if (other.sharedVariables != null)
272 return false;
273 } else if (!sharedVariables.equals(other.sharedVariables)) {
274 return false;
275 }
276 return true;
277 }
278
279 }