Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Ryan Berkheimer
messageapi
Commits
42222960
Commit
42222960
authored
Sep 21, 2020
by
Ryan Berkheimer
Browse files
added doc comments and added final modifiers where possible in request and schema utils classes
parent
10d2f671
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
dist/artifacts/c/messageapi_1_0_0/messageapi.tar
View file @
42222960
No preview for this file type
dist/artifacts/java/messageapi_1_0_0/messageapi.tar
View file @
42222960
No preview for this file type
dist/docs/api/messageapi_docs.tar
View file @
42222960
No preview for this file type
resources/test/file-reader/parameters.json
View file @
42222960
...
...
@@ -5,6 +5,7 @@
"conditions"
:
[{
"id"
:
"is-relative-path"
,
"type"
:
"comparison"
,
"operator"
:
"contains"
,
"factory"
:
"dummy"
,
"field"
:
"file-path"
,
"value"
:
"{}"
}],
"collections"
:
[{
"id"
:
"coll-1"
,
...
...
src/groovy/test/endtoend/FileReaderTests.groovy
View file @
42222960
...
...
@@ -3,18 +3,19 @@
* @author Ryan Berkheimer
*/
import
gov.noaa.messageapi.interfaces.ISession
;
import
gov.noaa.messageapi.interfaces.IRequest
;
import
gov.noaa.messageapi.interfaces.IResponse
;
import
gov.noaa.messageapi.interfaces.IRejection
;
import
gov.noaa.messageapi.interfaces.IRecord
;
import
gov.noaa.messageapi.interfaces.IField
;
import
gov.noaa.messageapi.interfaces.ISession
import
gov.noaa.messageapi.interfaces.IRequest
import
gov.noaa.messageapi.interfaces.IResponse
import
gov.noaa.messageapi.interfaces.IRecord
import
gov.noaa.messageapi.sessions.DefaultSession
;
import
gov.noaa.messageapi.sessions.DefaultSession
/**
This Spock test class demonstrates end to end behaviors for reading and validating reads of files.
It should hold file reader transformation and file reader endpoint, and things like that.
*/
class
FileReaderTests
extends
spock
.
lang
.
Specification
{
/*def "Tests submission of a full file reader task with 1 small input."() {
given: "A standard condition test request"
ISession session = new DefaultSession("{}/resources/test/file-reader/manifest.json")
...
...
@@ -27,19 +28,18 @@ class FileReaderTests extends spock.lang.Specification {
then: "We should have no rejections and there should be 7 records in the return set."
response.getRejections().size() == 0
response.getRecords().size() == 7
}*/
}*/
def
"Tests submission of a full file reader task with 1 large input."
()
{
given:
"
A standard condition test request
"
ISession
session
=
new
DefaultSession
(
"
{}/resources/test/file-reader/manifest.json
"
)
IRequest
request
=
session
.
createRequest
()
;
IRecord
record
=
request
.
createRecord
()
;
record
.
setField
(
"
file-path
"
,
"
{}/resources/test/inputs/file-reader/proc_sm_gtsnp_data_ftp_CF6_cf6_20190506.txt
"
);
when:
"
We submit the test session and wait for completion
"
IResponse
response
=
request
.
submit
()
;
given:
'
A standard condition test request
'
ISession
session
=
new
DefaultSession
(
'
{}/resources/test/file-reader/manifest.json
'
)
IRequest
request
=
session
.
createRequest
()
IRecord
record
=
request
.
createRecord
()
record
.
setField
(
'
file-path
'
,
'
{}/resources/test/inputs/file-reader/proc_sm_gtsnp_data_ftp_CF6_cf6_20190506.txt
'
)
when:
'
We submit the test session and wait for completion
'
IResponse
response
=
request
.
submit
()
while
(!
response
.
isComplete
())
{}
then:
"We should have no rejections and there should be 79794 records in the return set."
//println "FIELD VALUE!!!"
then:
'We should have no rejections and there should be 79794 records in the return set.'
//println response.getRecords().get(0).getField("value").getValue()
response
.
getRejections
().
size
()
==
0
response
.
getRecords
().
size
()
==
79794
...
...
src/java/main/gov/noaa/messageapi/definitions/SchemaDefinition.java
View file @
42222960
...
...
@@ -12,7 +12,7 @@ import gov.noaa.messageapi.parsers.schemas.ConditionParser;
import
gov.noaa.messageapi.parsers.schemas.ConditionOperatorParser
;
/**
* A SchemaDefinition is used
by the StorageService
to parse a specified
* A SchemaDefinition is used to parse a specified
* configuration and create a blueprint for how the user interacts with
* a session. SchemaDefinitions hold raw and/or simple datatypes to be turned
* held, referenced, and converted to more complex types over the course of
...
...
@@ -46,7 +46,7 @@ public class SchemaDefinition {
* @throws Exception An exception is thrown if there is an issue parsing the schema definition.
*/
@SuppressWarnings
(
"unchecked"
)
public
SchemaDefinition
(
Map
<
String
,
Object
>
properties
)
throws
Exception
{
public
SchemaDefinition
(
final
Map
<
String
,
Object
>
properties
)
throws
Exception
{
if
(
properties
.
containsKey
(
"metadata"
))
{
this
.
parseMetadataSpec
((
String
)
properties
.
get
(
"metadata"
));
}
else
{
...
...
@@ -58,82 +58,92 @@ public class SchemaDefinition {
throw
new
Exception
(
"Missing necessary 'fields' key when parsing schema definition."
);
}
if
(
properties
.
containsKey
(
"conditions"
))
{
this
.
parseConditionSpec
((
Map
<
String
,
String
>)
properties
.
get
(
"conditions"
));
this
.
parseConditionSpec
((
Map
<
String
,
String
>)
properties
.
get
(
"conditions"
));
}
else
{
this
.
setEmptyConditions
();
}
}
/**
* Copy constructor for SchemaDefinition. In the context of the Storage
*
Service,
this constructor is used to maintain copies of the schema
*
definition
per-request. This ensures no issues will be caused in the
*
case that the
definition is ever modified by another action during
*
a specific request. The
definition of a schema SHOULD be immutable,
*
however the configurability of
the service makes this impossible to
*
guarantee.
* @param definition The original schema definition for the service when
*
the
request was submitted.
* Copy constructor for SchemaDefinition. In the context of the Storage
Service,
* this constructor is used to maintain copies of the schema
definition
* per-request. This ensures no issues will be caused in the
case that the
* definition is ever modified by another action during
a specific request. The
* definition of a schema SHOULD be immutable,
however the configurability of
* the service makes this impossible to
guarantee.
*
* @param definition The original schema definition for the service when
the
*
request was submitted.
*/
public
SchemaDefinition
(
SchemaDefinition
definition
)
{
this
.
metadataMap
=
new
HashMap
<
String
,
Object
>(
definition
.
getMetadataMap
());
this
.
fieldMaps
=
new
ArrayList
<
Map
<
String
,
Object
>>(
definition
.
getFieldMaps
());
this
.
conditionMaps
=
new
ArrayList
<
Map
<
String
,
Object
>>(
definition
.
getConditionMaps
());
public
SchemaDefinition
(
final
SchemaDefinition
definition
)
{
this
.
metadataMap
=
new
HashMap
<
String
,
Object
>(
definition
.
getMetadataMap
());
this
.
fieldMaps
=
new
ArrayList
<
Map
<
String
,
Object
>>(
definition
.
getFieldMaps
());
this
.
conditionMaps
=
new
ArrayList
<
Map
<
String
,
Object
>>(
definition
.
getConditionMaps
());
this
.
conditionOperatorFactory
=
definition
.
getOperatorFactory
().
getCopy
();
}
/**
* This method constructs the operator factory used by certain request
* comparisons. This class is bootstrapped at runtime to provide the
* user with an ability to either extend a basic set of comparisons, or
* specify complex or customized comparison types (on object values).
* @param operatorClass A class that defines operators used in condition-field comparisons
* @throws Exception Throws an exception if there is an error loading the operator class.
* comparisons. This class is bootstrapped at runtime to provide the user with
* an ability to either extend a basic set of comparisons, or specify complex or
* customized comparison types (on object values).
*
* @param operatorClass A class that defines operators used in condition-field
* comparisons
* @throws Exception Throws an exception if there is an error loading the
* operator class.
*/
private
void
createOperatorFactory
(
String
operatorClass
)
throws
Exception
{
private
void
createOperatorFactory
(
final
String
operatorClass
)
throws
Exception
{
this
.
conditionOperatorFactory
=
ConditionOperatorParser
.
build
(
operatorClass
);
}
/**
* Parses a metadata map from a location specified by a string.
* This map holds metadata information related to a user schema - a type,
* a schema name, etc.
* @param spec A string pointing to a JSON map containing a schema metadata spec.
* @throws Exception Throws an exception in the case that the map could not be parsed.
* Parses a metadata map from a location specified by a string. This map holds
* metadata information related to a user schema - a type, a schema name, etc.
*
* @param spec A string pointing to a JSON map containing a schema metadata
* spec.
* @throws Exception Throws an exception in the case that the map could not be
* parsed.
*/
private
void
parseMetadataSpec
(
String
spec
)
throws
Exception
{
MetadataParser
parser
=
new
MetadataParser
(
spec
);
private
void
parseMetadataSpec
(
final
String
spec
)
throws
Exception
{
final
MetadataParser
parser
=
new
MetadataParser
(
spec
);
this
.
metadataMap
=
parser
.
getMetadataMap
();
}
/**
* Parses a field map from a location specified by a string.
* This map holds a flat list of fields that the user will interact with
* through the record interface. Every field holds a set of properties.
* @param spec A string pointing to a JSON map containing a schema field spec.
* @throws Exception Throws an exception in the case that the map could not be parsed.
* Parses a field map from a location specified by a string. This map holds a
* flat list of fields that the user will interact with through the record
* interface. Every field holds a set of properties.
*
* @param spec A string pointing to a JSON map containing a schema field spec.
* @throws Exception Throws an exception in the case that the map could not be
* parsed.
*/
private
void
parseFieldSpec
(
String
spec
)
throws
Exception
{
FieldParser
parser
=
new
FieldParser
(
spec
);
private
void
parseFieldSpec
(
final
String
spec
)
throws
Exception
{
final
FieldParser
parser
=
new
FieldParser
(
spec
);
this
.
fieldMaps
=
parser
.
getFieldMaps
();
}
/**
* Parses a condition map from a location specified by a string and a factory from a given class string.
* The condition map holds a flat list of conditions that the user will interact with
* through the record interface. Every condition holds a set of properties.
* Properties of conditions are mostly immutable, except for values of basic
* comparison conditions.
* The factory class usually should contain switches for each condition operator referenced
* in a condition map. If no factory is provided, the default factory is used, which handles
* basic (=, /=, <, >, <=, >=) operations on basic (boolean, float, double, int, string, datetime) datatypes.
* If no conditions are found, currently the
* @param conditionMap A conditionMap containing map and factory keywords
* @throws Exception Throws an exception in the case that the map could not be parsed.
* Parses a condition map from a location specified by a string and a factory
* from a given class string. The condition map holds a flat list of conditions
* that the user will interact with through the record interface. Every
* condition holds a set of properties. Properties of conditions are mostly
* immutable, except for values of basic comparison conditions. The factory
* class usually should contain switches for each condition operator referenced
* in a condition map. If no factory is provided, the default factory is used,
* which handles basic (=, /=, <, >, <=, >=) operations on basic (boolean,
* float, double, int, string, datetime) datatypes. If no conditions are found,
* currently the
*
* @param conditionMap A conditionMap containing map and factory keywords
* @throws Exception Throws an exception in the case that the map could not be
* parsed.
*/
private
void
parseConditionSpec
(
Map
<
String
,
String
>
conditionMap
)
throws
Exception
{
private
void
parseConditionSpec
(
final
Map
<
String
,
String
>
conditionMap
)
throws
Exception
{
if
(
conditionMap
.
containsKey
(
"map"
))
{
ConditionParser
parser
=
new
ConditionParser
((
String
)
conditionMap
.
get
(
"map"
));
final
ConditionParser
parser
=
new
ConditionParser
((
String
)
conditionMap
.
get
(
"map"
));
this
.
conditionMaps
=
parser
.
getConditionMaps
();
if
(
conditionMap
.
containsKey
(
"factory"
))
{
this
.
createOperatorFactory
((
String
)
conditionMap
.
get
(
"factory"
));
...
...
src/java/main/gov/noaa/messageapi/exceptions/ConfigurationParsingException.java
View file @
42222960
package
gov.noaa.messageapi.exceptions
;
import
java.lang.Exception
;
public
class
ConfigurationParsingException
extends
Exception
{
public
class
ConfigurationParsingException
extends
MessageApiException
{
/**
* Required (generated) serial version ID for serializable class
...
...
src/java/main/gov/noaa/messageapi/exceptions/MessageApiException.java
0 → 100644
View file @
42222960
package
gov.noaa.messageapi.exceptions
;
import
java.lang.Exception
;
public
class
MessageApiException
extends
Exception
{
/**
*
*/
private
static
final
long
serialVersionUID
=
-
4783565590470822212L
;
/**
* Required (generated) serial version ID for serializable class
*/
public
MessageApiException
(
String
message
,
Throwable
err
)
{
super
(
message
,
err
);
}
public
MessageApiException
(
String
message
)
{
super
(
message
);
}
}
src/java/main/gov/noaa/messageapi/interfaces/ITransformation.java
View file @
42222960
...
...
@@ -4,6 +4,11 @@ import java.util.Map;
import
java.util.List
;
/**
* The Transformation is a container that consumes a map of transformation ids
* and corresponding record lists. Any business logic that manipulates records can be used in a transformation.
* Transformation implementations should endeavor to maintain statelessness. The default Transformation implementation
* is automatically stateless in the case that the transformed records contain basic field types (Integer, String, Byte, etc.)
* and calls a copy method for user defined object types.
* @author Ryan Berkheimer
*/
public
interface
ITransformation
{
...
...
src/java/main/gov/noaa/messageapi/utils/request/ContainerUtils.java
View file @
42222960
...
...
@@ -15,6 +15,9 @@ import gov.noaa.messageapi.utils.containers.CollectionUtils;
/**
* This class contains static utilities for creating, parsing, or otherwise manipulating
* containers. Containers are record collections and include collections, transformations,
* and classifiers.
* @author Ryan Berkheimer
*/
public
class
ContainerUtils
{
...
...
@@ -29,10 +32,12 @@ public class ContainerUtils {
* @param records The schema records to be converted to container records
* @return A list of container records
*/
public
static
List
<
IContainerRecord
>
convertSchemaRecords
(
ISchema
schema
,
IContainer
container
,
IRecord
requestRecord
,
List
<
IRecord
>
schemaRecords
)
{
IContainerRecord
containerRecordTemplate
=
createRecordTemplate
(
container
);
public
static
List
<
IContainerRecord
>
convertSchemaRecords
(
final
ISchema
schema
,
final
IContainer
container
,
final
IRecord
requestRecord
,
final
List
<
IRecord
>
schemaRecords
)
{
final
IContainerRecord
containerRecordTemplate
=
createRecordTemplate
(
container
);
return
schemaRecords
.
stream
().
map
(
schemaRecord
->
{
IContainerRecord
containerRecord
=
CollectionUtils
.
setFieldValues
(
containerRecordTemplate
.
getCopy
(),
schemaRecord
.
getFields
());
final
IContainerRecord
containerRecord
=
CollectionUtils
.
setFieldValues
(
containerRecordTemplate
.
getCopy
(),
schemaRecord
.
getFields
());
return
CollectionUtils
.
validateCollectionConditions
(
schema
,
containerRecord
,
requestRecord
);
}).
collect
(
Collectors
.
toList
());
}
...
...
@@ -41,11 +46,14 @@ public class ContainerUtils {
* Creates an empty record for use in record conversion by copy. Uses the
* definition of the provided container to create a new empty record object,
* with
* @param container The container containing a definition that the template ContainerRecord object will be based on
* @return A new, empty,
*
* @param container The container containing a definition that the template
* ContainerRecord object will be based on
* @return A new, empty,
*/
public
static
IContainerRecord
createRecordTemplate
(
IContainer
container
)
{
List
<
ICollection
>
collections
=
CollectionUtils
.
buildCollections
(
container
.
getDefinition
().
getCollectionMaps
());
public
static
IContainerRecord
createRecordTemplate
(
final
IContainer
container
)
{
final
List
<
ICollection
>
collections
=
CollectionUtils
.
buildCollections
(
container
.
getDefinition
().
getCollectionMaps
());
return
new
ContainerRecord
(
collections
);
}
...
...
src/java/main/gov/noaa/messageapi/utils/request/PacketUtils.java
View file @
42222960
...
...
@@ -13,30 +13,34 @@ import gov.noaa.messageapi.interfaces.IRecord;
import
gov.noaa.messageapi.packets.DefaultPacket
;
import
gov.noaa.messageapi.utils.general.ListUtils
;
//import gov.noaa.messageapi.utils.request.SchemaUtils;
//import gov.noaa.messageapi.utils.request.RejectionUtils;
/**
* This class contains static utilities related to creating, parsing, routing, or otherwise
* manipulating Packets. Packets are containers that hold records and rejections and are
* the return type of endpoints.
* @author Ryan Berkheimer
*/
public
class
PacketUtils
{
public
static
IPacket
create
(
ISchema
schema
,
List
<
IRecord
>
records
)
{
IPacket
dataPacket
=
new
DefaultPacket
();
List
<
IRejection
>
primaryRejections
=
RejectionUtils
.
getRequiredFieldRejections
(
records
);
List
<
IRecord
>
filteredRecords
=
SchemaUtils
.
filterFieldlessConditions
(
SchemaUtils
.
filterNonValuedConditions
(
SchemaUtils
.
filterRejections
(
records
,
primary
Rejections
)));
List
<
IRejection
>
secondaryRejections
=
RejectionUtils
.
getFieldConditionRejections
(
schema
,
filteredRecords
);
public
static
IPacket
create
(
final
ISchema
schema
,
final
List
<
IRecord
>
records
)
{
final
IPacket
dataPacket
=
new
DefaultPacket
();
final
List
<
IRejection
>
primaryRejections
=
RejectionUtils
.
getRequiredFieldRejections
(
records
);
final
List
<
IRecord
>
filteredRecords
=
SchemaUtils
.
filterFieldlessConditions
(
SchemaUtils
.
filterNonValuedConditions
(
SchemaUtils
.
filterRejections
(
records
,
primaryRejections
)));
final
List
<
IRejection
>
secondaryRejections
=
RejectionUtils
.
getFieldCondition
Rejections
(
schema
,
filteredRecords
);
dataPacket
.
setRecords
(
SchemaUtils
.
filterRejections
(
filteredRecords
,
secondaryRejections
));
dataPacket
.
setRejections
(
ListUtils
.
flatten
(
new
ArrayList
<
List
<
IRejection
>>(
Arrays
.
asList
(
primaryRejections
,
secondaryRejections
))));
dataPacket
.
setRejections
(
ListUtils
.
flatten
(
new
ArrayList
<
List
<
IRejection
>>(
Arrays
.
asList
(
primaryRejections
,
secondaryRejections
))));
return
dataPacket
;
}
public
static
IPacket
combineResults
(
List
<
IPacket
>
packets
)
{
List
<
IRecord
>
allRecords
=
ListUtils
.
flatten
(
packets
.
stream
().
map
(
packet
->
packet
.
getRecords
()).
collect
(
Collectors
.
toList
()));
List
<
IRejection
>
allRejections
=
ListUtils
.
flatten
(
packets
.
stream
().
map
(
packet
->
packet
.
getRejections
()).
collect
(
Collectors
.
toList
()));
public
static
IPacket
combineResults
(
final
List
<
IPacket
>
packets
)
{
final
List
<
IRecord
>
allRecords
=
ListUtils
.
flatten
(
packets
.
stream
().
map
(
packet
->
packet
.
getRecords
()).
collect
(
Collectors
.
toList
()));
final
List
<
IRejection
>
allRejections
=
ListUtils
.
flatten
(
packets
.
stream
().
map
(
packet
->
packet
.
getRejections
()).
collect
(
Collectors
.
toList
()));
return
new
DefaultPacket
(
allRecords
,
allRejections
);
}
...
...
src/java/main/gov/noaa/messageapi/utils/request/ProtocolUtils.java
View file @
42222960
...
...
@@ -21,6 +21,10 @@ import gov.noaa.messageapi.records.protocol.ProtocolRecord;
/**
* This class contains static utilities related to creating, parsing, analyzing, or otherwise manipulating
* protocol records. Recall that protocol records belong to the protocol layer and are the primary access method
* for container records of any container type (transformation, collection, classifier, or UUID group) from
* within an endpoint.
* @author Ryan Berkheimer
*/
public
class
ProtocolUtils
{
...
...
@@ -35,89 +39,115 @@ public class ProtocolUtils {
* @param containerRecords A list of container Records to be parsed, categorized, and loaded into protocol records
* @return A list of protocol records, one per connection
*/
public
static
List
<
IProtocolRecord
>
convertContainerRecords
(
IProtocol
protocol
,
List
<
IContainerRecord
>
containerRecords
)
{
public
static
List
<
IProtocolRecord
>
convertContainerRecords
(
final
IProtocol
protocol
,
final
List
<
IContainerRecord
>
containerRecords
)
{
return
protocol
.
getConnections
().
stream
().
map
(
conn
->
{
return
createProtocolRecord
(
conn
,
containerRecords
);
}).
collect
(
Collectors
.
toList
());
}
/**
* The singular method called by convertContainerRecords, accepts a single connection and a list of container records,
* and creates a protocol record based on what the connection specified as data needs
* @param connection A connection containing information on what type of records it needs (classifications, collections, transformations)
* @param containerRecords A list of container records that will be the basis for records added to the protocol record
* @return A protocol record, containing a record map based on the containerRecords, for the given connection
* The singular method called by convertContainerRecords, accepts a single
* connection and a list of container records, and creates a protocol record
* based on what the connection specified as data needs
*
* @param connection A connection containing information on what type of
* records it needs (classifications, collections,
* transformations)
* @param containerRecords A list of container records that will be the basis
* for records added to the protocol record
* @return A protocol record, containing a record map based on the
* containerRecords, for the given connection
*/
public
static
IProtocolRecord
createProtocolRecord
(
IConnection
connection
,
List
<
IContainerRecord
>
containerRecords
)
{
List
<
String
>
connCollections
=
connection
.
getCollections
();
Map
<
String
,
List
<
Object
>>
connClassifiers
=
connection
.
getClassifiers
();
List
<
Map
<
IRecord
,
Map
<
String
,
Object
>>>
recordList
=
ListUtils
.
flatten
(
containerRecords
.
stream
().
map
(
containerRecord
->
{
UUID
recordId
=
containerRecord
.
getId
();
return
ListUtils
.
removeAllNulls
(
containerRecord
.
getCollections
().
stream
().
map
(
collection
->
{
return
convertCollectionToRecord
(
collection
,
recordId
,
connCollections
,
connClassifiers
);
}).
collect
(
Collectors
.
toList
()));
}).
collect
(
Collectors
.
toList
()));
public
static
IProtocolRecord
createProtocolRecord
(
final
IConnection
connection
,
final
List
<
IContainerRecord
>
containerRecords
)
{
final
List
<
String
>
connCollections
=
connection
.
getCollections
();
final
Map
<
String
,
List
<
Object
>>
connClassifiers
=
connection
.
getClassifiers
();
final
List
<
Map
<
IRecord
,
Map
<
String
,
Object
>>>
recordList
=
ListUtils
.
flatten
(
containerRecords
.
stream
().
map
(
containerRecord
->
{
final
UUID
recordId
=
containerRecord
.
getId
();
return
ListUtils
.
removeAllNulls
(
containerRecord
.
getCollections
().
stream
().
map
(
collection
->
{
return
convertCollectionToRecord
(
collection
,
recordId
,
connCollections
,
connClassifiers
);
}).
collect
(
Collectors
.
toList
()));
}).
collect
(
Collectors
.
toList
()));
return
new
ProtocolRecord
(
connection
,
MapUtils
.
mergeMapList
(
recordList
));
}
/**
* Creates a new collection record map entry for the IProtocolRecord map. This entry has a key of
* the record itself (created from the collection field set),
* with a map value, that itself has keys of UUID (uuid type), COLLECTION (string collID), and CLASSIFIERS (Map<String, Object>).
* Creates a new collection record map entry for the IProtocolRecord map. This
* entry has a key of the record itself (created from the collection field set),
* with a map value, that itself has keys of UUID (uuid type), COLLECTION
* (string collID), and CLASSIFIERS (Map<String, Object>).
*
* @param collection The collection that will serve as the basis for the record (record uses collection fields)
* @param recordId A record ID to associated with this record - the UUID of the container it came from
* @param connCollections A list of collections referenced by a connection that will be used to
* determine if this record fits in the given record
* @param connClassifiers A map of classifiers referenced by a connection that this record will be attached to
* @return A new map consisting of a record (IRecord) and a set of associated properties (in a map).
* If none of the properties match, this method returns null.
* @param collection The collection that will serve as the basis for the
* record (record uses collection fields)
* @param recordId A record ID to associated with this record - the UUID
* of the container it came from
* @param connCollections A list of collections referenced by a connection that
* will be used to determine if this record fits in the
* given record
* @param connClassifiers A map of classifiers referenced by a connection that
* this record will be attached to
* @return A new map consisting of a record (IRecord) and a set of associated
* properties (in a map). If none of the properties match, this method
* returns null.
*/
public
static
Map
<
IRecord
,
Map
<
String
,
Object
>>
convertCollectionToRecord
(
ICollection
collection
,
UUID
recordId
,
List
<
String
>
connCollections
,
Map
<
String
,
List
<
Object
>>
connClassifiers
)
{
String
collectionId
=
collection
.
getId
();
Map
<
String
,
Object
>
collectionClassifiers
=
collection
.
getClassifiers
();
public
static
Map
<
IRecord
,
Map
<
String
,
Object
>>
convertCollectionToRecord
(
final
ICollection
collection
,
final
UUID
recordId
,
final
List
<
String
>
connCollections
,
final
Map
<
String
,
List
<
Object
>>
connClassifiers
)
{
final
String
collectionId
=
collection
.
getId
();
final
Map
<
String
,
Object
>
collectionClassifiers
=
collection
.
getClassifiers
();
if
(
collectionMatch
(
collectionId
,
connCollections
)
||
classifierMatch
(
collectionClassifiers
,
connClassifiers
))
{
return
makeCollectionRecordMap
(
recordId
,
new
SchemaRecord
(
collection
.
getFields
()),
collectionId
,
collectionClassifiers
);
return
makeCollectionRecordMap
(
recordId
,
new
SchemaRecord
(
collection
.
getFields
()),
collectionId
,
collectionClassifiers
);
}
return
null
;
}
/**
* Creates a record map for the given record. This record map will be one of many that are merged into
* a single record map for the ProtocolRecord (one map per protocol record). This map
* associates the record object (as a key) with a map of associated properties (as the value).
* These properties included the UUID of the ancestral container, the collectionId of the collection which
* was used in the record creation, and a map of classifiers (key/value pairs) that categorize the record.
* Please note - that in general, objects are not good candidates for map keys, due to key operations being
* indeterminate if objects are changed. However, in this case, we use the value map as the search criteria.
* The record as the key is what's used in processing if some value map parameter matches, making this pattern
* unconcerned with holding the record as a map key.
* @param id A UUID belonging to the parent container (all collections get the same UUID)
* @param record A record created from the collection field set
* @param collectionId The id (string) of the collection used to create the record
* @param classifiers A map of classifiers that
* @return a map for the record
* Creates a record map for the given record. This record map will be one of
* many that are merged into a single record map for the ProtocolRecord (one map
* per protocol record). This map associates the record object (as a key) with a
* map of associated properties (as the value). These properties included the
* UUID of the ancestral container, the collectionId of the collection which was
* used in the record creation, and a map of classifiers (key/value pairs) that
* categorize the record. Please note - that in general, objects are not good
* candidates for map keys, due to key operations being indeterminate if objects
* are changed. However, in this case, we use the value map as the search
* criteria. The record as the key is what's used in processing if some value
* map parameter matches, making this pattern unconcerned with holding the
* record as a map key.
*
* @param id A UUID belonging to the parent container (all collections
* get the same UUID)
* @param record A record created from the collection field set
* @param collectionId The id (string) of the collection used to create the
* record
* @param classifiers A map of classifiers that
* @return a map for the record
*/
public
static
Map
<
IRecord
,
Map
<
String
,
Object
>>
makeCollectionRecordMap
(
UUID
id
,
IRecord
record
,
String
collectionId
,
Map
<
String
,
Object
>
classifiers
)
{
Map
<
IRecord
,
Map
<
String
,
Object
>>
retMap
=
new
HashMap
<
IRecord
,
Map
<
String
,
Object
>>();
Map
<
String
,
Object
>
valMap
=
new
HashMap
<
String
,
Object
>();
public
static
Map
<
IRecord
,
Map
<
String
,
Object
>>
makeCollectionRecordMap
(
final
UUID
id
,
final
IRecord
record
,
final
String
collectionId
,
final
Map
<
String
,
Object
>
classifiers
)
{
final
Map
<
IRecord
,
Map
<
String
,
Object
>>
retMap
=
new
HashMap
<
IRecord
,
Map
<
String
,
Object
>>();
final
Map
<
String
,
Object
>
valMap
=
new
HashMap
<
String
,
Object
>();
valMap
.
put
(
"UUID"
,
id
);
valMap
.
put
(
"COLLECTION"
,
collectionId
);
valMap
.
put
(
"CLASSIFIERS"
,
classifiers
);
valMap
.
put
(
"CLASSIFIERS"
,
classifiers
);
retMap
.
put
(
record
,
valMap
);
return
retMap
;
}
/**
* Determines if a collection ID is contained within a connection list of
* associated collections (or if the connection wants all collections) and returns
* a boolean indicating true (if it matches) or false in the negative case
* @param collectionId An id of the collection in question
* @param connCollections A list of collection ids associated with a given connection
* @return true if a match, otherwise false
* associated collections (or if the connection wants all collections) and
* returns a boolean indicating true (if it matches) or false in the negative
* case
*
* @param collectionId An id of the collection in question
* @param connCollections A list of collection ids associated with a given
* connection
* @return true if a match, otherwise false
*/
public
static
Boolean
collectionMatch
(
String
collectionId
,
List
<
String
>
connCollections
)
{
public
static
Boolean
collectionMatch
(
final
String
collectionId
,
final
List
<
String
>
connCollections
)
{
if
(
connCollections
.
contains
(
collectionId
)
||
connCollections
.
contains
(
"*"
))
{
return
true
;
}
...
...
@@ -125,15 +155,19 @@ public class ProtocolUtils {
}
/**
* Determines if a given collection classifier matches any of the associated classifiers
* referenced by a connection. This method first checks for classifier key matches,
* and then for any matching key, checks the value. Returns true if a match, otherwise false
* @param collectionClassifiers A set of classifiers attached to the collection
* @param connClassifiers A set of classifers attached to the connection
* @return true if classifiers match, false otherwise
* Determines if a given collection classifier matches any of the associated
* classifiers referenced by a connection. This method first checks for
* classifier key matches, and then for any matching key, checks the value.
* Returns true if a match, otherwise false
*
* @param collectionClassifiers A set of classifiers attached to the collection
* @param connClassifiers A set of classifers attached to the connection
* @return true if classifiers match, false otherwise
*/