001/* 002 * Syncany, www.syncany.org 003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package org.syncany.operations.down; 019 020import java.util.Comparator; 021 022import org.syncany.database.DatabaseVersionHeader; 023import org.syncany.database.VectorClock; 024import org.syncany.database.VectorClock.VectorClockComparison; 025 026/** 027 * Comparator to be used when comparing {@link DatabaseVersionHeader}s. The comparison precedence 028 * is as follows, if the comparator is time sensitive. 029 * 030 * <ol> 031 * <li>Comparison by {@link VectorClock}</li> 032 * <li>Comparison by timestamp/date</li> 033 * <li>Comparison by name of the client</li> 034 * </ol> 035 * 036 * If the comparator is not time sensitive, the ordering is specified solely by the {@link VectorClock}s. 037 * Larger and smaller {@link VectorClock}s result in larger, respectively smaller {@link DatabaseVersionHeader}s. 038 * Equal and simultaneous {@link VectorClock}s result in equal {@link DatabaseVersionHeader}s. Note that in 039 * this case the name of the client is not used either. 040 * 041 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 042 */ 043public class DatabaseVersionHeaderComparator implements Comparator<DatabaseVersionHeader> { 044 private boolean considerTime; 045 046 public DatabaseVersionHeaderComparator(boolean considerTime) { 047 this.considerTime = considerTime; 048 } 049 050 /** 051 * Compares the two given database versions headers and returns -1, 0 or 1 depending on 052 * which header is considered larger. See {@link DatabaseVersionHeaderComparator class description} 053 * for details regarding the precedence. 054 * 055 * @return -1 if dbvh1 is smaller than dbvh2, 0 if they are equal, 1 if dbvh1 is greater than dbvh2 056 */ 057 @Override 058 public int compare(DatabaseVersionHeader dbvh1, DatabaseVersionHeader dbvh2) { 059 return compareByVectorClock(dbvh1, dbvh2); 060 } 061 062 private int compareByVectorClock(DatabaseVersionHeader dbvh1, DatabaseVersionHeader dbvh2) { 063 VectorClockComparison vectorClockComparison = VectorClock.compare(dbvh1.getVectorClock(), dbvh2.getVectorClock()); 064 065 if (vectorClockComparison == VectorClockComparison.SIMULTANEOUS || vectorClockComparison == VectorClockComparison.EQUAL) { 066 if (considerTime) { 067 return compareByTimestamp(dbvh1, dbvh2); 068 } 069 else { 070 return 0; 071 } 072 } 073 074 return vectorClockComparison == VectorClockComparison.SMALLER ? -1 : 1; 075 } 076 077 private int compareByTimestamp(DatabaseVersionHeader dbvh1, DatabaseVersionHeader dbvh2) { 078 int timestampComparison = Long.compare(dbvh1.getDate().getTime(), dbvh2.getDate().getTime()); 079 080 if (timestampComparison == 0) { 081 return compareByClientName(dbvh1, dbvh2); 082 } 083 else { 084 return timestampComparison; 085 } 086 } 087 088 private int compareByClientName(DatabaseVersionHeader dbvh1, DatabaseVersionHeader dbvh2) { 089 return dbvh1.getClient().compareTo(dbvh2.getClient()); 090 } 091}