View Javadoc

1   /*-
2    * #%L
3    * prolobjectlink-jpi-jlog
4    * %%
5    * Copyright (C) 2020 - 2021 Prolobjectlink Project
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as
9    * published by the Free Software Foundation, either version 3 of the
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Public
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/gpl-3.0.html>.
20   * #L%
21   */
22  package io.github.prolobjectlink.prolog.jlog;
23  
24  import java.util.Collection;
25  import java.util.Iterator;
26  import java.util.LinkedHashMap;
27  import java.util.LinkedHashSet;
28  import java.util.Map;
29  import java.util.Set;
30  
31  import io.github.prolobjectlink.prolog.AbstractIterator;
32  import io.github.prolobjectlink.prolog.PrologMap;
33  import io.github.prolobjectlink.prolog.PrologProvider;
34  import io.github.prolobjectlink.prolog.PrologTerm;
35  import io.github.prolobjectlink.prolog.PrologTermType;
36  
37  /**
38   * A PrologTerm that maps PrologTerm keys to PrologTerm values. A map cannot
39   * contain duplicate keys. Each key can map to at most one value.
40   * 
41   * @author Jose Zalacain
42   * @since 1.1
43   */
44  public final class JLogMap extends JLogTerm implements PrologMap {
45  
46  	private Map<PrologTerm, PrologTerm> map;
47  
48  	JLogMap(PrologProvider provider, int size) {
49  		super(PrologTermType.MAP_TYPE, provider);
50  		map = new LinkedHashMap<PrologTerm, PrologTerm>(size);
51  	}
52  
53  	JLogMap(PrologProvider provider, Map<? extends PrologTerm, ? extends PrologTerm> m) {
54  		this(provider);
55  		putAll(m);
56  	}
57  
58  	JLogMap(PrologProvider provider) {
59  		this(provider, 16);
60  	}
61  
62  	public String getFunctor() {
63  		return ".";
64  	}
65  
66  	public PrologTerm[] getArguments() {
67  		PrologProvider p = getProvider();
68  		PrologTerm[] args = new PrologTerm[map.size()];
69  		Set<Entry<PrologTerm, PrologTerm>> s = entrySet();
70  		Iterator<Entry<PrologTerm, PrologTerm>> i = s.iterator();
71  		for (int j = 0; j < args.length && i.hasNext(); j++) {
72  			Entry<PrologTerm, PrologTerm> e = i.next();
73  			args[j] = new JLogEntry(p, e.getKey(), e.getValue());
74  		}
75  		return args;
76  	}
77  
78  	public PrologTerm getArgument(int index) {
79  		int idx = 0;
80  		PrologTerm term = null;
81  		checkIndex(index, size());
82  		Iterator<PrologTerm> i = iterator();
83  		for (; i.hasNext() && idx <= index; idx++) {
84  			term = i.next();
85  			if (idx == index) {
86  				return term;
87  			}
88  		}
89  		return term;
90  	}
91  
92  	public int hashCode() {
93  		int result = 0;
94  		final int prime = 31;
95  		result = prime * result + ((map == null) ? 0 : map.hashCode());
96  		return result;
97  	}
98  
99  	public boolean equals(Object obj) {
100 		if (this == obj)
101 			return true;
102 		if (obj == null)
103 			return false;
104 		if (getClass() != obj.getClass())
105 			return false;
106 		JLogMap other = (JLogMap) obj;
107 		if (map == null) {
108 			if (other.map != null)
109 				return false;
110 		} else if (!map.equals(other.map)) {
111 			return false;
112 		}
113 		return true;
114 	}
115 
116 	@Override
117 	public String toString() {
118 		StringBuilder b = new StringBuilder();
119 		Set<Entry<PrologTerm, PrologTerm>> set = entrySet();
120 		Iterator<Entry<PrologTerm, PrologTerm>> i = set.iterator();
121 		b.append('[');
122 		while (i.hasNext()) {
123 			Entry<PrologTerm, PrologTerm> entry = i.next();
124 			b.append(entry.getKey());
125 			b.append('-');
126 			b.append(entry.getValue());
127 			if (i.hasNext()) {
128 				b.append(',');
129 				b.append(' ');
130 			}
131 		}
132 		b.append(']');
133 		return "" + b + "";
134 	}
135 
136 	@Override
137 	public Iterator<PrologTerm> iterator() {
138 		return new PrologMapIterator();
139 	}
140 
141 	@Override
142 	public PrologTerm getHead() {
143 		return iterator().next();
144 	}
145 
146 	@Override
147 	public PrologTerm getTail() {
148 		JLogMap m = new JLogMap(provider, map);
149 		m.remove(((Entry<?, ?>) getHead()).getKey());
150 		return m;
151 	}
152 	
153 	public void putAll(Collection<Entry<PrologTerm, PrologTerm>> entries) {
154 		for (Entry<PrologTerm, PrologTerm> entry : entries) {
155 			put(entry);
156 		}
157 	}
158 
159 	public boolean contains(Entry<PrologTerm, PrologTerm> entry) {
160 		PrologTerm value = get(entry.getKey());
161 		return value != null ? value.equals(entry.getValue()) : false;
162 	}
163 
164 	public void remove(Entry<PrologTerm, PrologTerm> entry) {
165 		remove(entry.getKey());
166 	}
167 
168 	public void put(Entry<PrologTerm, PrologTerm> entry) {
169 		put(entry.getKey(), entry.getValue());
170 	}
171 
172 	private class PrologMapIterator extends AbstractIterator<PrologTerm> implements Iterator<PrologTerm> {
173 
174 		private final Set<PrologTerm> set;
175 		private final Iterator<PrologTerm> itr;
176 
177 		private PrologMapIterator() {
178 			set = new LinkedHashSet<PrologTerm>(map.size());
179 			for (Iterator<Entry<PrologTerm, PrologTerm>> i = map.entrySet().iterator(); i.hasNext();) {
180 				Entry<PrologTerm, PrologTerm> e = i.next();
181 				PrologTerm t = new JLogEntry(provider, e.getKey(), e.getValue());
182 				set.add(t);
183 			}
184 			itr = set.iterator();
185 		}
186 
187 		@Override
188 		public boolean hasNext() {
189 			return itr.hasNext();
190 		}
191 
192 		@Override
193 		public PrologTerm next() {
194 			return itr.next();
195 		}
196 
197 	}
198 
199 	public PrologTerm put(PrologTerm key, PrologTerm value) {
200 		return map.put(key, value);
201 	}
202 
203 	public Set<Entry<PrologTerm, PrologTerm>> entrySet() {
204 		return map.entrySet();
205 	}
206 
207 	@Override
208 	public boolean containsKey(Object key) {
209 		return map.containsKey(key);
210 	}
211 
212 	@Override
213 	public boolean containsValue(Object value) {
214 		return map.containsValue(value);
215 	}
216 
217 	@Override
218 	public PrologTerm get(Object key) {
219 		return map.get(key);
220 	}
221 
222 	@Override
223 	public PrologTerm remove(Object key) {
224 		return map.remove(key);
225 	}
226 
227 	@Override
228 	public void putAll(Map<? extends PrologTerm, ? extends PrologTerm> m) {
229 		map.putAll(m);
230 	}
231 
232 	@Override
233 	public Set<PrologTerm> keySet() {
234 		return map.keySet();
235 	}
236 
237 	@Override
238 	public Collection<PrologTerm> values() {
239 		return map.values();
240 	}
241 
242 	@Override
243 	public boolean isEmpty() {
244 		return map.isEmpty();
245 	}
246 
247 	@Override
248 	public void clear() {
249 		map.clear();
250 	}
251 
252 	@Override
253 	public int size() {
254 		return map.size();
255 	}
256 
257 	@Override
258 	public int getArity() {
259 		if (map.size() > 0) {
260 			return 2;
261 		}
262 		return 0;
263 	}
264 
265 	@Override
266 	public PrologTerm getTerm() {
267 		return this;
268 	}
269 
270 	@Override
271 	public boolean isEvaluable() {
272 		return false;
273 	}
274 
275 	@Override
276 	public boolean isCompound() {
277 		return true;
278 	}
279 
280 }