View Javadoc

1   /*-
2    * #%L
3    * prolobjectlink-jpi
4    * %%
5    * Copyright (C) 2012 - 2019 Prolobjectlink Project
6    * %%
7    * Permission is hereby granted, free of charge, to any person obtaining a copy
8    * of this software and associated documentation files (the "Software"), to deal
9    * in the Software without restriction, including without limitation the rights
10   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11   * copies of the Software, and to permit persons to whom the Software is
12   * furnished to do so, subject to the following conditions:
13   * 
14   * The above copyright notice and this permission notice shall be included in
15   * all copies or substantial portions of the Software.
16   * 
17   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23   * THE SOFTWARE.
24   * #L%
25   */
26  package io.github.prolobjectlink.prolog;
27  
28  import static io.github.prolobjectlink.prolog.PrologTermType.ATOM_TYPE;
29  import static io.github.prolobjectlink.prolog.PrologTermType.DOUBLE_TYPE;
30  import static io.github.prolobjectlink.prolog.PrologTermType.FALSE_TYPE;
31  import static io.github.prolobjectlink.prolog.PrologTermType.FLOAT_TYPE;
32  import static io.github.prolobjectlink.prolog.PrologTermType.INTEGER_TYPE;
33  import static io.github.prolobjectlink.prolog.PrologTermType.LIST_TYPE;
34  import static io.github.prolobjectlink.prolog.PrologTermType.LONG_TYPE;
35  import static io.github.prolobjectlink.prolog.PrologTermType.NIL_TYPE;
36  import static io.github.prolobjectlink.prolog.PrologTermType.OBJECT_TYPE;
37  import static io.github.prolobjectlink.prolog.PrologTermType.STRUCTURE_TYPE;
38  import static io.github.prolobjectlink.prolog.PrologTermType.TRUE_TYPE;
39  import static io.github.prolobjectlink.prolog.PrologTermType.VARIABLE_TYPE;
40  
41  import java.lang.reflect.Array;
42  import java.util.ArrayList;
43  import java.util.HashMap;
44  import java.util.List;
45  import java.util.Map;
46  import java.util.Map.Entry;
47  
48  /**
49   * Partial implementation of {@link PrologJavaConverter} interface.
50   * 
51   * @author Jose Zalacain
52   * @since 1.0
53   */
54  public abstract class AbstractJavaConverter implements PrologJavaConverter {
55  
56  	private final PrologProvider provider;
57  
58  	protected AbstractJavaConverter(PrologProvider provider) {
59  		this.provider = provider;
60  	}
61  
62  	public final boolean containQuotes(String functor) {
63  		if (functor != null && !functor.isEmpty()) {
64  			return functor.startsWith("\'") && functor.endsWith("\'");
65  		}
66  		return false;
67  	}
68  
69  	public final String removeQuotes(String functor) {
70  		if (containQuotes(functor)) {
71  			return functor.substring(1, functor.length() - 1);
72  		}
73  		return functor;
74  	}
75  
76  	public final Object toObject(PrologTerm prologTerm) {
77  		if (prologTerm == null) {
78  			return null;
79  		}
80  
81  		switch (prologTerm.getType()) {
82  		case NIL_TYPE:
83  			return null;
84  		case TRUE_TYPE:
85  			return true;
86  		case FALSE_TYPE:
87  			return false;
88  		case ATOM_TYPE:
89  			return removeQuotes(prologTerm.getFunctor());
90  		case INTEGER_TYPE:
91  			return ((PrologInteger) prologTerm).getIntegerValue();
92  		case FLOAT_TYPE:
93  			return ((PrologFloat) prologTerm).getFloatValue();
94  		case LONG_TYPE:
95  			return ((PrologLong) prologTerm).getLongValue();
96  		case DOUBLE_TYPE:
97  			return ((PrologDouble) prologTerm).getDoubleValue();
98  		case VARIABLE_TYPE:
99  			return prologTerm;
100 		case LIST_TYPE:
101 			return toObjectsArray(prologTerm.getArguments());
102 		case STRUCTURE_TYPE:
103 			return prologTerm;
104 		case OBJECT_TYPE:
105 			return prologTerm.getObject();
106 		default:
107 			throw new UnknownTermError(prologTerm);
108 		}
109 	}
110 
111 	public final Object[] toObjectsArray(PrologTerm[] terms) {
112 		Object array = Array.newInstance(Object.class, terms.length);
113 		for (int i = 0; i < terms.length; i++) {
114 			Array.set(array, i, toObject(terms[i]));
115 		}
116 		return (Object[]) array;
117 	}
118 
119 	public final PrologTerm toTerm(Object object) {
120 		// null pointer
121 		if (object == null) {
122 			return provider.prologNil();
123 		}
124 
125 		// string data type
126 		else if (object instanceof String) {
127 			if (((String) object).matches("[A-Z_]*")) {
128 				return provider.newVariable("" + (String) object + "", 0);
129 			}
130 			return provider.newAtom("" + (String) object + "");
131 		}
132 
133 		// primitives and wrappers data types
134 		else if (object.getClass() == char.class || object instanceof Character) {
135 			return provider.newAtom("" + (String) object + "");
136 		} else if (object.getClass() == byte.class || object instanceof Byte) {
137 			return provider.newInteger((Integer) object);
138 		} else if (object.getClass() == short.class || object instanceof Short) {
139 			return provider.newInteger((Integer) object);
140 		} else if (object.getClass() == boolean.class || object instanceof Boolean) {
141 			return (Boolean) object ? provider.prologTrue() : provider.prologFalse();
142 		} else if (object.getClass() == int.class || object instanceof Integer) {
143 			return provider.newInteger((Integer) object);
144 		} else if (object.getClass() == float.class || object instanceof Float) {
145 			return provider.newFloat((Float) object);
146 		} else if (object.getClass() == long.class || object instanceof Long) {
147 			return provider.newLong((Long) object);
148 		} else if (object.getClass() == double.class || object instanceof Double) {
149 			return provider.newDouble((Double) object);
150 		}
151 
152 		// object array
153 		else if (object instanceof Object[]) {
154 			return provider.newList(toTermsArray((Object[]) object));
155 		}
156 
157 		throw new UnknownTermError(object);
158 
159 	}
160 
161 	public final PrologTerm[] toTermsArray(Object[] objects) {
162 		PrologTerm[] terms = new PrologTerm[objects.length];
163 		for (int i = 0; i < objects.length; i++) {
164 			terms[i] = toTerm(objects[i]);
165 		}
166 		return terms;
167 	}
168 
169 	public final List<Map<String, Object>> toObjectMaps(Map<String, PrologTerm>[] maps) {
170 		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(maps.length);
171 		for (Map<String, PrologTerm> map : maps) {
172 			list.add(toObjectMap(map));
173 		}
174 		return list;
175 	}
176 
177 	public final Map<String, Object> toObjectMap(Map<String, PrologTerm> map) {
178 		Map<String, Object> objects = new HashMap<String, Object>(map.size());
179 		for (Entry<String, PrologTerm> entry : map.entrySet()) {
180 			objects.put(entry.getKey(), toObject(entry.getValue()));
181 		}
182 		return objects;
183 	}
184 
185 	public final List<Object> toObjectList(PrologTerm[] terms) {
186 		List<Object> list = new ArrayList<Object>(terms.length);
187 		for (PrologTerm prologTerm : terms) {
188 			list.add(toObject(prologTerm));
189 		}
190 		return list;
191 	}
192 
193 	public final List<List<Object>> toObjectLists(PrologTerm[][] terms) {
194 		List<List<Object>> list = new ArrayList<List<Object>>(terms.length);
195 		for (PrologTerm[] prologTerms : terms) {
196 			list.add(toObjectList(prologTerms));
197 		}
198 		return list;
199 	}
200 
201 	@Override
202 	public int hashCode() {
203 		final int prime = 31;
204 		int result = super.hashCode();
205 		result = prime * result + ((provider == null) ? 0 : provider.hashCode());
206 		return result;
207 	}
208 
209 	@Override
210 	public boolean equals(Object obj) {
211 		if (this == obj)
212 			return true;
213 		if (!super.equals(obj))
214 			return false;
215 		if (getClass() != obj.getClass())
216 			return false;
217 		AbstractJavaConverter other = (AbstractJavaConverter) obj;
218 		if (provider == null) {
219 			if (other.provider != null)
220 				return false;
221 		} else if (!provider.equals(other.provider)) {
222 			return false;
223 		}
224 		return true;
225 	}
226 
227 }