mirror of https://github.com/apache/lucene.git
LUCENE-1621: deprecate MultiTermQuery:getTerm
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@772156 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
aa870e356f
commit
3c434afb8f
|
@ -71,22 +71,35 @@ public final class Term implements Comparable, java.io.Serializable {
|
||||||
return new Term(field,text,false);
|
return new Term(field,text,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compares two terms, returning true iff they have the same
|
//@Override
|
||||||
field and text. */
|
public boolean equals(Object obj) {
|
||||||
public final boolean equals(Object o) {
|
if (this == obj)
|
||||||
if (o == this)
|
|
||||||
return true;
|
return true;
|
||||||
if (o == null)
|
if (obj == null)
|
||||||
return false;
|
return false;
|
||||||
if (!(o instanceof Term))
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
Term other = (Term)o;
|
Term other = (Term) obj;
|
||||||
return field == other.field && text.equals(other.text);
|
if (field == null) {
|
||||||
|
if (other.field != null)
|
||||||
|
return false;
|
||||||
|
} else if (!field.equals(other.field))
|
||||||
|
return false;
|
||||||
|
if (text == null) {
|
||||||
|
if (other.text != null)
|
||||||
|
return false;
|
||||||
|
} else if (!text.equals(other.text))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Combines the hashCode() of the field and the text. */
|
//@Override
|
||||||
public final int hashCode() {
|
public int hashCode() {
|
||||||
return field.hashCode() + text.hashCode();
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((field == null) ? 0 : field.hashCode());
|
||||||
|
result = prime * result + ((text == null) ? 0 : text.hashCode());
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(Object other) {
|
public int compareTo(Object other) {
|
||||||
|
|
|
@ -36,6 +36,8 @@ public class FuzzyQuery extends MultiTermQuery {
|
||||||
private int prefixLength;
|
private int prefixLength;
|
||||||
private boolean termLongEnough = false;
|
private boolean termLongEnough = false;
|
||||||
|
|
||||||
|
protected Term term;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new FuzzyQuery that will match terms with a similarity
|
* Create a new FuzzyQuery that will match terms with a similarity
|
||||||
* of at least <code>minimumSimilarity</code> to <code>term</code>.
|
* of at least <code>minimumSimilarity</code> to <code>term</code>.
|
||||||
|
@ -53,7 +55,8 @@ public class FuzzyQuery extends MultiTermQuery {
|
||||||
* or if prefixLength < 0
|
* or if prefixLength < 0
|
||||||
*/
|
*/
|
||||||
public FuzzyQuery(Term term, float minimumSimilarity, int prefixLength) throws IllegalArgumentException {
|
public FuzzyQuery(Term term, float minimumSimilarity, int prefixLength) throws IllegalArgumentException {
|
||||||
super(term);
|
super(term); // will be removed in 3.0
|
||||||
|
this.term = term;
|
||||||
|
|
||||||
if (minimumSimilarity >= 1.0f)
|
if (minimumSimilarity >= 1.0f)
|
||||||
throw new IllegalArgumentException("minimumSimilarity >= 1");
|
throw new IllegalArgumentException("minimumSimilarity >= 1");
|
||||||
|
@ -105,6 +108,13 @@ public class FuzzyQuery extends MultiTermQuery {
|
||||||
return new FuzzyTermEnum(reader, getTerm(), minimumSimilarity, prefixLength);
|
return new FuzzyTermEnum(reader, getTerm(), minimumSimilarity, prefixLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the pattern term.
|
||||||
|
*/
|
||||||
|
public Term getTerm() {
|
||||||
|
return term;
|
||||||
|
}
|
||||||
|
|
||||||
public void setConstantScoreRewrite(boolean constantScoreRewrite) {
|
public void setConstantScoreRewrite(boolean constantScoreRewrite) {
|
||||||
throw new UnsupportedOperationException("FuzzyQuery cannot rewrite to a constant score query");
|
throw new UnsupportedOperationException("FuzzyQuery cannot rewrite to a constant score query");
|
||||||
}
|
}
|
||||||
|
@ -158,7 +168,6 @@ public class FuzzyQuery extends MultiTermQuery {
|
||||||
|
|
||||||
public String toString(String field) {
|
public String toString(String field) {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
Term term = getTerm();
|
|
||||||
if (!term.field().equals(field)) {
|
if (!term.field().equals(field)) {
|
||||||
buffer.append(term.field());
|
buffer.append(term.field());
|
||||||
buffer.append(":");
|
buffer.append(":");
|
||||||
|
@ -200,23 +209,35 @@ public class FuzzyQuery extends MultiTermQuery {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public int hashCode() {
|
||||||
if (this == o) return true;
|
final int prime = 31;
|
||||||
if (!(o instanceof FuzzyQuery)) return false;
|
int result = 1;
|
||||||
if (!super.equals(o)) return false;
|
result = prime * result + Float.floatToIntBits(minimumSimilarity);
|
||||||
|
result = prime * result + prefixLength;
|
||||||
final FuzzyQuery fuzzyQuery = (FuzzyQuery) o;
|
result = prime * result + ((term == null) ? 0 : term.hashCode());
|
||||||
|
return result;
|
||||||
if (minimumSimilarity != fuzzyQuery.minimumSimilarity) return false;
|
}
|
||||||
if (prefixLength != fuzzyQuery.prefixLength) return false;
|
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
FuzzyQuery other = (FuzzyQuery) obj;
|
||||||
|
if (Float.floatToIntBits(minimumSimilarity) != Float
|
||||||
|
.floatToIntBits(other.minimumSimilarity))
|
||||||
|
return false;
|
||||||
|
if (prefixLength != other.prefixLength)
|
||||||
|
return false;
|
||||||
|
if (term == null) {
|
||||||
|
if (other.term != null)
|
||||||
|
return false;
|
||||||
|
} else if (!term.equals(other.term))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode();
|
|
||||||
result = 29 * result + minimumSimilarity != +0.0f ? Float.floatToIntBits(minimumSimilarity) : 0;
|
|
||||||
result = 29 * result + prefixLength;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.apache.lucene.util.ToStringUtils;
|
||||||
* override equals and hashcode.
|
* override equals and hashcode.
|
||||||
*/
|
*/
|
||||||
public abstract class MultiTermQuery extends Query {
|
public abstract class MultiTermQuery extends Query {
|
||||||
|
/* @deprecated move to sub class */
|
||||||
protected Term term;
|
protected Term term;
|
||||||
protected boolean constantScoreRewrite = false;
|
protected boolean constantScoreRewrite = false;
|
||||||
transient int numberOfTerms = 0;
|
transient int numberOfTerms = 0;
|
||||||
|
@ -55,7 +56,11 @@ public abstract class MultiTermQuery extends Query {
|
||||||
public MultiTermQuery() {
|
public MultiTermQuery() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the pattern term. */
|
/**
|
||||||
|
* Returns the pattern term.
|
||||||
|
* @deprecated check sub class for possible term access - getTerm does not
|
||||||
|
* make sense for all MultiTermQuerys and will be removed.
|
||||||
|
*/
|
||||||
public Term getTerm() {
|
public Term getTerm() {
|
||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +126,11 @@ public abstract class MultiTermQuery extends Query {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prints a user-readable version of this query. */
|
|
||||||
|
/* Prints a user-readable version of this query.
|
||||||
|
* Implemented for back compat in case MultiTermQuery
|
||||||
|
* subclasses do no implement.
|
||||||
|
*/
|
||||||
public String toString(String field) {
|
public String toString(String field) {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
if (term != null) {
|
if (term != null) {
|
||||||
|
@ -145,31 +154,29 @@ public abstract class MultiTermQuery extends Query {
|
||||||
this.constantScoreRewrite = constantScoreRewrite;
|
this.constantScoreRewrite = constantScoreRewrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
//@Override
|
||||||
if (o == null || term == null) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"MultiTermQuerys that do not use a pattern term need to override equals/hashcode");
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (term == null) {
|
final int prime = 31;
|
||||||
throw new UnsupportedOperationException(
|
int result = 1;
|
||||||
"MultiTermQuerys that do not use a pattern term need to override equals/hashcode");
|
result = prime * result + Float.floatToIntBits(getBoost());
|
||||||
|
result = prime * result + (constantScoreRewrite ? 1231 : 1237);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return term.hashCode() + Float.floatToRawIntBits(getBoost());
|
|
||||||
|
//@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
MultiTermQuery other = (MultiTermQuery) obj;
|
||||||
|
if (Float.floatToIntBits(getBoost()) != Float.floatToIntBits(other.getBoost()))
|
||||||
|
return false;
|
||||||
|
if (constantScoreRewrite != other.constantScoreRewrite)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class PrefixQuery extends MultiTermQuery {
|
||||||
|
|
||||||
/** Constructs a query for terms starting with <code>prefix</code>. */
|
/** Constructs a query for terms starting with <code>prefix</code>. */
|
||||||
public PrefixQuery(Term prefix) {
|
public PrefixQuery(Term prefix) {
|
||||||
super(prefix);
|
super(prefix); //will be removed in 3.0
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,14 +38,7 @@ public class PrefixQuery extends MultiTermQuery {
|
||||||
public Term getPrefix() { return prefix; }
|
public Term getPrefix() { return prefix; }
|
||||||
|
|
||||||
protected FilteredTermEnum getEnum(IndexReader reader) throws IOException {
|
protected FilteredTermEnum getEnum(IndexReader reader) throws IOException {
|
||||||
return new PrefixTermEnum(reader, getTerm());
|
return new PrefixTermEnum(reader, prefix);
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o instanceof PrefixQuery)
|
|
||||||
return super.equals(o);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prints a user-readable version of this query. */
|
/** Prints a user-readable version of this query. */
|
||||||
|
@ -60,4 +53,30 @@ public class PrefixQuery extends MultiTermQuery {
|
||||||
buffer.append(ToStringUtils.boost(getBoost()));
|
buffer.append(ToStringUtils.boost(getBoost()));
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (!super.equals(obj))
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
PrefixQuery other = (PrefixQuery) obj;
|
||||||
|
if (prefix == null) {
|
||||||
|
if (other.prefix != null)
|
||||||
|
return false;
|
||||||
|
} else if (!prefix.equals(other.prefix))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.lucene.index.IndexReader;
|
||||||
* the useOldRangeQuery property set to true. The QueryParser default behaviour is to use
|
* the useOldRangeQuery property set to true. The QueryParser default behaviour is to use
|
||||||
* the newer ConstantScore mode. This is generally preferable because:
|
* the newer ConstantScore mode. This is generally preferable because:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>It is faster than the standard RangeQuery mode</li>
|
* <li>In certain situations, it may be faster than the standard RangeQuery mode</li>
|
||||||
* <li>Unlike the RangeQuery mode, it does not cause a BooleanQuery.TooManyClauses exception if the range of values is large</li>
|
* <li>Unlike the RangeQuery mode, it does not cause a BooleanQuery.TooManyClauses exception if the range of values is large</li>
|
||||||
* <li>Unlike the RangeQuery mode, it does not influence scoring based on the scarcity of individual terms that may match</li>
|
* <li>Unlike the RangeQuery mode, it does not influence scoring based on the scarcity of individual terms that may match</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
|
@ -195,40 +195,53 @@ public class RangeQuery extends MultiTermQuery {
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true iff <code>o</code> is equal to this. */
|
//@Override
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (!(o instanceof RangeQuery)) return false;
|
|
||||||
RangeQuery other = (RangeQuery) o;
|
|
||||||
|
|
||||||
if (this.field != other.field // interned comparison
|
|
||||||
|| this.includeLower != other.includeLower
|
|
||||||
|| this.includeUpper != other.includeUpper
|
|
||||||
|| (this.collator != null && ! this.collator.equals(other.collator) || (this.collator == null && other.collator != null))
|
|
||||||
) { return false; }
|
|
||||||
String lowerVal = this.lowerTerm == null ? null : lowerTerm.text();
|
|
||||||
String upperVal = this.upperTerm == null ? null : upperTerm.text();
|
|
||||||
String olowerText = other.lowerTerm == null ? null : other.lowerTerm.text();
|
|
||||||
String oupperText = other.upperTerm == null ? null : other.upperTerm.text();
|
|
||||||
if (lowerVal != null ? !lowerVal.equals(olowerText) : olowerText != null) return false;
|
|
||||||
if (upperVal != null ? !upperVal.equals(oupperText) : oupperText != null) return false;
|
|
||||||
return this.getBoost() == other.getBoost();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a hash code value for this object.*/
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int h = Float.floatToIntBits(getBoost()) ^ field.hashCode();
|
final int prime = 31;
|
||||||
String lowerVal = this.lowerTerm == null ? null : lowerTerm.text();
|
int result = super.hashCode();
|
||||||
String upperVal = this.upperTerm == null ? null : upperTerm.text();
|
result = prime * result + ((collator == null) ? 0 : collator.hashCode());
|
||||||
// hashCode of "" is 0, so don't use that for null...
|
result = prime * result + ((field == null) ? 0 : field.hashCode());
|
||||||
h ^= lowerVal != null ? lowerVal.hashCode() : 0x965a965a;
|
result = prime * result + (includeLower ? 1231 : 1237);
|
||||||
// don't just XOR upperVal with out mixing either it or h, as it will cancel
|
result = prime * result + (includeUpper ? 1231 : 1237);
|
||||||
// out lowerVal if they are equal.
|
result = prime * result + ((lowerTerm == null) ? 0 : lowerTerm.hashCode());
|
||||||
h ^= (h << 17) | (h >>> 16); // a reversible (one to one) 32 bit mapping mix
|
result = prime * result + ((upperTerm == null) ? 0 : upperTerm.hashCode());
|
||||||
h ^= (upperVal != null ? (upperVal.hashCode()) : 0x5a695a69);
|
return result;
|
||||||
h ^= (includeLower ? 0x665599aa : 0)
|
|
||||||
^ (includeUpper ? 0x99aa5566 : 0);
|
|
||||||
h ^= collator != null ? collator.hashCode() : 0;
|
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (!super.equals(obj))
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
RangeQuery other = (RangeQuery) obj;
|
||||||
|
if (collator == null) {
|
||||||
|
if (other.collator != null)
|
||||||
|
return false;
|
||||||
|
} else if (!collator.equals(other.collator))
|
||||||
|
return false;
|
||||||
|
if (field == null) {
|
||||||
|
if (other.field != null)
|
||||||
|
return false;
|
||||||
|
} else if (!field.equals(other.field))
|
||||||
|
return false;
|
||||||
|
if (includeLower != other.includeLower)
|
||||||
|
return false;
|
||||||
|
if (includeUpper != other.includeUpper)
|
||||||
|
return false;
|
||||||
|
if (lowerTerm == null) {
|
||||||
|
if (other.lowerTerm != null)
|
||||||
|
return false;
|
||||||
|
} else if (!lowerTerm.equals(other.lowerTerm))
|
||||||
|
return false;
|
||||||
|
if (upperTerm == null) {
|
||||||
|
if (other.upperTerm != null)
|
||||||
|
return false;
|
||||||
|
} else if (!upperTerm.equals(other.upperTerm))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.lucene.search;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
|
import org.apache.lucene.util.ToStringUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/** Implements the wildcard search query. Supported wildcards are <code>*</code>, which
|
/** Implements the wildcard search query. Supported wildcards are <code>*</code>, which
|
||||||
|
@ -32,9 +34,11 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
public class WildcardQuery extends MultiTermQuery {
|
public class WildcardQuery extends MultiTermQuery {
|
||||||
private boolean termContainsWildcard;
|
private boolean termContainsWildcard;
|
||||||
|
protected Term term;
|
||||||
|
|
||||||
public WildcardQuery(Term term) {
|
public WildcardQuery(Term term) {
|
||||||
super(term);
|
super(term); //will be removed in 3.0
|
||||||
|
this.term = term;
|
||||||
this.termContainsWildcard = (term.text().indexOf('*') != -1) || (term.text().indexOf('?') != -1);
|
this.termContainsWildcard = (term.text().indexOf('*') != -1) || (term.text().indexOf('?') != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,11 +46,11 @@ public class WildcardQuery extends MultiTermQuery {
|
||||||
return new WildcardTermEnum(reader, getTerm());
|
return new WildcardTermEnum(reader, getTerm());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
/**
|
||||||
if (o instanceof WildcardQuery)
|
* Returns the pattern term.
|
||||||
return super.equals(o);
|
*/
|
||||||
|
public Term getTerm() {
|
||||||
return false;
|
return term;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Query rewrite(IndexReader reader) throws IOException {
|
public Query rewrite(IndexReader reader) throws IOException {
|
||||||
|
@ -55,4 +59,42 @@ public class WildcardQuery extends MultiTermQuery {
|
||||||
else
|
else
|
||||||
return super.rewrite(reader);
|
return super.rewrite(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Prints a user-readable version of this query. */
|
||||||
|
public String toString(String field) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
if (!term.field().equals(field)) {
|
||||||
|
buffer.append(term.field());
|
||||||
|
buffer.append(":");
|
||||||
|
}
|
||||||
|
buffer.append(term.text());
|
||||||
|
buffer.append(ToStringUtils.boost(getBoost()));
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((term == null) ? 0 : term.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (!super.equals(obj))
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
WildcardQuery other = (WildcardQuery) obj;
|
||||||
|
if (term == null) {
|
||||||
|
if (other.term != null)
|
||||||
|
return false;
|
||||||
|
} else if (!term.equals(other.term))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue