// Copyright 2017 JanusGraph Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.janusgraph.graphdb.internal;
import com.google.common.base.Preconditions;
import org.janusgraph.core.PropertyKey;
import org.janusgraph.core.JanusGraphElement;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
* @author Matthias Broecheler (me@matthiasb.com)
*/
public class OrderList implements Comparator<JanusGraphElement>, Iterable<OrderList.OrderEntry> {
public static final OrderList NO_ORDER = new OrderList() {{
makeImmutable();
}};
private List<OrderEntry> list = new ArrayList<OrderList.OrderEntry>(3);
private boolean immutable = false;
public void add(PropertyKey key, Order order) {
Preconditions.checkArgument(!immutable, "This OrderList has been closed");
list.add(new OrderEntry(key, order));
}
public boolean isEmpty() {
return list.isEmpty();
}
public PropertyKey getKey(int position) {
return list.get(position).getKey();
}
public Order getOrder(int position) {
return list.get(position).getOrder();
}
public int size() {
return list.size();
}
public boolean containsKey(PropertyKey key) {
for (int i = 0; i < list.size(); i++) if (getKey(i).equals(key)) return true;
return false;
}
public void makeImmutable() {
this.immutable = true;
}
public boolean isImmutable() {
return immutable;
}
/**
* Whether all individual orders are the same
*
* @return
*/
public boolean hasCommonOrder() {
Order lastOrder = null;
for (OrderEntry oe : list) {
if (lastOrder==null) lastOrder=oe.order;
else if (lastOrder!=oe.order) return false;
}
return true;
}
public Order getCommonOrder() {
Preconditions.checkArgument(hasCommonOrder(),"This OrderList does not have a common order");
return isEmpty()?Order.DEFAULT:getOrder(0);
}
@Override
public Iterator<OrderEntry> iterator() {
return list.iterator();
}
@Override
public String toString() {
return list.toString();
}
@Override
public int hashCode() {
return list.hashCode();
}
@Override
public boolean equals(Object oth) {
if (this == oth) return true;
else if (oth == null) return false;
else if (!getClass().isInstance(oth)) return false;
return list.equals(((OrderList) oth).list);
}
@Override
public int compare(JanusGraphElement o1, JanusGraphElement o2) {
for (int i = 0; i < list.size(); i++) {
int cmp = list.get(i).compare(o1, o2);
if (cmp != 0) return cmp;
}
// return o1.compareTo(o2);
return 0;
}
/**
* @author Matthias Broecheler (me@matthiasb.com)
*/
public static class OrderEntry implements Comparator<JanusGraphElement> {
private final PropertyKey key;
private final Order order;
public OrderEntry(PropertyKey key, Order order) {
Preconditions.checkNotNull(key);
Preconditions.checkNotNull(order);
this.key = key;
this.order = order;
}
public PropertyKey getKey() {
return key;
}
public Order getOrder() {
return order;
}
@Override
public int hashCode() {
return key.hashCode() * 1003 + order.hashCode();
}
@Override
public int compare(JanusGraphElement o1, JanusGraphElement o2) {
Object v1 = o1.valueOrNull(key);
Object v2 = o2.valueOrNull(key);
if (v1 == null || v2 == null) {
if (v1 == null && v2 == null) return 0;
else if (v1 == null) return 1;
else return -1; //v2==null
} else {
return order.modulateNaturalOrder(((Comparable) v1).compareTo(v2));
}
}
@Override
public boolean equals(Object oth) {
if (this == oth) return true;
else if (oth == null) return false;
else if (!getClass().isInstance(oth)) return false;
OrderEntry o = (OrderEntry) oth;
return key.equals(o.key) && order == o.order;
}
@Override
public String toString() {
return order + "(" + key + ")";
}
}
}