/** * PODD is an OWL ontology database used for scientific project management * * Copyright (C) 2009-2013 The University Of Queensland * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program 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 * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see <http://www.gnu.org/licenses/>. */ package com.github.podd.utils; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentMap; import org.openrdf.model.URI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class OntologyImportsComparator implements Comparator<URI> { private static final Logger log = LoggerFactory.getLogger(OntologyImportsComparator.class); private static final int BEFORE = -1; private static final int EQUALS = 0; private static final int AFTER = 1; private final ConcurrentMap<URI, Set<URI>> importsMap; OntologyImportsComparator(final ConcurrentMap<URI, Set<URI>> importsMap) { this.importsMap = importsMap; } @Override public int compare(final URI o1, final URI o2) { if(o1.equals(o2)) { return OntologyImportsComparator.EQUALS; } Set<URI> set1 = this.importsMap.get(o1); Set<URI> set2 = this.importsMap.get(o2); if(set1 == null) { set1 = Collections.emptySet(); } if(set2 == null) { set2 = Collections.emptySet(); } if(set1.contains(o2) && set2.contains(o1)) { OntologyImportsComparator.log.error("Ontologies have mutual imports: {} {}", o1, o2); throw new RuntimeException("Ontologies have mutual imports: " + o1.stringValue() + " " + o2.stringValue()); } else if(set1.equals(set2)) { return OntologyImportsComparator.EQUALS; } else if(set1.contains(o2)) { return OntologyImportsComparator.AFTER; } else if(set2.contains(o1)) { return OntologyImportsComparator.BEFORE; } else { Set<URI> tempSet1; if(set1.isEmpty()) { tempSet1 = Collections.emptySet(); } else { tempSet1 = new HashSet<>(set1); } Set<URI> tempSet2; if(set2.isEmpty()) { tempSet2 = Collections.emptySet(); } else { tempSet2 = new HashSet<>(set2); } if(!set2.isEmpty()) { for(final URI nextImport1 : set1) { if(set2.contains(nextImport1)) { tempSet1.remove(nextImport1); } } } if(!set1.isEmpty()) { for(final URI nextImport2 : set2) { if(set1.contains(nextImport2)) { tempSet2.remove(nextImport2); } } } if(tempSet1.size() > tempSet2.size()) { return OntologyImportsComparator.AFTER; } else if(tempSet2.size() > tempSet1.size()) { return OntologyImportsComparator.BEFORE; } for(final URI nextImport1 : tempSet1) { final int compare = this.compare(nextImport1, o2); if(compare != OntologyImportsComparator.EQUALS) { return compare; } } for(final URI nextImport2 : tempSet2) { final int compare = this.compare(o1, nextImport2); if(compare != OntologyImportsComparator.EQUALS) { return compare; } } // Default to lexical mapping, as there is no direct semantic link between // them // at this point // FIXME: This should not be part of the comparison as the imports map // should always contain one of the URIs // return o1.stringValue().compareTo(o2.stringValue()); throw new RuntimeException("Could not determine comparison result for ontology imports: " + o1 + " " + o2); } } }