Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Fix JexlMap and GenotypeJEXLContext NullPtrException #668
Conversation
|
@lbergelson , would you mind open discussions on all these? EDIT: |
coveralls
commented
Jul 24, 2016
coveralls
commented
Jul 26, 2016
lbergelson
was assigned
by droazen
Aug 9, 2016
yfarjoun
added the
Review-party candidate
label
Aug 9, 2016
coveralls
commented
Aug 10, 2016
|
Sorry @lbergelson , I accidentally pushed another improvements that I'm working on to this branch. Please ignore the third commit first. |
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| * Compatible with JEXL 1.1 (this code will be easier if we move to 2.0, all of the functionality can go into the | ||
| * JexlContext's get() | ||
| * | ||
| + * TODO: there is some troubling design choices in this class: the laziness and exception behavior: |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| // our context | ||
| private JexlContext jContext = null; | ||
| + // our variant context and/or Genotype |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| private Map<JexlVCMatchExp,Boolean> jexl; | ||
| - | ||
| - public JEXLMap(Collection<JexlVCMatchExp> jexlCollection, VariantContext vc, Genotype g) { | ||
| + // ----------------------------------------------------------------------------------------------- |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| /** | ||
| - * create the internal JexlContext, only when required. This code is where new JEXL context variables | ||
| - * should get added. | ||
| - * | ||
| + * Note: due to laziness, this accessor actually modifies the instance by possibly forcing evaluation of an Jexl expression. | ||
| + * @throws IllegalArgumentException when {@code o} is {@code null} |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| * @return a collection of boolean values, representing the results of all the variants evaluated | ||
| + * | ||
| + * @throws IllegalArgumentException |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| return jexl.values(); | ||
| } | ||
| /** | ||
| - * evaulate a JexlVCMatchExp's expression, given the current context (and setup the context if it's null) | ||
| - * @param exp the JexlVCMatchExp to evaluate | ||
| + * TODO: the number may count invalid entries, is this good? | ||
| + * @return the number of keys, i.e. {@link JexlVCMatchExp}'s hold by this mapping. |
|
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| return jexl.values(); | ||
| } | ||
| /** | ||
| - * evaulate a JexlVCMatchExp's expression, given the current context (and setup the context if it's null) | ||
| - * @param exp the JexlVCMatchExp to evaluate | ||
| + * TODO: the number may count invalid entries, is this good? |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| + return jexl.put(jexlVCMatchExp, aBoolean); | ||
| + } | ||
| + | ||
| + public void putAll(Map<? extends JexlVCMatchExp, ? extends Boolean> map) { | ||
| + jexl.putAll(map); | ||
| + } | ||
| + | ||
| + // ----------------------------------------------------------------------------------------------- | ||
| + // Utilities | ||
| + // ----------------------------------------------------------------------------------------------- | ||
| + | ||
| + /** | ||
| + * Lazily initializes {@link #jexl}, in the sense that all keys in {@code jexlCollection} are associated with {@code null}. | ||
| + * @param jexlCollection | ||
| + */ | ||
| + private void lazyInitialize(Collection<JexlVCMatchExp> jexlCollection) { |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| - if (e.getMessage() != null && e.getMessage().contains("undefined variable")) | ||
| - jexl.put(exp,false); | ||
| - else | ||
| - throw new IllegalArgumentException(String.format("Invalid JEXL expression detected for %s with message %s", exp.name, (e.getMessage() == null ? "no message" : e.getMessage()))); | ||
| + // if exception happens because variable is undefined (i.e. field in expression is not present), evaluate to FALSE | ||
| + throw new IllegalArgumentException(String.format("Invalid JEXL expression detected for %s with message %s", | ||
| + exp.name, | ||
| + /*(e.getMessage() == null ? */"no message" /*: e.getMessage())*/)); | ||
| + } | ||
| + } | ||
| + | ||
| + /** | ||
| + * Create the internal JexlContext, only when required. | ||
| + * This code is where new JEXL context variables should get added. | ||
| + */ | ||
| + private void createContext() { |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| * @param infoMap the map | ||
| * @param attributes the attributes | ||
| */ | ||
| - private static void addAttributesToMap(Map<String, Object> infoMap, Map<String, ?> attributes ) { | ||
| + private static void addAttributesToMap(final Map<String, Object> infoMap, final Map<String, ?> attributes ) { |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| // ////////////////////////////////////////////////////////////////////////////////////// | ||
| + // TODO: is the following comment still true? must resolve in PR review rounds | ||
| + // TODO: is not supported, any other way to resolve at compile time rather than blow up in your face? |
lbergelson
Contributor
|
lbergelson
and 1 other
commented on an outdated diff
Aug 16, 2016
| try { | ||
| final Boolean value = (Boolean) exp.exp.evaluate(jContext); | ||
| // treat errors as no match | ||
| jexl.put(exp, value == null ? false : value); | ||
| - } catch (Exception e) { | ||
| + } catch (final JexlException e) { |
lbergelson
Contributor
|
coveralls
commented
Aug 18, 2016
lbergelson
and 1 other
commented on an outdated diff
Aug 19, 2016
| // if exception happens because variable is undefined (i.e. field in expression is not present), evaluate to FALSE | ||
| - // todo - might be safer if we explicitly checked for an exception type, but Apache's API doesn't seem to have that ability | ||
| - if (e.getMessage() != null && e.getMessage().contains("undefined variable")) | ||
| - jexl.put(exp,false); | ||
| - else | ||
| - throw new IllegalArgumentException(String.format("Invalid JEXL expression detected for %s with message %s", exp.name, (e.getMessage() == null ? "no message" : e.getMessage()))); | ||
| + jexl.put(exp,false); | ||
| + } catch (final JexlException e) { | ||
| + // todo - might be better if no exception is caught here but let's user decide how to deal with them; note this will propagate to get() and values() | ||
| + throw new IllegalArgumentException(String.format("Invalid JEXL expression detected for %s with message %s", |
lbergelson
Contributor
|
SHuang-Broad
added some commits
Jul 15, 2016
SHuang-Broad
changed the title from
NO merge yet: Fix JexlMap and GenotypeJEXLContext NullPtrException to Fix JexlMap and GenotypeJEXLContext NullPtrException
Aug 22, 2016
yfarjoun
and 1 other
commented on an outdated diff
Aug 23, 2016
| */ | ||
| - private static void addAttributesToMap(Map<String, Object> infoMap, Map<String, ?> attributes ) { | ||
| - for (Entry<String, ?> e : attributes.entrySet()) { | ||
| - infoMap.put(e.getKey(), String.valueOf(e.getValue())); | ||
| + private void createContext() { | ||
| + if ( vc == null ) { | ||
| + jContext = new MapContext(Collections.emptyMap()); | ||
| + } |
|
|
yfarjoun
and 1 other
commented on an outdated diff
Aug 23, 2016
yfarjoun
and 1 other
commented on an outdated diff
Aug 23, 2016
| */ | ||
| - private void createContext() { | ||
| - if ( vc == null ) { | ||
| - jContext = new MapContext(Collections.emptyMap()); | ||
| - } | ||
| - else if (g == null) { | ||
| - jContext = new VariantJEXLContext(vc); | ||
| - } | ||
| - else { | ||
| - jContext = new GenotypeJEXLContext(vc, g); | ||
| + public Boolean get(Object o) { | ||
| + if(o == null){ |
|
|
|
@SHuang-Broad Can you add a unit test that used to fail with nullptr? |
yfarjoun
and 1 other
commented on an outdated diff
Aug 23, 2016
yfarjoun
and 1 other
commented on an outdated diff
Aug 23, 2016
|
@lbergelson , yes, will add a test. |
coveralls
commented
Aug 23, 2016
|
There you go, @lbergelson , the unit test were cleaned up a little and more tests are added. |
coveralls
commented
Aug 27, 2016
|
Friendly poke on @lbergelson, is the unit test covering what's needed? |
coveralls
commented
Sep 8, 2016
|
@SHuang-Broad This looks good. Sorry for slowness. |
lbergelson
merged commit 21d8865
into
samtools:master
Sep 13, 2016
SHuang-Broad
deleted the
SHuang-Broad:sh_fix_GenotypeJEXLContext_nullptr branch
Sep 13, 2016
|
Thank you very much! @lbergelson |
SHuang-Broad commentedJul 24, 2016
Description
GenotypeJEXLContext.get()currently potentially throwsNullPointerException, triggered by a design choice inGenotype.getFilters(), which explicitly returnsnull(genotype considered to be filter passing in such case according to documentation). This fix temporarily fixes that exception (1st commit, by Louis).Class
CommonInfo, which holds "Common utility routines for VariantContext and Genotype", contains such a constantVariantContextuses this constant in its owngetFilters()(it has a separate methodgetFiltersMaybeNull()), butGenotypedoesn't use such constant. A choice has to be made to whether makeGenotyperesembleVariantContext's behavior (a backward non-compatible change) or keep things as they are.Some code re-organizing and whole bunch of todo's in
JEXLMap, which must be resolved in the review rounds.Checklist