[
https://issues.apache.org/jira/browse/LUCENE-1188?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Chandan Raj Rupakheti updated LUCENE-1188:
------------------------------------------
Description:
I would like to talk about the implementation of equals and hashCode method in
org.apache.lucene.search.* package.
Example One:
org.apache.lucene.search.spans.SpanTermQuery (Super Class)
<- org.apache.lucene.search.payloads.BoostingTermQuery (Sub Class)
Observation:
* BoostingTermQuery defines equals but inherits hashCode from SpanTermQuery.
Definition of equals is a code clone of SpanTermQuery with a change in class
name.
Intention:
I believe the intention of equals redefinition in BoostingTermQuery is not to
make the objects of SpanTermQuery and BoostingTermQuery comparable. ie.
spanTermQuery.equals(boostingTermQuery) == false &&
boostingTermQuery.equals(spanTermQuery) == false.
Problem:
With current implementation, the intention might not be respected as a result
of symmetric property violation of equals contract i.e.
spanTermQuery.equals(boostingTermQuery) == true (can be) &&
boostingTermQuery.equals(spanTermQuery) == false. (always)
(Note: Provided their state variables are equal)
Solution:
Change implementation of equals in SpanTermQuery from:
{code:title=SpanTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if (!(o instanceof SpanTermQuery))
return false;
SpanTermQuery other = (SpanTermQuery)o;
return (this.getBoost() == other.getBoost())
&& this.term.equals(other.term);
}
{code}
To:
{code:title=SpanTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if(o == this) return true;
if(o == null || o.getClass() != this.getClass()) return false;
// if (!(o instanceof SpanTermQuery))
// return false;
SpanTermQuery other = (SpanTermQuery)o;
return (this.getBoost() == other.getBoost())
&& this.term.equals(other.term);
}
{code}
Advantage:
* BoostingTermQuery.equals and BoostingTermQuery.hashCode is not needed while
still preserving the same intention as before.
* Any further subclassing that does not add new state variables in the extended
classes of SpanTermQuery, does not have to redefine equals and hashCode.
* Even if a new state variable is added in a subclass, the symmetric property
of equals contract will still be respected irrespective of implementation (i.e.
instanceof / getClass) of equals and hashCode in the subclasses.
Example Two:
org.apache.lucene.search.CachingWrapperFilter (Super Class)
<- org.apache.lucene.search.CachingWrapperFilterHelper (Sub Class)
Observation:
Same as Example One.
Problem:
Same as Example one.
Solution:
Change equals in CachingWrapperFilter from:
{code:title=CachingWrapperFilter.java|borderStyle=solid}
public boolean equals(Object o) {
if (!(o instanceof CachingWrapperFilter)) return false;
return this.filter.equals(((CachingWrapperFilter)o).filter);
}
{code}
To:
{code:title=CachingWrapperFilter.java|borderStyle=solid}
public boolean equals(Object o) {
// if (!(o instanceof CachingWrapperFilter)) return false;
if(o == this) return true;
if(o == null || o.getClass() != this.getClass()) return false;
return this.filter.equals(((CachingWrapperFilter)o).filter);
}
{code}
Advantage:
Same as Example One. Here, CachingWrapperFilterHelper.equals and
CachingWrapperFilterHelper.hashCode is not needed.
Example Three:
org.apache.lucene.search.MultiTermQuery (Abstract Parent)
<- org.apache.lucene.search.FuzzyQuery (Concrete Sub)
<- org.apache.lucene.search.WildcardQuery (Concrete Sub)
Observation (Not a problem):
* WildcardQuery defines equals but inherits hashCode from MultiTermQuery.
Definition of equals contains just super.equals invocation.
* FuzzyQuery has few state variables added that are referenced in its equals
and hashCode.
Intention:
I believe the intention here is not to make objects of FuzzyQuery and
WildcardQuery comparable. ie. fuzzyQuery.equals(wildCardQuery) == false &&
wildCardQuery.equals(fuzzyQuery) == false.
Proposed Implementation:
How about changing the implementation of equals in MultiTermQuery from:
{code:title=MultiTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MultiTermQuery)) return false;
final MultiTermQuery multiTermQuery = (MultiTermQuery) o;
if (!term.equals(multiTermQuery.term)) return false;
return getBoost() == multiTermQuery.getBoost();
}
{code}
To:
{code:title=MultiTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if (this == o) return true;
// if (!(o instanceof MultiTermQuery)) return false;
if(o == null || o.getClass() != this.getClass()) return false;
final MultiTermQuery multiTermQuery = (MultiTermQuery) o;
if (!term.equals(multiTermQuery.term)) return false;
return getBoost() == multiTermQuery.getBoost();
}
{code}
Advantage:
Same as above. Here, WildcardQuery.equals is not needed as it does not define
any new state. (FuzzyQuery.equals is still needed because FuzzyQuery defines
new state.)
was:
I would like to talk about the implementation of equals and hashCode method in
org.apache.lucene.search.* package.
Example One:
org.apache.lucene.search.spans.SpanTermQuery (Super Class)
<- org.apache.lucene.search.payloads.BoostingTermQuery (Sub Class)
Observation:
* BoostingTermQuery defines equals but inherits hashCode from SpanTermQuery.
Definition of equals is a code clone of SpanTermQuery with a change in class
name.
Intention:
I believe the intention of equals redefinition in BoostingTermQuery is not to
make the objects of SpanTermQuery and BoostingTermQuery comparable. ie.
spanTermQuery.equals(boostingTermQuery) == false &&
boostingTermQuery.equals(spanTermQuery) == false.
Problem:
With current implementation, the intention might not be respected as a result
of symmetric property violation of equals contract i.e.
spanTermQuery.equals(boostingTermQuery) == true (can be) &&
boostingTermQuery.equals(spanTermQuery) == false. (always)
(Note: Provided their state variables are equal)
Solution:
Change implementation of equals in SpanTermQuery from:
{code:title=SpanTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if (!(o instanceof SpanTermQuery))
return false;
SpanTermQuery other = (SpanTermQuery)o;
return (this.getBoost() == other.getBoost())
&& this.term.equals(other.term);
}
{code}
To:
{code:title=SpanTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if(o == this) return true;
if(o == null || o.getClass() != this.getClass()) return false;
// if (!(o instanceof SpanTermQuery))
// return false;
SpanTermQuery other = (SpanTermQuery)o;
return (this.getBoost() == other.getBoost())
&& this.term.equals(other.term);
}
{code}
Advantage:
* Do not have to redefine equals and hashCode in BoostingTermQuery while
preserving the same intention as before.
* Any further subclassing that does not add new state variables in the extended
classes of SpanTermQuery, does not have to redefine equals and hashCode.
* Even if a new state variable is added in a subclass, the symmetric property
of equals contract will still be respected irrespective of implementation (i.e.
instanceof / getClass) of equals and hashCode in the subclasses.
Example Two:
org.apache.lucene.search.CachingWrapperFilter (Super Class)
<- org.apache.lucene.search.CachingWrapperFilterHelper (Sub Class)
Observation:
Same as Example One.
Problem:
Same as Example one.
Solution:
Change equals in CachingWrapperFilter from:
{code:title=CachingWrapperFilter.java|borderStyle=solid}
public boolean equals(Object o) {
if (!(o instanceof CachingWrapperFilter)) return false;
return this.filter.equals(((CachingWrapperFilter)o).filter);
}
{code}
To:
{code:title=CachingWrapperFilter.java|borderStyle=solid}
public boolean equals(Object o) {
// if (!(o instanceof CachingWrapperFilter)) return false;
if(o == this) return true;
if(o == null || o.getClass() != this.getClass()) return false;
return this.filter.equals(((CachingWrapperFilter)o).filter);
}
{code}
Advantage:
Same as Example One.
Example Three:
org.apache.lucene.search.MultiTermQuery (Abstract Parent)
<- org.apache.lucene.search.FuzzyQuery (Concrete Sub)
<- org.apache.lucene.search.WildcardQuery (Concrete Sub)
Observation (Not a problem):
* WildcardQuery defines equals but inherits hashCode from MultiTermQuery.
Definition of equals contains just super.equals invocation.
* FuzzyQuery has few state variables added that are referenced in its equals
and hashCode.
Intention:
I believe the intention here is not to make objects of FuzzyQuery and
WildcardQuery comparable. ie. fuzzyQuery.equals(wildCardQuery) == false &&
wildCardQuery.equals(fuzzyQuery) == false.
Proposed Implementation:
How about changing the implementation of equals in MultiTermQuery from:
{code:title=MultiTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MultiTermQuery)) return false;
final MultiTermQuery multiTermQuery = (MultiTermQuery) o;
if (!term.equals(multiTermQuery.term)) return false;
return getBoost() == multiTermQuery.getBoost();
}
{code}
To:
{code:title=MultiTermQuery.java|borderStyle=solid}
public boolean equals(Object o) {
if (this == o) return true;
// if (!(o instanceof MultiTermQuery)) return false;
if(o == null || o.getClass() != this.getClass()) return false;
final MultiTermQuery multiTermQuery = (MultiTermQuery) o;
if (!term.equals(multiTermQuery.term)) return false;
return getBoost() == multiTermQuery.getBoost();
}
{code}
Advantage:
Same as above.
Updated the advantage of the proposed solution to make it more clear.
> equals and hashCode implementation in org.apache.lucene.search.* package
> ------------------------------------------------------------------------
>
> Key: LUCENE-1188
> URL: https://issues.apache.org/jira/browse/LUCENE-1188
> Project: Lucene - Java
> Issue Type: Improvement
> Components: Search
> Affects Versions: 2.2, 2.3, 2.3.1
> Environment: All
> Reporter: Chandan Raj Rupakheti
> Fix For: 2.2, 2.3, 2.3.1
>
>
> I would like to talk about the implementation of equals and hashCode method
> in org.apache.lucene.search.* package.
> Example One:
> org.apache.lucene.search.spans.SpanTermQuery (Super Class)
> <- org.apache.lucene.search.payloads.BoostingTermQuery (Sub Class)
> Observation:
> * BoostingTermQuery defines equals but inherits hashCode from SpanTermQuery.
> Definition of equals is a code clone of SpanTermQuery with a change in class
> name.
> Intention:
> I believe the intention of equals redefinition in BoostingTermQuery is not to
> make the objects of SpanTermQuery and BoostingTermQuery comparable. ie.
> spanTermQuery.equals(boostingTermQuery) == false &&
> boostingTermQuery.equals(spanTermQuery) == false.
> Problem:
> With current implementation, the intention might not be respected as a result
> of symmetric property violation of equals contract i.e.
> spanTermQuery.equals(boostingTermQuery) == true (can be) &&
> boostingTermQuery.equals(spanTermQuery) == false. (always)
> (Note: Provided their state variables are equal)
> Solution:
> Change implementation of equals in SpanTermQuery from:
> {code:title=SpanTermQuery.java|borderStyle=solid}
> public boolean equals(Object o) {
> if (!(o instanceof SpanTermQuery))
> return false;
> SpanTermQuery other = (SpanTermQuery)o;
> return (this.getBoost() == other.getBoost())
> && this.term.equals(other.term);
> }
> {code}
> To:
> {code:title=SpanTermQuery.java|borderStyle=solid}
> public boolean equals(Object o) {
> if(o == this) return true;
> if(o == null || o.getClass() != this.getClass()) return false;
> // if (!(o instanceof SpanTermQuery))
> // return false;
> SpanTermQuery other = (SpanTermQuery)o;
> return (this.getBoost() == other.getBoost())
> && this.term.equals(other.term);
> }
> {code}
> Advantage:
> * BoostingTermQuery.equals and BoostingTermQuery.hashCode is not needed while
> still preserving the same intention as before.
>
> * Any further subclassing that does not add new state variables in the
> extended classes of SpanTermQuery, does not have to redefine equals and
> hashCode.
> * Even if a new state variable is added in a subclass, the symmetric property
> of equals contract will still be respected irrespective of implementation
> (i.e. instanceof / getClass) of equals and hashCode in the subclasses.
> Example Two:
> org.apache.lucene.search.CachingWrapperFilter (Super Class)
> <- org.apache.lucene.search.CachingWrapperFilterHelper (Sub Class)
> Observation:
> Same as Example One.
> Problem:
> Same as Example one.
> Solution:
> Change equals in CachingWrapperFilter from:
> {code:title=CachingWrapperFilter.java|borderStyle=solid}
> public boolean equals(Object o) {
> if (!(o instanceof CachingWrapperFilter)) return false;
> return this.filter.equals(((CachingWrapperFilter)o).filter);
> }
> {code}
> To:
> {code:title=CachingWrapperFilter.java|borderStyle=solid}
> public boolean equals(Object o) {
> // if (!(o instanceof CachingWrapperFilter)) return false;
> if(o == this) return true;
> if(o == null || o.getClass() != this.getClass()) return false;
> return this.filter.equals(((CachingWrapperFilter)o).filter);
> }
> {code}
> Advantage:
> Same as Example One. Here, CachingWrapperFilterHelper.equals and
> CachingWrapperFilterHelper.hashCode is not needed.
> Example Three:
> org.apache.lucene.search.MultiTermQuery (Abstract Parent)
> <- org.apache.lucene.search.FuzzyQuery (Concrete Sub)
> <- org.apache.lucene.search.WildcardQuery (Concrete Sub)
> Observation (Not a problem):
> * WildcardQuery defines equals but inherits hashCode from MultiTermQuery.
> Definition of equals contains just super.equals invocation.
> * FuzzyQuery has few state variables added that are referenced in its equals
> and hashCode.
> Intention:
> I believe the intention here is not to make objects of FuzzyQuery and
> WildcardQuery comparable. ie. fuzzyQuery.equals(wildCardQuery) == false &&
> wildCardQuery.equals(fuzzyQuery) == false.
> Proposed Implementation:
> How about changing the implementation of equals in MultiTermQuery from:
> {code:title=MultiTermQuery.java|borderStyle=solid}
> public boolean equals(Object o) {
> if (this == o) return true;
> if (!(o instanceof MultiTermQuery)) return false;
> final MultiTermQuery multiTermQuery = (MultiTermQuery) o;
> if (!term.equals(multiTermQuery.term)) return false;
> return getBoost() == multiTermQuery.getBoost();
> }
> {code}
> To:
> {code:title=MultiTermQuery.java|borderStyle=solid}
> public boolean equals(Object o) {
> if (this == o) return true;
> // if (!(o instanceof MultiTermQuery)) return false;
> if(o == null || o.getClass() != this.getClass()) return false;
> final MultiTermQuery multiTermQuery = (MultiTermQuery) o;
> if (!term.equals(multiTermQuery.term)) return false;
> return getBoost() == multiTermQuery.getBoost();
> }
> {code}
> Advantage:
> Same as above. Here, WildcardQuery.equals is not needed as it does not define
> any new state. (FuzzyQuery.equals is still needed because FuzzyQuery defines
> new state.)
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]