Skip to content

Commit

Permalink
Add the IDRangeHelper class.
Browse files Browse the repository at this point in the history
Create a new class of static method, IDRangeHelper, and move all the
code needed to deal with ID range files to that class. That code will
later be reused by another command.
  • Loading branch information
gouttegd committed Mar 25, 2024
1 parent 94b82fc commit b735ad7
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package org.incenp.obofoundry.kgcl.robot;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneId;
Expand All @@ -31,10 +30,6 @@

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.incenp.obofoundry.idrange.IDRange;
import org.incenp.obofoundry.idrange.IDRangePolicyException;
import org.incenp.obofoundry.idrange.IDRangePolicyParser;
import org.incenp.obofoundry.idrange.IIDRangePolicy;
import org.incenp.obofoundry.kgcl.AutoIDAllocator;
import org.incenp.obofoundry.kgcl.IAutoIDGenerator;
import org.incenp.obofoundry.kgcl.KGCLHelper;
Expand Down Expand Up @@ -231,9 +226,14 @@ private KGCLWriter getRejectedWriter(CommandLine line) throws IOException {
}
}

private IAutoIDGenerator getAutoIDGenerator(CommandLine line, OWLOntology ontology)
throws Exception {
if ( line.hasOption("audo-id-prefix") ) {
private IAutoIDGenerator getAutoIDGenerator(CommandLine line, OWLOntology ontology) throws Exception {
IAutoIDGenerator generator = null;

if ( line.hasOption("auto-id-prefix") ) {
/*
* Manual mode; generate IDs in a range that is explicitly specified on the
* command line.
*/
if ( !line.hasOption("auto-id-min") ) {
throw new Exception("Missing --auto-id-min option for auto-assigned IDs");
}
Expand All @@ -242,76 +242,26 @@ private IAutoIDGenerator getAutoIDGenerator(CommandLine line, OWLOntology ontolo
: lower + 1000;
int width = line.hasOption("auto-id-width") ? Integer.parseInt(line.getOptionValue("auto-id-width")) : 7;
String format = String.format("%s%%0%dd", line.getOptionValue("auto-id-prefix"), width);
return new RandomizedIDGenerator(ontology, format, lower, upper);
generator = new RandomizedIDGenerator(ontology, format, lower, upper);
} else if ( line.hasOption("auto-id-temp-prefix") ) {
/*
* Temporary ID mode; generate temporary IDs that should later be replaced by
* permanent IDs.
*/
String prefix = line.getOptionValue("auto-id-temp-prefix");
return () -> prefix + UUID.randomUUID().toString();
} else if ( line.hasOption("auto-id-range-file") ) {
return getAutoIDGenerator(line, ontology, line.getOptionValue("auto-id-range-file"), false);
generator = () -> prefix + UUID.randomUUID().toString();
} else {
String rangeFile = findIDRangeFile();
if ( rangeFile != null ) {
return getAutoIDGenerator(line, ontology, rangeFile, true);
}
}
return null;
}

private IAutoIDGenerator getAutoIDGenerator(CommandLine line, OWLOntology ontology, String rangeFile,
boolean silent) throws Exception {
IDRangePolicyParser parser = new IDRangePolicyParser(rangeFile);
try {
IIDRangePolicy policy = parser.parse();
IDRange range = null;
if ( line.hasOption("auto-id-range-name") ) {
range = policy.getRange(line.getOptionValue("auto-id-range-name"));
if ( range == null ) {
throw new Exception("Requested range not found in ID range file");
}
}

if ( range == null ) {
range = policy.getRange("kgcl");
}
if ( range == null ) {
range = policy.getRange("KGCL");
}
if ( range == null ) {
range = policy.getRange("ontobot");
}
if ( range == null ) {
range = policy.getRange("Ontobot");
}

if ( range != null ) {
String format = String.format("%s%%0%dd", policy.getPrefix(), policy.getWidth());
return new RandomizedIDGenerator(ontology, format, range.getLowerBound(), range.getUpperBound());
} else if ( !silent ) {
throw new Exception("No range specified and no default range found in ID range file");
}
} catch ( IDRangePolicyException e ) {
if ( !silent ) {
throw new Exception("Cannot parse ID range policy file");
}
}

return null;
}

private String findIDRangeFile() {
FilenameFilter idRangeFilter = new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
return name.endsWith("-idranges.owl");
}
};

File currentDir = new File(".");
String[] rangeFiles = currentDir.list(idRangeFilter);
if ( rangeFiles.length == 1 ) {
return rangeFiles[0];
/*
* Range-file mode; similar to manual mode, but the range is obtained from a
* file of ID ranges.
*/
String rangeFile = line.getOptionValue("auto-id-range-file");
String requestedName = line.getOptionValue("auto-id-range-name");
String[] defaultNames = new String[] { "kgcl", "KGCL", "ontobot", "Ontobot" };

generator = IDRangeHelper.maybeGetIDGenerator(ontology, rangeFile, requestedName, defaultNames, true);
}

return null;
return generator;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* KGCL-Java - KGCL library for Java
* Copyright © 2024 Damien Goutte-Gattat
*
* This program 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.
*
* 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 General Public License for more details.
*
* You should have received a copy of the Gnu General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.incenp.obofoundry.kgcl.robot;

import java.io.File;
import java.io.FilenameFilter;

import org.incenp.obofoundry.idrange.IDRange;
import org.incenp.obofoundry.idrange.IDRangePolicyException;
import org.incenp.obofoundry.idrange.IDRangePolicyParser;
import org.incenp.obofoundry.idrange.IIDRangePolicy;
import org.incenp.obofoundry.kgcl.IAutoIDGenerator;
import org.incenp.obofoundry.kgcl.RandomizedIDGenerator;
import org.incenp.obofoundry.kgcl.SequentialIDGenerator;
import org.semanticweb.owlapi.model.OWLOntology;

/*
* Helper methods to work with OBO-style ID range policy files.
*/
public class IDRangeHelper {

/**
* Finds an ID range policy file in the current directory. This methods looks
* for a single file whose name ends with {@code -idranges.owl} in the current
* directory.
*
* @return The name of the ID range policy file, if such a file exists;
* otherwise {@code null}.
*/
public static String findIDRangeFile() {
FilenameFilter idRangeFilter = new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
return name.endsWith("-idranges.owl");
}
};

File cwd = new File(".");
String[] rangeFiles = cwd.list(idRangeFilter);
if ( rangeFiles.length == 1 ) {
return rangeFiles[0];
}

return null;
}

/**
* Gets an ID generator initialised with data from the specified range file.
*
* @param ontology The ontology to generate IDs for.
* @param rangeFile The range file to initialise the generator with.
* @param rangeName The name of the range to use. This should match the
* {@code allocatedto} annotation of one of the ranges in the
* file. May be {@code null}, in which case the method will
* look for a range that matches one of the alternative names
* instead. If not {@code null} and a corresponding range
* cannot be found, an exception will be thrown.
* @param altNames A list of default range names to use if {@code rangeName} is
* {@code null}.
* @param random If {@code true}, the generator will produce IDs picked at
* random within the target range; otherwise, IDs will be
* picked sequentially.
* @return A newly initialised ID generator.
* @throws IDRangePolicyException If the range file cannot be read for any
* reason, if the requested {@code rangeName}
* cannot be found, or if none of the default
* ranges can be found.
*/
public static IAutoIDGenerator getIDGenerator(OWLOntology ontology, String rangeFile, String rangeName,
String[] altNames, boolean random) throws IDRangePolicyException {

IDRangePolicyParser parser = new IDRangePolicyParser(rangeFile);
IIDRangePolicy policy = parser.parse();
IDRange range = null;

if ( rangeName != null ) {
range = policy.getRange(rangeName);
if ( range == null ) {
throw new IDRangePolicyException("Requested range not found in ID range file");
}
}

int i = 0;
while ( range == null && altNames != null && i < altNames.length ) {
range = policy.getRange(altNames[i++]);
}

if ( range == null ) {
throw new IDRangePolicyException("Not suitable range found in ID range file");
}

String format = String.format("%s%%0%dd", policy.getPrefix(), policy.getWidth());
if ( random ) {
return new RandomizedIDGenerator(ontology, format, range.getLowerBound(), range.getUpperBound());
} else {
return new SequentialIDGenerator(ontology, format, range.getLowerBound(), range.getUpperBound());
}
}

/**
* Gets an ID generator initialised with data from the specified range file, or
* a default file. This method is similar to
* {@link #getIDGenerator(OWLOntology, String, String, String[], boolean)},
* except that if the {@code rangeFile} parameter is {@code null}, it tries to
* find a default range file (using the {@link #findIDRangeFile()} method); in
* that case, no exception will be thrown.
*
* @param ontology The ontology to generate IDs for.
* @param rangeFile The range file to initialise the generator with. If
* {@code null}, the method will try to find a default file.
* @param rangeName The name of the range to use. This should match the
* {@code allocatedto} annotation of one of the ranges in the
* file. May be {@code null}, in which case the method will
* look for a range that matches one of the alternative names
* instead.
* @param altNames A list of default range names to use if {@code rangeName} is
* {@code null}.
* @param random If {@code true}, the generator will produce IDs picked at
* random within the target range; otherwise, IDs will be
* picked sequentially.
* @return A newly initialised ID generator or {@code null} if no range file has
* been specified and no suitable default file was found.
* @throws IDRangePolicyException Only if {@code rangeFile} is not {@code null}:
* iIf the range file cannot be read for any
* reason, if the requested {@code rangeName}
* cannot be found, or if none of the default
* ranges can be found.
*/
public static IAutoIDGenerator maybeGetIDGenerator(OWLOntology ontology, String rangeFile, String rangeName,
String[] altNames, boolean random) throws IDRangePolicyException {
boolean silent = false;
IAutoIDGenerator generator = null;

if ( rangeFile == null ) {
rangeFile = findIDRangeFile();
if ( rangeFile == null ) {
return null;
}
silent = true;
}

try {
generator = getIDGenerator(ontology, rangeFile, rangeName, altNames, random);
} catch ( IDRangePolicyException e ) {
if ( !silent ) {
throw e;
}
}

return generator;
}
}

0 comments on commit b735ad7

Please sign in to comment.