Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Genesys Backend
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
13
Issues
13
List
Boards
Labels
Service Desk
Milestones
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Genesys PGR
Genesys Backend
Commits
367bf5b7
Commit
367bf5b7
authored
Aug 28, 2014
by
Matija Obreza
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Deserialize JSON filters to internal objects
parent
9c2de3eb
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
814 additions
and
5 deletions
+814
-5
src/main/java/org/genesys2/server/model/filters/NoSuchFilterException.java
.../genesys2/server/model/filters/NoSuchFilterException.java
+9
-0
src/main/java/org/genesys2/server/model/filters/NoSuchFilterValueException.java
...sys2/server/model/filters/NoSuchFilterValueException.java
+19
-0
src/main/java/org/genesys2/server/model/filters/UnsupportedFilterOperation.java
...sys2/server/model/filters/UnsupportedFilterOperation.java
+9
-0
src/main/java/org/genesys2/server/service/impl/FilterHandler.java
.../java/org/genesys2/server/service/impl/FilterHandler.java
+559
-5
src/test/java/org/genesys2/server/model/filters/FiltersTest.java
...t/java/org/genesys2/server/model/filters/FiltersTest.java
+218
-0
No files found.
src/main/java/org/genesys2/server/model/filters/NoSuchFilterException.java
0 → 100644
View file @
367bf5b7
package
org.genesys2.server.model.filters
;
public
class
NoSuchFilterException
extends
Exception
{
public
NoSuchFilterException
(
String
message
)
{
super
(
message
);
}
}
src/main/java/org/genesys2/server/model/filters/NoSuchFilterValueException.java
0 → 100644
View file @
367bf5b7
package
org.genesys2.server.model.filters
;
public
class
NoSuchFilterValueException
extends
Exception
{
private
Object
filterValue
;
public
NoSuchFilterValueException
(
Object
filterValue
)
{
this
.
filterValue
=
filterValue
;
}
public
Object
getFilterValue
()
{
return
filterValue
;
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
" Invalid value: "
+
filterValue
;
}
}
src/main/java/org/genesys2/server/model/filters/UnsupportedFilterOperation.java
0 → 100644
View file @
367bf5b7
package
org.genesys2.server.model.filters
;
public
class
UnsupportedFilterOperation
extends
Exception
{
public
UnsupportedFilterOperation
(
String
message
)
{
super
(
message
);
}
}
src/main/java/org/genesys2/server/service/impl/FilterHandler.java
View file @
367bf5b7
...
...
@@ -19,8 +19,10 @@ package org.genesys2.server.service.impl;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.collections4.Predicate
;
...
...
@@ -35,6 +37,9 @@ import org.genesys2.server.model.filters.GenesysFilter.DataType;
import
org.genesys2.server.model.filters.GenesysFilter.FilterType
;
import
org.genesys2.server.model.filters.I18nListFilter
;
import
org.genesys2.server.model.filters.MethodFilter
;
import
org.genesys2.server.model.filters.NoSuchFilterException
;
import
org.genesys2.server.model.filters.NoSuchFilterValueException
;
import
org.genesys2.server.model.filters.UnsupportedFilterOperation
;
import
org.genesys2.server.model.filters.ValueName
;
import
org.genesys2.server.model.genesys.Method
;
import
org.genesys2.server.model.genesys.TraitCode
;
...
...
@@ -43,7 +48,18 @@ import org.genesys2.server.service.TraitService;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.core.JsonParseException
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.core.JsonToken
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.JsonSerializer
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
com.fasterxml.jackson.databind.annotation.JsonDeserialize
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.fasterxml.jackson.databind.deser.std.StdDeserializer
;
/**
* Converts filter requests (usually JSON) to internal data structures
...
...
@@ -155,24 +171,562 @@ public class FilterHandler {
return
filter
;
}
public
List
<
AppliedFilter
>
fromJSON
(
String
jsonFilter
)
throws
IOException
{
Map
<
String
,
List
<
String
>>
filters
=
objectMapper
.
readValue
(
jsonFilter
,
Map
.
class
);
List
<
AppliedFilter
>
appliedFilters
=
new
ArrayList
<
AppliedFilter
>();
public
List
<
AppliedFilter
>
fromJSON
(
String
jsonFilter
)
throws
IOException
,
NoSuchFilterException
,
UnsupportedFilterOperation
,
NoSuchFilterValueException
{
@SuppressWarnings
(
"unchecked"
)
Map
<
String
,
List
<
Object
>>
filters
=
objectMapper
.
readValue
(
jsonFilter
,
Map
.
class
);
AppliedFilters
appliedFilters
=
new
AppliedFilters
();
for
(
String
key
:
filters
.
keySet
())
{
List
<
String
>
filterValues
=
filters
.
get
(
key
);
List
<
Object
>
filterValues
=
filters
.
get
(
key
);
if
(
filterValues
==
null
||
filterValues
.
isEmpty
())
continue
;
LOG
.
info
(
"key="
+
key
);
AppliedFilter
appliedFilter
=
new
AppliedFilter
();
appliedFilter
.
setFilter
(
getFilterByName
(
key
));
for
(
Object
filterValue
:
filterValues
)
{
appliedFilter
.
addFilterValue
(
toFilterValue
(
filterValue
));
}
}
return
appliedFilters
;
}
private
static
class
AppliedFilter
{
private
FilterValue
toFilterValue
(
Object
filterValue
)
throws
UnsupportedFilterOperation
,
NoSuchFilterValueException
{
if
(
filterValue
==
null
)
return
null
;
if
(
filterValue
instanceof
Map
)
{
return
toFilterOperation
((
Map
<?,
?>)
filterValue
);
}
else
if
(
filterValue
instanceof
Number
||
filterValue
instanceof
String
)
{
return
new
LiteralValueFilter
(
filterValue
);
}
else
{
throw
new
NoSuchFilterValueException
(
filterValue
);
}
}
private
FilterValue
toFilterOperation
(
Map
<?,
?>
filterValue
)
throws
UnsupportedFilterOperation
{
@SuppressWarnings
(
"unchecked"
)
List
<
Number
>
range
=
(
List
<
Number
>)
filterValue
.
get
(
"range"
);
if
(
range
!=
null
)
{
return
new
ValueRangeFilter
(
range
.
get
(
0
),
range
.
get
(
1
));
}
Number
max
=
(
Number
)
filterValue
.
get
(
"max"
);
if
(
max
!=
null
)
{
return
new
MaxValueFilter
(
max
);
}
Number
min
=
(
Number
)
filterValue
.
get
(
"min"
);
if
(
min
!=
null
)
{
return
new
MinValueFilter
(
min
);
}
String
like
=
(
String
)
filterValue
.
get
(
"like"
);
if
(
like
!=
null
)
{
return
new
StartsWithFilter
(
like
);
}
throw
new
UnsupportedFilterOperation
(
filterValue
.
toString
());
}
private
GenesysFilter
getFilterByName
(
String
key
)
throws
NoSuchFilterException
{
for
(
GenesysFilter
filter
:
this
.
availableFilters
)
{
if
(
filter
.
getKey
().
equals
(
key
))
{
return
filter
;
}
}
throw
new
NoSuchFilterException
(
key
);
}
public
static
interface
FilterValue
{
}
@JsonSerialize
(
using
=
AppliedFilters
.
Serializer
.
class
)
@JsonDeserialize
(
using
=
AppliedFilters
.
Deserializer
.
class
)
public
static
class
AppliedFilters
extends
ArrayList
<
AppliedFilter
>
{
public
static
class
Serializer
extends
JsonSerializer
<
AppliedFilters
>
{
@Override
public
void
serialize
(
AppliedFilters
filters
,
JsonGenerator
jgen
,
SerializerProvider
provider
)
throws
IOException
,
JsonProcessingException
{
jgen
.
writeStartObject
();
for
(
AppliedFilter
filter
:
filters
)
{
jgen
.
writeArrayFieldStart
(
filter
.
getFilterName
());
for
(
FilterValue
fv
:
filter
.
getValues
())
jgen
.
writeObject
(
fv
);
if
(
filter
.
withNull
)
jgen
.
writeNull
();
jgen
.
writeEndArray
();
}
jgen
.
writeEndObject
();
}
}
public
static
class
Deserializer
extends
StdDeserializer
<
AppliedFilters
>
{
public
Deserializer
()
{
super
(
AppliedFilters
.
class
);
}
protected
Deserializer
(
Class
<
AppliedFilters
>
vc
)
{
super
(
vc
);
}
@Override
public
AppliedFilters
deserialize
(
JsonParser
jp
,
DeserializationContext
ctxt
)
throws
IOException
,
JsonProcessingException
{
if
(
jp
.
getCurrentToken
()
!=
JsonToken
.
START_OBJECT
)
{
throw
new
IOException
(
"invalid start marker"
);
}
final
AppliedFilters
appliedFilters
=
new
AppliedFilters
();
jp
.
nextToken
();
while
(
jp
.
getCurrentToken
()
==
JsonToken
.
FIELD_NAME
)
{
AppliedFilter
af
=
new
AppliedFilter
();
appliedFilters
.
add
(
af
);
af
.
setFilterName
(
jp
.
getCurrentName
());
jp
.
nextToken
();
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
START_ARRAY
)
{
jp
.
nextToken
();
do
{
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_STRING
)
{
af
.
addFilterValue
(
new
LiteralValueFilter
(
jp
.
getText
()));
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_TRUE
||
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_FALSE
)
{
af
.
addFilterValue
(
new
LiteralValueFilter
(
jp
.
getBooleanValue
()));
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_FLOAT
)
{
af
.
addFilterValue
(
new
LiteralValueFilter
(
jp
.
getDoubleValue
()));
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_INT
)
{
af
.
addFilterValue
(
new
LiteralValueFilter
(
jp
.
getLongValue
()));
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NULL
)
{
af
.
addFilterValue
(
null
);
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
START_OBJECT
)
{
jp
.
nextToken
();
String
op
=
jp
.
getCurrentName
();
if
(
"like"
.
equals
(
op
))
{
af
.
addFilterValue
(
new
StartsWithFilter
(
jp
.
nextTextValue
()));
}
else
if
(
"min"
.
equals
(
op
))
{
Number
number1
=
null
;
jp
.
nextToken
();
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_FLOAT
)
{
number1
=
jp
.
getDoubleValue
();
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_INT
)
{
number1
=
jp
.
getLongValue
();
}
if
(
number1
==
null
)
throw
new
JsonParseException
(
"MinValueFilter expects a single numeric value"
,
jp
.
getCurrentLocation
());
af
.
addFilterValue
(
new
MinValueFilter
(
number1
));
}
else
if
(
"max"
.
equals
(
op
))
{
Number
number1
=
null
;
jp
.
nextToken
();
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_FLOAT
)
{
number1
=
jp
.
getDoubleValue
();
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_INT
)
{
number1
=
jp
.
getLongValue
();
}
if
(
number1
==
null
)
throw
new
JsonParseException
(
"MaxValueFilter expects a single numeric value"
,
jp
.
getCurrentLocation
());
af
.
addFilterValue
(
new
MaxValueFilter
(
number1
));
}
else
if
(
"range"
.
equals
(
op
))
{
if
(
jp
.
nextToken
()
==
JsonToken
.
START_ARRAY
)
{
Number
number1
=
null
,
number2
=
null
;
jp
.
nextToken
();
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_FLOAT
)
{
number1
=
jp
.
getDoubleValue
();
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_INT
)
{
number1
=
jp
.
getLongValue
();
}
jp
.
nextToken
();
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_FLOAT
)
{
number2
=
jp
.
getDoubleValue
();
}
else
if
(
jp
.
getCurrentToken
()
==
JsonToken
.
VALUE_NUMBER_INT
)
{
number2
=
jp
.
getLongValue
();
}
if
(
number1
==
null
||
number2
==
null
||
jp
.
nextToken
()
!=
JsonToken
.
END_ARRAY
)
throw
new
JsonParseException
(
"ValueRangeFilter expects two numeric values in an array"
,
jp
.
getCurrentLocation
());
af
.
addFilterValue
(
new
ValueRangeFilter
(
number1
,
number2
));
}
else
{
throw
new
JsonParseException
(
"ValueRangeFilter expects an array of values"
,
jp
.
getCurrentLocation
());
}
}
if
(
jp
.
nextToken
()
!=
JsonToken
.
END_OBJECT
)
throw
new
JsonParseException
(
"Expecting }, got "
+
jp
.
getCurrentToken
(),
jp
.
getCurrentLocation
());
}
else
{
throw
new
JsonParseException
(
"I don't know where I am."
,
jp
.
getCurrentLocation
());
}
jp
.
nextToken
();
}
while
(
jp
.
getCurrentToken
()
!=
JsonToken
.
END_ARRAY
);
}
else
{
System
.
err
.
println
(
jp
.
getCurrentToken
());
throw
new
JsonParseException
(
"Filter values must be provided in an array"
,
jp
.
getCurrentLocation
());
}
if
(
jp
.
nextToken
()
==
JsonToken
.
END_OBJECT
)
break
;
// System.err.println(jp.getCurrentToken());
}
return
appliedFilters
;
}
}
}
public
static
class
AppliedFilter
{
private
GenesysFilter
filter
;
private
Set
<
FilterValue
>
values
=
new
HashSet
<
FilterValue
>();
private
boolean
withNull
=
false
;
private
String
filterName
;
public
void
setFilter
(
GenesysFilter
filter
)
{
this
.
filter
=
filter
;
}
public
String
getFilterName
()
{
return
this
.
filterName
;
}
public
AppliedFilter
setFilterName
(
String
filterName
)
{
this
.
filterName
=
filterName
;
return
this
;
}
public
AppliedFilter
addFilterValue
(
FilterValue
filterValue
)
{
if
(
filterValue
==
null
)
{
this
.
withNull
=
true
;
}
else
{
values
.
add
(
filterValue
);
}
return
this
;
}
public
GenesysFilter
getFilter
()
{
return
filter
;
}
public
boolean
getWithNull
()
{
return
this
.
withNull
;
}
public
Set
<
FilterValue
>
getValues
()
{
return
values
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
filterName
==
null
)
?
0
:
filterName
.
hashCode
());
result
=
prime
*
result
+
((
values
==
null
)
?
0
:
values
.
hashCode
());
result
=
prime
*
result
+
(
withNull
?
1231
:
1237
);
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
AppliedFilter
other
=
(
AppliedFilter
)
obj
;
if
(
filterName
==
null
)
{
if
(
other
.
filterName
!=
null
)
return
false
;
}
else
if
(!
filterName
.
equals
(
other
.
filterName
))
return
false
;
if
(
values
==
null
)
{
if
(
other
.
values
!=
null
)
return
false
;
}
else
if
(!
values
.
equals
(
other
.
values
))
return
false
;
if
(
withNull
!=
other
.
withNull
)
return
false
;
return
true
;
}
}
@JsonSerialize
(
using
=
LiteralValueFilter
.
Serializer
.
class
)
public
static
class
LiteralValueFilter
implements
FilterValue
{
public
static
class
Serializer
extends
JsonSerializer
<
LiteralValueFilter
>
{
@Override
public
void
serialize
(
LiteralValueFilter
value
,
JsonGenerator
jgen
,
SerializerProvider
provider
)
throws
IOException
,
JsonProcessingException
{
jgen
.
writeObject
(
value
.
getValue
());
}
}
private
Object
value
;
public
LiteralValueFilter
(
Object
value
)
{
this
.
value
=
value
;
}
public
Object
getValue
()
{
return
value
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
value
==
null
)
?
0
:
value
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
LiteralValueFilter
other
=
(
LiteralValueFilter
)
obj
;
if
(
value
==
null
)
{
if
(
other
.
value
!=
null
)
return
false
;
}
else
if
(!
value
.
equals
(
other
.
value
))
return
false
;
return
true
;
}
}
@JsonSerialize
(
using
=
ValueRangeFilter
.
Serializer
.
class
)
public
static
class
ValueRangeFilter
implements
FilterValue
{
public
static
class
Serializer
extends
JsonSerializer
<
ValueRangeFilter
>
{
@Override
public
void
serialize
(
ValueRangeFilter
value
,
JsonGenerator
jgen
,
SerializerProvider
provider
)
throws
IOException
,
JsonProcessingException
{
jgen
.
writeStartObject
();
jgen
.
writeArrayFieldStart
(
"range"
);
jgen
.
writeObject
(
value
.
getFrom
());
jgen
.
writeObject
(
value
.
getTo
());
jgen
.
writeEndArray
();
jgen
.
writeEndObject
();
}
}
private
Number
from
;
private
Number
to
;
public
ValueRangeFilter
(
Number
number1
,
Number
number2
)
{
if
(
number1
==
null
||
number2
==
null
)
throw
new
NullPointerException
(
"ValueRangeFilter requires non-null values for range"
);
if
(
number1
instanceof
Integer
)
number1
=
number1
.
longValue
();
if
(
number1
instanceof
Float
)
number1
=
number1
.
doubleValue
();
if
(
number2
instanceof
Integer
)
number2
=
number2
.
longValue
();
if
(
number2
instanceof
Float
)
number2
=
number2
.
doubleValue
();
this
.
from
=
number1
.
doubleValue
()
<
number2
.
doubleValue
()
?
number1
:
number2
;
this
.
to
=
number1
.
doubleValue
()
<
number2
.
doubleValue
()
?
number2
:
number1
;
}
public
Number
getFrom
()
{
return
from
;
}
public
Number
getTo
()
{
return
to
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
from
==
null
)
?
0
:
from
.
hashCode
());
result
=
prime
*
result
+
((
to
==
null
)
?
0
:
to
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
ValueRangeFilter
other
=
(
ValueRangeFilter
)
obj
;
if
(
from
==
null
)
{
if
(
other
.
from
!=
null
)
return
false
;
}
else
if
(!
from
.
equals
(
other
.
from
))
return
false
;
if
(
to
==
null
)
{
if
(
other
.
to
!=
null
)
return
false
;
}
else
if
(!
to
.
equals
(
other
.
to
))
return
false
;
return
true
;
}
}
@JsonSerialize
(
using
=
MaxValueFilter
.
Serializer
.
class
)
public
static
class
MaxValueFilter
implements
FilterValue
{
public
static
class
Serializer
extends
JsonSerializer
<
MaxValueFilter
>
{
@Override
public
void
serialize
(
MaxValueFilter
value
,
JsonGenerator
jgen
,
SerializerProvider
provider
)
throws
IOException
,
JsonProcessingException
{
jgen
.
writeStartObject
();
jgen
.
writeObjectField
(
"max"
,
value
.
getTo
());
jgen
.
writeEndObject
();
}
}
private
Number
to
;
public
MaxValueFilter
(
Number
max
)
{
if
(
max
instanceof
Integer
)
max
=
max
.
longValue
();
else
if
(
max
instanceof
Float
)
max
=
max
.
doubleValue
();
this
.
to
=
max
;
}
public
Number
getTo
()
{
return
to
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
to
==
null
)
?
0
:
to
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
MaxValueFilter
other
=
(
MaxValueFilter
)
obj
;
if
(
to
==
null
)
{
if
(
other
.
to
!=
null
)
return
false
;
}
else
if
(!
to
.
equals
(
other
.
to
))
return
false
;
return
true
;
}
}
@JsonSerialize
(
using
=
MinValueFilter
.
Serializer
.
class
)
public
static
class
MinValueFilter
implements
FilterValue
{
public
static
class
Serializer
extends
JsonSerializer
<
MinValueFilter
>
{
@Override
public
void
serialize
(
MinValueFilter
value
,
JsonGenerator
jgen
,
SerializerProvider
provider
)
throws
IOException
,
JsonProcessingException
{
jgen
.
writeStartObject
();
jgen
.
writeObjectField
(
"min"
,
value
.
getFrom
());
jgen
.
writeEndObject
();
}
}
private
Number
from
;
public
MinValueFilter
(
Number
min
)
{
if
(
min
instanceof
Integer
)
this
.
from
=
min
.
longValue
();
else
if
(
min
instanceof
Float
)
this
.
from
=
min
.
doubleValue
();
else
this
.
from
=
min
;
}
public
Number
getFrom
()
{
return
from
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
from
==
null
)
?
0
:
from
.
hashCode
());
return
result
;
}