/* * Copyright 2009-2016 Tilmann Zaeschke. All rights reserved. * * This file is part of ZooDB. * * ZooDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ZooDB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZooDB. If not, see <http://www.gnu.org/licenses/>. * * See the README and COPYING files for further information. */ package org.zoodb.internal.query; import java.lang.reflect.Field; import java.util.Comparator; import java.util.List; import org.zoodb.internal.ZooFieldDef; import org.zoodb.internal.util.DBLogger; import org.zoodb.internal.util.Pair; public class QueryComparator<T> implements Comparator<T> { private final List<Pair<ZooFieldDef, Boolean>> ordering; public QueryComparator(List<Pair<ZooFieldDef, Boolean>> ordering) { this.ordering = ordering; } @SuppressWarnings("unchecked") @Override public int compare(Object o1, Object o2) { for (Pair<ZooFieldDef, Boolean> p: ordering) { ZooFieldDef fd = p.getA(); Field f = fd.getJavaField(); Object o1Val; try { o1Val = f.get(o1); } catch (IllegalArgumentException e) { throw DBLogger.newFatalInternal("Cannot access field: " + fd.getName() + " class=\"" + o1.getClass().getName() + "\"," + " declaring class=\"" + f.getDeclaringClass().getName()+ "\"", e); } catch (IllegalAccessException e) { throw DBLogger.newFatalInternal("Cannot access field: " + fd.getName(), e); } Object o2Val; try { o2Val = f.get(o2); } catch (IllegalArgumentException e) { throw DBLogger.newFatalInternal("Cannot access field: " + fd.getName() + " class=\"" + o2.getClass().getName() + "\"," + " declaring class=\"" + f.getDeclaringClass().getName()+ "\"", e); } catch (IllegalAccessException e) { throw DBLogger.newFatalInternal("Cannot access field: " + fd.getName(), e); } if (o1Val == null) { if (o2Val == null) { continue; } //ordering of null-value fields is not specified (JDO 3.0 14.6.6: Ordering Statement) //We specify: (null <= 'x' ==true) if (o2Val != null) { return ret(-1, p); } } else if (o2Val != null && o1Val != null) { if (o2Val.equals(o1Val)) { continue; } if (o2Val instanceof Comparable) { Comparable<Object> qComp = (Comparable<Object>) o2Val; int res = -qComp.compareTo(o1Val); //-1:< 0:== 1:> if (res == 0) { continue; } else { return ret(res, p); } } } else { //here: o2Val == null && o1Val != null //Ordering of null-value fields is not specified (JDO 3.0 14.6.6: Ordering Statement) //We specify: (null <= 'x' ==true) return ret(1, p); } } return 0; } private int ret(int result, Pair<ZooFieldDef, Boolean> p) { return p.getB() ? result : -result; } }