Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F93966185
MedCoQuery.java
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Dec 2, 21:47
Size
8 KB
Mime Type
text/x-java
Expires
Wed, Dec 4, 21:47 (1 d, 21 h)
Engine
blob
Format
Raw Data
Handle
22730528
Attached To
R4434 MedCo I2b2 Cell
MedCoQuery.java
View Options
/*
* Copyright (c) 2006-2007 Massachusetts General Hospital
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the i2b2 Software License v1.0
* which accompanies this distribution.
*
* Contributors:
* Rajesh Kuttan
*/
package
ch.epfl.lca1.medco
;
import
java.io.StringWriter
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
ch.epfl.lca1.medco.dao.MedCoDatabase
;
import
ch.epfl.lca1.medco.i2b2.crc.I2B2CRCCell
;
import
ch.epfl.lca1.medco.i2b2.crc.I2B2QueryResponse
;
import
ch.epfl.lca1.medco.unlynx.UnlynxClient
;
import
ch.epfl.lca1.medco.unlynx.UnlynxQuery
;
import
ch.epfl.lca1.medco.unlynx.UnlynxQueryResult
;
import
ch.epfl.lca1.medco.util.Logger
;
import
ch.epfl.lca1.medco.util.MedCoUtil
;
import
ch.epfl.lca1.medco.util.StopWatch
;
import
ch.epfl.lca1.medco.util.exceptions.MedCoException
;
import
ch.epfl.lca1.medco.i2b2.crc.I2B2QueryRequest
;
//
import
edu.harvard.i2b2.common.exception.I2B2Exception
;
import
edu.harvard.i2b2.common.util.jaxb.JAXBUtilException
;
import
edu.harvard.i2b2.crc.datavo.setfinder.query.PanelType
;
import
edu.harvard.i2b2.crc.datavo.setfinder.query.QueryDefinitionRequestType
;
import
edu.harvard.i2b2.crc.datavo.setfinder.query.QueryDefinitionType
;
import
org.javatuples.Pair
;
//todo doc: https://github.com/chb/shrine/tree/master/doc
/**
* Represents a query to MedCo.
* From the XML query (in CRC format), parse to extract the sensitive attributes,
* make query to CRC for non-sensitive attributes, get the patient set from CRC,
* query the cothority with the patient sets and sensitive attributes and answer.
*
* Setfinder query request delegate class $Id: QueryRequestDelegate.java,v 1.17
* 2008/05/08 15:13:45 rk903 Exp $
*
* @author rkuttan
*/
public
class
MedCoQuery
{
private
static
final
String
QUERY_ITEM_KEY_ENC_PREFIX
=
"MEDCO_ENC:"
,
QUERY_ITEM_KEY_GEN_PREFIX
=
"MEDCO_GEN:"
;
/** The original request from client. **/
private
I2B2QueryRequest
queryRequest
;
/** The original XML request from client (a query definition) extracted as XML. **/
private
QueryDefinitionRequestType
originalRequestXml
;
private
I2B2CRCCell
crcCell
;
private
MedCoDatabase
medcoDao
;
public
MedCoQuery
(
I2B2QueryRequest
request
)
throws
I2B2Exception
{
this
.
queryRequest
=
request
;
crcCell
=
new
I2B2CRCCell
(
request
.
getUserAuthentication
());
medcoDao
=
new
MedCoDatabase
();
}
/**
*
* @return the query answer in CRC XML format.
* @throws JAXBUtilException
*/
// todo: handle cases: only clear no encrypt / only encrypt no clear
public
I2B2QueryResponse
executeQuery
(
int
resultMode
,
String
clientPubKey
,
long
timoutSeconds
)
throws
MedCoException
,
I2B2Exception
{
// retrieve the encrypted query terms
StopWatch
.
steps
.
start
(
"Query parsing/splitting"
);
Pair
<
List
<
String
>,
String
>
encryptedItemsAndPredicate
=
extractEncryptedQueryTermsAndPredicate
();
List
<
String
>
encryptedItems
=
encryptedItemsAndPredicate
.
getValue0
();
String
predicate
=
encryptedItemsAndPredicate
.
getValue1
();
StopWatch
.
steps
.
stop
();
// make query to i2b2 with the leftovers clear query terms, creates patient set on server side
StopWatch
.
steps
.
start
(
"Clear query: i2b2 query"
);
I2B2QueryResponse
clearResponse
=
crcCell
.
queryClearTerms
(
queryRequest
);
StopWatch
.
steps
.
stop
();
// predicate empty: means that there is no encrypted query terms, we can stop here the processing
if
(
predicate
.
isEmpty
())
{
clearResponse
.
resetResultInstanceListToClearCountOnly
();
clearResponse
.
setQueryResults
(
""
,
""
,
StopWatch
.
generateAllCsvReports
(
null
));
Logger
.
info
(
"Query clear only successful ("
+
queryRequest
.
getQueryName
()
+
")."
);
return
clearResponse
;
}
StopWatch
.
steps
.
start
(
"Clear query: patient set retrieval"
);
List
<
String
>
clearPatientSet
=
crcCell
.
queryForPatientSet
(
clearResponse
.
getPatientSetId
());
StopWatch
.
steps
.
stop
();
// retrieve encrypted data of the patients
StopWatch
.
steps
.
start
(
"Patient set encrypted data retrieval"
);
List
<
List
<
String
>>
patientsEncData
=
medcoDao
.
getPatientsData
(
clearPatientSet
);
//List<List<String>> patientsEncData = new ArrayList<>();
//List<String> tempTest = new ArrayList<>();
//tempTest.add("ZwneoQQyvDUckDcxlOvS+1IvDckXgw7n13IpznyAcHaU6r3uHuSZOXFHUHxhqINh0q6PFj9htw4Ogrt0TR7b5w=="); //todo: change me for 6/9/10!
//patientsEncData.add(tempTest);
StopWatch
.
steps
.
stop
();
// query unlynx
StopWatch
.
steps
.
start
(
"Unlynx query"
);
UnlynxQuery
unlynxQuery
=
new
UnlynxQuery
(
queryRequest
.
getQueryName
(),
predicate
,
encryptedItems
,
patientsEncData
,
clientPubKey
,
resultMode
,
timoutSeconds
);
UnlynxClient
unlynxClient
=
UnlynxClient
.
executeQuery
(
unlynxQuery
);
unlynxClient
.
waitForCompletion
();
UnlynxQueryResult
queryResult
=
unlynxClient
.
getQueryResult
();
if
(
unlynxClient
.
getQueryState
()
==
UnlynxClient
.
QueryState
.
COMPLETED
)
{
Logger
.
info
(
"MedCo query successful ("
+
queryRequest
.
getQueryName
()
+
")."
);
}
else
{
throw
Logger
.
error
(
new
MedCoException
(
"Error during MedCo query: "
+
queryResult
.
getErrorMessage
()));
}
StopWatch
.
steps
.
stop
();
StopWatch
.
overall
.
stop
();
clearResponse
.
resetResultInstanceListToEncryptedCountOnly
();
clearResponse
.
setQueryResults
(
clientPubKey
,
queryResult
.
getEncResultB64
(),
StopWatch
.
generateAllCsvReports
(
queryResult
.
getTimes
()));
return
clearResponse
;
}
/**
* Extracts from the i2b2 query the sensitive / encrypted items.
*
* They are the items with a non standard name of "MEDCO_ENC" or "MEDCO_GEN"
* enforce that panel are exclusive!! at least for now
*
// from panel - items to
// (exists(v0, r) || exists(v1, r)) && (exists(v2, r) || exists(v3, r)) && exists(v4, r)
* todo: must be modified if invertion implementation
*
* @throws MedCoException if a panel contains mixed clear and encrypted query terms
*/
private
Pair
<
List
<
String
>,
String
>
extractEncryptedQueryTermsAndPredicate
()
throws
MedCoException
{
QueryDefinitionType
qd
=
queryRequest
.
getQueryDefinition
();
StringWriter
predicateSw
=
new
StringWriter
();
List
<
String
>
extractedItems
=
new
ArrayList
<>();
int
encTermCount
=
0
;
// regex that matches with encrypted query terms
Pattern
medcoKeyRegex
=
Pattern
.
compile
(
"^(\\s*)("
+
QUERY_ITEM_KEY_ENC_PREFIX
+
"|"
+
QUERY_ITEM_KEY_GEN_PREFIX
+
")(.*)"
);
// iter on the panels
for
(
int
p
=
0
;
p
<
qd
.
getPanel
().
size
()
;
p
++)
{
boolean
panelIsEnc
=
false
,
panelIsClear
=
false
;
PanelType
panel
=
qd
.
getPanel
().
get
(
p
);
// iter on the items
int
nbItems
=
panel
.
getItem
().
size
();
for
(
int
i
=
0
;
i
<
nbItems
;
i
++)
{
// check if item is clear or encrypted, extract and generate predicate if yes
Matcher
medcoKeyMatcher
=
medcoKeyRegex
.
matcher
(
panel
.
getItem
().
get
(
i
).
getItemKey
());
if
(
medcoKeyMatcher
.
matches
())
{
if
(
i
==
0
)
{
predicateSw
.
append
(
"("
);
}
extractedItems
.
add
(
medcoKeyMatcher
.
group
(
3
));
predicateSw
.
append
(
"exists(v"
+
encTermCount
++
+
", r)"
);
if
(
i
<
nbItems
-
1
)
{
predicateSw
.
append
(
" || "
);
}
else
if
(
i
==
nbItems
-
1
)
{
predicateSw
.
append
(
")"
);
if
(
p
<
qd
.
getPanel
().
size
()
-
1
)
{
predicateSw
.
append
(
" && "
);
}
}
Logger
.
debug
(
"Extracted item "
+
extractedItems
.
get
(
extractedItems
.
size
()
-
1
));
panelIsEnc
=
true
;
}
else
{
panelIsClear
=
true
;
}
// enforce that a panel can only be one type
if
(
panelIsClear
&&
panelIsEnc
)
{
throw
Logger
.
error
(
new
MedCoException
(
"Encountered panel with mixed clear and encrypted query terms: not allowed."
));
}
}
// remove panel and log
if
(
panelIsEnc
)
{
qd
.
getPanel
().
remove
(
panel
);
p
--;
Logger
.
debug
(
"Encountered encrypted panel, removed"
);
}
else
if
(
panelIsClear
)
{
Logger
.
debug
(
"Encountered clear panel"
);
}
else
{
Logger
.
warn
(
"Encountered empty panel in query "
+
qd
.
getQueryName
());
}
}
String
predicate
=
predicateSw
.
toString
();
Logger
.
info
(
"Extracted "
+
extractedItems
.
size
()
+
" encrypted query terms and generated unlynx predicate with "
+
encTermCount
+
" terms: "
+
predicate
+
" for query "
+
queryRequest
.
getQueryName
());
return
new
Pair
<>(
extractedItems
,
predicate
);
}
}
Event Timeline
Log In to Comment