Skip to content

Commit 2f66361

Browse files
committed
improved Filter to support exclusive/inclusive modes
improved (cached) values in OIDataListHelpers improved filtering tests
1 parent 908c574 commit 2f66361

25 files changed

Lines changed: 1471 additions & 774 deletions

src/main/java/fr/jmmc/oitools/OIFitsCommand.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package fr.jmmc.oitools;
1818

19+
import java.util.ArrayList;
20+
import java.util.List;
1921
import java.util.Locale;
2022
import java.util.TimeZone;
2123
import java.util.logging.Level;
@@ -135,4 +137,33 @@ static String getOptionArgValue(final String[] args, final String opt) {
135137
return null;
136138
}
137139

140+
/**
141+
* Get all values of an option in given args.
142+
* @param args
143+
* @param opt
144+
* @return all values of the option in args if found, null otherwise.
145+
*/
146+
static List<String> getOptionArgValues(final String[] args, final String opt) {
147+
List<String> values = null;
148+
149+
for (int i = 0; i < args.length; i++) {
150+
int pos = -1;
151+
for (; i < args.length; i++) {
152+
if (args[i].equals(opt)) {
153+
pos = i;
154+
break;
155+
}
156+
}
157+
if ((pos != -1) && (pos + 1) < args.length) {
158+
// add value:
159+
if (values == null) {
160+
values = new ArrayList<>();
161+
}
162+
values.add(args[pos + 1]);
163+
i++; // skip
164+
}
165+
}
166+
return values;
167+
}
168+
138169
}

src/main/java/fr/jmmc/oitools/OIFitsProcessor.java

Lines changed: 126 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import fr.jmmc.oitools.model.range.Range;
2828
import fr.jmmc.oitools.processing.Merger;
2929
import fr.jmmc.oitools.processing.Selector;
30+
import fr.jmmc.oitools.processing.Selector.FilterValues;
3031
import fr.nom.tam.fits.FitsException;
3132
import java.io.IOException;
3233
import java.util.ArrayList;
@@ -67,6 +68,8 @@ public class OIFitsProcessor extends OIFitsCommand {
6768
private static final String OPTION_STACONF = appendColumnArg(Selector.FILTER_STACONF);
6869
private static final String OPTION_EFFWAVE = appendColumnArg(Selector.FILTER_EFFWAVE);
6970
private static final String OPTION_EFFBAND = appendColumnArg(Selector.FILTER_EFFBAND);
71+
/* prefix for filter values indicating EXCLUDE ('not:') */
72+
private static final String OPTION_PREFIX_EXCLUDE = "not:";
7073

7174
/**
7275
* Main entry point.
@@ -80,7 +83,7 @@ public static void main(final String[] args) {
8083
return;
8184
}
8285

83-
final boolean quiet = !hasOptionArg(args, "-l", "-log") && !hasOptionArg(args, "-v", "-verbose");;
86+
final boolean quiet = !hasOptionArg(args, "-l", "-log") && !hasOptionArg(args, "-v", "-verbose");
8487
bootstrap(quiet);
8588

8689
final String command = args[0];
@@ -234,64 +237,37 @@ private static void merge(final String[] args) throws FitsException, IOException
234237

235238
if (hasOptionArg(args, OPTION_TARGET)) {
236239
selector.setTargetUID(getOptionArgValue(args, OPTION_TARGET));
237-
} else {
238-
if (hasOptionArg(args, OPTION_TARGET_ID)) {
239-
selector.setTargetUID(getOptionArgValue(args, OPTION_TARGET_ID));
240-
}
240+
} else if (hasOptionArg(args, OPTION_TARGET_ID)) {
241+
selector.setTargetUID(getOptionArgValue(args, OPTION_TARGET_ID));
241242
}
242243
if (hasOptionArg(args, OPTION_INSNAME)) {
243244
selector.setInsModeUID(getOptionArgValue(args, OPTION_INSNAME));
244245
}
245246
if (hasOptionArg(args, OPTION_NIGHT)) {
246247
selector.setNightID(Integer.valueOf(getOptionArgValue(args, OPTION_NIGHT)));
247-
} else {
248-
if (hasOptionArg(args, OPTION_NIGHT_ID)) {
249-
selector.setNightID(Integer.valueOf(getOptionArgValue(args, OPTION_NIGHT_ID)));
250-
}
251-
}
252-
if (hasOptionArg(args, OPTION_MJD_RANGES)) {
253-
addFilter(selector, Selector.FILTER_MJD, parseRanges(getOptionArgValue(args, OPTION_MJD_RANGES)));
254-
} else {
255-
if (hasOptionArg(args, OPTION_MJD)) {
256-
addFilter(selector, Selector.FILTER_MJD, parseRanges(getOptionArgValue(args, OPTION_MJD)));
257-
}
248+
} else if (hasOptionArg(args, OPTION_NIGHT_ID)) {
249+
selector.setNightID(Integer.valueOf(getOptionArgValue(args, OPTION_NIGHT_ID)));
258250
}
259-
if (hasOptionArg(args, OPTION_BASELINES)) {
260-
addFilter(selector, Selector.FILTER_STAINDEX, parseStrings(getOptionArgValue(args, OPTION_BASELINES)));
261-
} else {
262-
if (hasOptionArg(args, OPTION_STAINDEX)) {
263-
addFilter(selector, Selector.FILTER_STAINDEX, parseStrings(getOptionArgValue(args, OPTION_STAINDEX)));
264-
}
265-
}
266-
{
267-
if (hasOptionArg(args, OPTION_STACONF)) {
268-
addFilter(selector, Selector.FILTER_STACONF, parseStrings(getOptionArgValue(args, OPTION_STACONF)));
269-
}
251+
252+
if (!addRangeFilter(selector, Selector.FILTER_MJD, args, OPTION_MJD_RANGES)) {
253+
addRangeFilter(selector, Selector.FILTER_MJD, args, OPTION_MJD);
270254
}
271-
if (hasOptionArg(args, OPTION_WL_RANGES)) {
272-
addFilter(selector, Selector.FILTER_EFFWAVE, parseRanges(getOptionArgValue(args, OPTION_WL_RANGES)));
273-
} else {
274-
if (hasOptionArg(args, OPTION_EFFWAVE)) {
275-
addFilter(selector, Selector.FILTER_EFFWAVE, parseRanges(getOptionArgValue(args, OPTION_EFFWAVE)));
276-
}
255+
if (!addStringFilter(selector, Selector.FILTER_STAINDEX, args, OPTION_BASELINES)) {
256+
addStringFilter(selector, Selector.FILTER_STAINDEX, args, OPTION_STAINDEX);
277257
}
278-
{
279-
if (hasOptionArg(args, OPTION_EFFBAND)) {
280-
addFilter(selector, Selector.FILTER_EFFBAND, parseRanges(getOptionArgValue(args, OPTION_EFFBAND)));
281-
}
258+
addStringFilter(selector, Selector.FILTER_STACONF, args, OPTION_STACONF);
259+
260+
if (!addRangeFilter(selector, Selector.FILTER_EFFWAVE, args, OPTION_WL_RANGES)) {
261+
addRangeFilter(selector, Selector.FILTER_EFFWAVE, args, OPTION_EFFWAVE);
282262
}
263+
addRangeFilter(selector, Selector.FILTER_EFFBAND, args, OPTION_EFFBAND);
283264

284265
// collect extra arguments from OIFITS2 data model:
285-
for (String colName : DataModel.getInstance().getNumericalColumnNames()) {
286-
if (!Selector.isCustomFilter(colName)) {
287-
288-
final String arg = appendColumnArg(colName);
289-
if (hasOptionArg(args, arg)) {
290-
addFilter(selector, colName, parseRanges(getOptionArgValue(args, arg)));
291-
}
266+
for (String columnName : DataModel.getInstance().getNumericalColumnNames()) {
267+
if (!Selector.isCustomFilter(columnName)) {
268+
addRangeFilter(selector, columnName, args);
292269
}
293270
}
294-
295271
if (!selector.isEmpty()) {
296272
info("Filters: " + selector);
297273
}
@@ -450,23 +426,15 @@ protected static void showArgumentsHelp() {
450426
info("--------------------------------------------------------------------------------------");
451427
}
452428

453-
public static List<String> parseStrings(final String input) {
454-
if (input == null) {
455-
return null;
456-
}
457-
final String[] values = input.split(",");
458-
459-
final List<String> baselineList = new ArrayList<String>(values.length);
460-
for (String value : values) {
461-
baselineList.add(value.trim());
462-
}
463-
if (baselineList.isEmpty()) {
464-
return null;
429+
private static void parseStrings(final List<String> values, final String input) {
430+
if (input != null) {
431+
for (String value : input.split(",")) {
432+
values.add(value.trim());
433+
}
465434
}
466-
return baselineList;
467435
}
468436

469-
public static StringBuilder dumpStrings(final List<String> values, final StringBuilder sb) {
437+
private static StringBuilder dumpStrings(final List<String> values, final StringBuilder sb) {
470438
if (values == null || values.isEmpty()) {
471439
return sb;
472440
}
@@ -477,34 +445,28 @@ public static StringBuilder dumpStrings(final List<String> values, final StringB
477445
return sb;
478446
}
479447

480-
public static List<Range> parseRanges(final String input) {
481-
if (input == null) {
482-
return null;
483-
}
484-
final String[] values = input.split(",");
448+
private static void parseRanges(final List<Range> ranges, final String input) {
449+
if (input != null) {
450+
final String[] values = input.split(",");
485451

486-
if ((values.length % 2) == 1) {
487-
throw new IllegalStateException("Invalid ranges (" + values.length + " items): " + input);
488-
}
489-
final List<Range> ranges = new ArrayList<Range>(values.length);
452+
if ((values.length % 2) == 1) {
453+
throw new IllegalStateException("Invalid ranges (" + values.length + " items): " + input);
454+
}
490455

491-
for (int i = 0; i < values.length; i += 2) {
492-
final double min = Double.valueOf(values[i]);
493-
final double max = Double.valueOf(values[i + 1]);
456+
for (int i = 0; i < values.length; i += 2) {
457+
final double min = Double.parseDouble(values[i]);
458+
final double max = Double.parseDouble(values[i + 1]);
494459

495-
if (min > max) {
496-
throw new IllegalStateException("Invalid range [" + min + "," + max + "]");
497-
}
460+
if (min > max) {
461+
throw new IllegalStateException("Invalid range [" + min + "," + max + "]");
462+
}
498463

499-
ranges.add(new Range(min, max));
500-
}
501-
if (ranges.isEmpty()) {
502-
return null;
464+
ranges.add(new Range(min, max));
465+
}
503466
}
504-
return ranges;
505467
}
506468

507-
public static StringBuilder dumpRanges(final List<Range> values, final StringBuilder sb) {
469+
private static StringBuilder dumpRanges(final List<Range> values, final StringBuilder sb) {
508470
if (values == null || values.isEmpty()) {
509471
return sb;
510472
}
@@ -532,40 +494,60 @@ public static String generateCLIargs(final Selector selector) {
532494
/* no way to define selector.tables via CLI */
533495

534496
if (selector.hasFilter(Selector.FILTER_MJD)) {
535-
appendColumnArg(sb, Selector.FILTER_MJD).append(" ");
536-
dumpRanges(selector.getFilter(Selector.FILTER_MJD), sb).append(" ");
497+
dumpRangeFilter(sb, selector.getFilterValues(Selector.FILTER_MJD));
537498
}
538499

539500
if (selector.hasFilter(Selector.FILTER_STAINDEX)) {
540-
appendColumnArg(sb, Selector.FILTER_STAINDEX).append(" ");
541-
dumpStrings(selector.getFilter(Selector.FILTER_STAINDEX), sb).append(" ");
501+
dumpStringFilter(sb, selector.getFilterValues(Selector.FILTER_STAINDEX));
542502
}
543503
if (selector.hasFilter(Selector.FILTER_STACONF)) {
544-
appendColumnArg(sb, Selector.FILTER_STACONF).append(" ");
545-
dumpStrings(selector.getFilter(Selector.FILTER_STACONF), sb).append(" ");
504+
dumpStringFilter(sb, selector.getFilterValues(Selector.FILTER_STACONF));
546505
}
547506

548507
if (selector.hasFilter(Selector.FILTER_EFFWAVE)) {
549-
appendColumnArg(sb, Selector.FILTER_EFFWAVE).append(" ");
550-
dumpRanges(selector.getFilter(Selector.FILTER_EFFWAVE), sb).append(" ");
508+
dumpRangeFilter(sb, selector.getFilterValues(Selector.FILTER_EFFWAVE));
551509
}
552510
if (selector.hasFilter(Selector.FILTER_EFFBAND)) {
553-
appendColumnArg(sb, Selector.FILTER_EFFBAND).append(" ");
554-
dumpRanges(selector.getFilter(Selector.FILTER_EFFBAND), sb).append(" ");
511+
dumpRangeFilter(sb, selector.getFilterValues(Selector.FILTER_EFFBAND));
555512
}
556513

557514
// convert generic filters from selector.filters:
558-
for (Map.Entry<String, List<?>> e : selector.getFiltersMap().entrySet()) {
515+
for (Map.Entry<String, FilterValues<?>> e : selector.getFiltersMap().entrySet()) {
559516
if (!Selector.isCustomFilter(e.getKey())) {
560-
appendColumnArg(sb, e.getKey()).append(" ");
561-
dumpRanges((List<Range>) e.getValue(), sb).append(" ");
517+
dumpRangeFilter(sb, e.getValue());
562518
}
563519
}
564520
return sb.toString();
565521
}
566522
return "";
567523
}
568524

525+
private static void dumpStringFilter(final StringBuilder sb, final FilterValues filterValues) {
526+
if (filterValues != null) {
527+
if (filterValues.getIncludeValues() != null) {
528+
appendColumnArg(sb, filterValues.getColumnName()).append(" ");
529+
dumpStrings(filterValues.getIncludeValues(), sb).append(" ");
530+
}
531+
if (filterValues.getExcludeValues() != null) {
532+
appendColumnArg(sb, filterValues.getColumnName()).append(" ").append(OPTION_PREFIX_EXCLUDE);
533+
dumpStrings(filterValues.getExcludeValues(), sb).append(" ");
534+
}
535+
}
536+
}
537+
538+
private static void dumpRangeFilter(final StringBuilder sb, final FilterValues filterValues) {
539+
if (filterValues != null) {
540+
if (filterValues.getIncludeValues() != null) {
541+
appendColumnArg(sb, filterValues.getColumnName()).append(" ");
542+
dumpRanges(filterValues.getIncludeValues(), sb).append(" ");
543+
}
544+
if (filterValues.getExcludeValues() != null) {
545+
appendColumnArg(sb, filterValues.getColumnName()).append(" ").append(OPTION_PREFIX_EXCLUDE);
546+
dumpRanges(filterValues.getExcludeValues(), sb).append(" ");
547+
}
548+
}
549+
}
550+
569551
private static String appendColumnArg(final String colName) {
570552
sbTmp.setLength(0);
571553
return appendColumnArg(sbTmp, colName).toString();
@@ -576,9 +558,57 @@ private static StringBuilder appendColumnArg(final StringBuilder sb, final Strin
576558
return sb; // fluent API
577559
}
578560

579-
private static void addFilter(final Selector selector, final String colName, final List<?> values) {
580-
if (values != null) {
581-
selector.addFilter(colName, values);
561+
private static boolean addRangeFilter(final Selector selector, final String columnName,
562+
final String[] args) {
563+
return addRangeFilter(selector, columnName, args, appendColumnArg(columnName));
564+
}
565+
566+
private static boolean addRangeFilter(final Selector selector, final String columnName,
567+
final String[] args, final String optionArg) {
568+
if (hasOptionArg(args, optionArg)) {
569+
final List<String> argValues = getOptionArgValues(args, optionArg);
570+
if (argValues != null) {
571+
FilterValues<Range> filterValues = null;
572+
573+
for (String arg : argValues) {
574+
if ((arg != null) && !arg.isEmpty()) {
575+
if (filterValues == null) {
576+
filterValues = new FilterValues<Range>(columnName);
577+
}
578+
if (arg.startsWith(OPTION_PREFIX_EXCLUDE)) {
579+
parseRanges(filterValues.getOrCreateExcludeValues(), arg.substring(OPTION_PREFIX_EXCLUDE.length()));
580+
} else {
581+
parseRanges(filterValues.getOrCreateIncludeValues(), arg);
582+
}
583+
}
584+
}
585+
return selector.addFilter(columnName, filterValues);
586+
}
582587
}
588+
return false;
583589
}
590+
591+
private static boolean addStringFilter(final Selector selector, final String columnName,
592+
final String[] args, final String optionArg) {
593+
if (hasOptionArg(args, optionArg)) {
594+
final List<String> argValues = getOptionArgValues(args, optionArg);
595+
FilterValues<String> filterValues = null;
596+
597+
for (String arg : argValues) {
598+
if ((arg != null) && !arg.isEmpty()) {
599+
if (filterValues == null) {
600+
filterValues = new FilterValues<String>(columnName);
601+
}
602+
if (arg.startsWith(OPTION_PREFIX_EXCLUDE)) {
603+
parseStrings(filterValues.getOrCreateExcludeValues(), arg.substring(OPTION_PREFIX_EXCLUDE.length()));
604+
} else {
605+
parseStrings(filterValues.getOrCreateIncludeValues(), arg);
606+
}
607+
}
608+
}
609+
return selector.addFilter(columnName, filterValues);
610+
}
611+
return false;
612+
}
613+
584614
}

src/main/java/fr/jmmc/oitools/meta/ColumnMeta.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ public final String getErrorColumnName() {
235235
}
236236

237237
/**
238-
* @return optional column name storing error values (may be null)
238+
* @return optional column name storing data values (may be null)
239239
*/
240240
public String getDataColumnName() {
241241
return dataName;

0 commit comments

Comments
 (0)