Revision 47502
Added by Katerina Iatropoulou over 7 years ago
modules/uoa-claims/branches/newClaimSchema/deploy.info | ||
---|---|---|
1 |
{ |
|
2 |
"type_source": "SVN", |
|
3 |
"goal": "package -U -T 4C source:jar", |
|
4 |
"url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-openaire-connector/trunk", |
|
5 |
"deploy_repository": "dnet4-snapshots", |
|
6 |
"version": "4", |
|
7 |
"mail": "antleb@di.uoa.gr, kiatrop@di.uoa.gr", |
|
8 |
"deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", |
|
9 |
"name": "uoa-openaire-connector" |
|
10 |
} |
modules/uoa-claims/branches/newClaimSchema/src/test/java/eu/dnetlib/openaire/thrift/TestConnector.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.thrift; |
|
2 |
|
|
3 |
import org.apache.thrift.TException; |
|
4 |
|
|
5 |
import java.util.Arrays; |
|
6 |
|
|
7 |
/** |
|
8 |
* Created by antleb on 6/20/14. |
|
9 |
*/ |
|
10 |
public class TestConnector { |
|
11 |
|
|
12 |
public static void main(String[] args) throws TException { |
|
13 |
|
|
14 |
OpenAIREConnector.Client client = new ThriftClient().getConnector("194.177.192.223", 7911); |
|
15 |
|
|
16 |
String id = client.insertDocument("123123/3434.23", "doi", "a title", " a description", "OPEN ACCESS", null, Arrays.asList(new Author("id" ,"lastname", "firstname")), "url", "dcsource", "antleb@di.uoa.gr", Arrays.asList("subject"), "2012-01-02", "publisher", "language", "category", "doioioioi" ); |
|
17 |
System.out.println(id); |
|
18 |
|
|
19 |
client.insertConcept(id, "doi", "egi", "antleb@di.uoa.gr", "123"); |
|
20 |
client.insertProjectRelation(id, "doi", new Project("ec", "1233312"), "antleb@di.uoa.gr"); |
|
21 |
client.insertProjectRelation(id, "doi", new Project(null, "1233312"), "antleb@di.uoa.gr"); |
|
22 |
client.insertResultRelation(id, "result", "doi", id, "result", "antleb@di.uoa.gr"); |
|
23 |
|
|
24 |
id = "od______1406::fbda7b28cda277b04c8dc27a5e0deb68"; |
|
25 |
|
|
26 |
client.insertConcept(id, "openaire", "ec", "antleb@di.uoa.gr", "123"); |
|
27 |
client.insertProjectRelation(id, "openaire", new Project("ec", "099809987"), "antleb@di.uoa.gr"); |
|
28 |
client.insertProjectRelation(id, "openaire", new Project(null, "098908908"), "antleb@di.uoa.gr"); |
|
29 |
client.insertResultRelation(id, "result", "openaire", id, "dataset", "antleb@di.uoa.gr"); |
|
30 |
} |
|
31 |
} |
modules/uoa-claims/branches/newClaimSchema/src/test/java/eu/dnetlib/openaire/thrift/ThriftClient.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.thrift; |
|
2 |
|
|
3 |
import org.apache.thrift.protocol.TBinaryProtocol; |
|
4 |
import org.apache.thrift.protocol.TProtocol; |
|
5 |
import org.apache.thrift.transport.TSocket; |
|
6 |
import org.apache.thrift.transport.TTransport; |
|
7 |
import org.apache.thrift.transport.TTransportException; |
|
8 |
|
|
9 |
import eu.dnetlib.openaire.thrift.OpenAIREConnector; |
|
10 |
|
|
11 |
public class ThriftClient { |
|
12 |
|
|
13 |
public OpenAIREConnector.Client getConnector() throws TTransportException { |
|
14 |
return getConnector("localhost", 7911); |
|
15 |
} |
|
16 |
|
|
17 |
public OpenAIREConnector.Client getConnector(String host, int port) throws TTransportException { |
|
18 |
TTransport transport = new TSocket(host, port); |
|
19 |
transport.open(); |
|
20 |
|
|
21 |
TProtocol protocol = new TBinaryProtocol(transport); |
|
22 |
|
|
23 |
return new OpenAIREConnector.Client(protocol); |
|
24 |
} |
|
25 |
} |
modules/uoa-claims/branches/newClaimSchema/src/main/resources/eu/dnetlib/openaire/action/relation.vm | ||
---|---|---|
1 |
<RELATIONS> |
|
2 |
#foreach ($rel in $relations) |
|
3 |
<RELATION type='$rel.Type' source='$rel.SourceId' target='$rel.TargetId' /> |
|
4 |
#end |
|
5 |
</RELATIONS> |
modules/uoa-claims/branches/newClaimSchema/src/main/resources/eu/dnetlib/openaire/thrift/springContext-openaire-thrift.xml | ||
---|---|---|
1 |
<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
<beans xmlns="http://www.springframework.org/schema/beans" |
|
3 |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
4 |
xmlns:tx="http://www.springframework.org/schema/tx" |
|
5 |
|
|
6 |
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
7 |
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd |
|
8 |
http://www.springframework.org/schema/tx |
|
9 |
http://www.springframework.org/schema/tx/spring-tx.xsd"> |
|
10 |
|
|
11 |
<bean id="openaire.dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> |
|
12 |
<property name="driverClassName" value="${openaire.db.driverClassName}" /> |
|
13 |
<property name="url" value="${openaire.db.url}" /> |
|
14 |
<property name="username" value="${openaire.db.username}" /> |
|
15 |
<property name="password" value="${openaire.db.password}" /> |
|
16 |
<property name="maxIdle" value="10" /> |
|
17 |
<property name="maxActive" value="100" /> |
|
18 |
<property name="maxWait" value="10000" /> |
|
19 |
<property name="validationQuery" value="SELECT 1;" /> |
|
20 |
<property name="testOnBorrow" value="true" /> |
|
21 |
<property name="testOnReturn" value="true" /> |
|
22 |
<property name="testWhileIdle" value="true" /> |
|
23 |
<property name="timeBetweenEvictionRunsMillis" value="1200000" /> |
|
24 |
<property name="minEvictableIdleTimeMillis" value="1800000" /> |
|
25 |
<property name="numTestsPerEvictionRun" value="5" /> |
|
26 |
<property name="poolPreparedStatements" value="true" /> |
|
27 |
<property name="defaultAutoCommit" value="true" /> |
|
28 |
</bean> |
|
29 |
|
|
30 |
<bean id="claimConnector" class="eu.dnetlib.openaire.thrift.ClaimConnector"> |
|
31 |
<property name="datasource" ref="openaire.dataSource" /> |
|
32 |
<property name="lookupServiceLocator" ref="lookupServiceLocator"/> |
|
33 |
</bean> |
|
34 |
|
|
35 |
<bean id="alertConnector" class="eu.dnetlib.openaire.thrift.AlertConnector"> |
|
36 |
<property name="alertServiceLocator" ref="alertServiceLocator" /> |
|
37 |
</bean> |
|
38 |
|
|
39 |
<bean id="openAireConnector" class="eu.dnetlib.openaire.thrift.OpenAIREConnectorImpl"> |
|
40 |
<property name="claimConnector" ref="claimConnector" /> |
|
41 |
<property name="alertConnector" ref="alertConnector" /> |
|
42 |
</bean> |
|
43 |
|
|
44 |
<bean id="thriftServer" class="eu.dnetlib.openaire.thrift.ThriftServer" init-method="start" destroy-method="stop"> |
|
45 |
<property name="openAireConnector" ref="openAireConnector" /> |
|
46 |
<property name="port" value="${openaire.connector.thrift.port}"/> |
|
47 |
<property name="timeout" value="${openaire.connector.thrift.timeout}" /> |
|
48 |
</bean> |
|
49 |
|
|
50 |
<tx:annotation-driven transaction-manager="txManager"/> |
|
51 |
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
|
52 |
<property name="dataSource" ref="openaire.dataSource"/> |
|
53 |
</bean> |
|
54 |
|
|
55 |
|
|
56 |
</beans> |
|
57 |
|
modules/uoa-claims/branches/newClaimSchema/src/main/resources/eu/dnetlib/openaire/thrift/springContext-openaire-thrift.properties | ||
---|---|---|
1 |
openaire.connector.thrift.port = 7911 |
|
2 |
openaire.connector.thrift.timeout = 15000 |
|
3 |
|
|
4 |
openaire.connector.unknownRepositoryName = Unknown Repository |
|
5 |
|
|
6 |
openaire.db.driverClassName = org.postgresql.Driver |
|
7 |
openaire.db.url = jdbc:postgresql://194.177.192.223:5432/dnet_claims |
|
8 |
openaire.db.username = dnet |
|
9 |
openaire.db.password = dnetPwd |
modules/uoa-claims/branches/newClaimSchema/src/main/resources/eu/dnetlib/openaire/utils/claims.sql | ||
---|---|---|
1 |
select |
|
2 |
r.resultid as dri_objidentifier, |
|
3 |
r.title as dc_title, |
|
4 |
array_agg(DISTINCT lpad('0'||aut.rank,5,'0')||'ยงยงยง'||ltrim(replace(per.surname||', '||per.name,'UNKNOWN, ',''), ', ')) as dc_creator, |
|
5 |
r.description as dc_description, |
|
6 |
r.publisher as dc_publisher, |
|
7 |
r.keywords as dc_subject, |
|
8 |
r.language as dc_language, |
|
9 |
array_agg(DISTINCT ws.file_url) as dc_identifier, |
|
10 |
r.publication_date as oaf_publicationdate, |
|
11 |
r.embargo_end_date as oaf_embargoenddate, |
|
12 |
r.access_mode as oaf_accessmode, |
|
13 |
r.haskind as oaf_haskind, |
|
14 |
r.hastype as "dr_CobjCategory", |
|
15 |
r.storagedate as oaf_storagedate, |
|
16 |
createdfrom as createdfrom, |
|
17 |
array_agg(DISTINCT p.projectid) as oaf_projectid, |
|
18 |
array_agg(DISTINCT cr.creator) as creators |
|
19 |
|
|
20 |
from |
|
21 |
|
|
22 |
results r |
|
23 |
left outer join results_projects rp on (r.resultid = rp.result) |
|
24 |
left outer join projects p on (p.projectid = rp.project) |
|
25 |
left outer join projects_projectsubjects ps on (ps.project = p.projectID) |
|
26 |
left outer join fundingschemes fs on (p.fundedhow = fs.fundingschemeid) |
|
27 |
left outer join programs s on (p.fundedby = s.programid) |
|
28 |
left outer join specificprograms sp on (s.hasspecificprogram = sp.specificprogramid) |
|
29 |
left outer join frameworkprograms fp on (sp.hasframeworkprogram = fp.frameworkprogramid) |
|
30 |
left outer join authorships aut on (r.resultid = aut.result) |
|
31 |
left outer join persons per on (per.personid = aut.author) |
|
32 |
left outer join organizations o on (o.organizationid = aut.affiliation) |
|
33 |
left outer join instances i on (r.resultid = i.resource) |
|
34 |
left outer join webresources_instances wsi on (wsi.instanceid = i.instanceid) |
|
35 |
left outer join webresources ws on (ws.webresourceid = wsi.webresourceid) |
|
36 |
|
|
37 |
join creations cr on cr.creation = r.resultid |
|
38 |
|
|
39 |
where |
|
40 |
r.pmhdeleted != true and r.pendingforclaim = false |
|
41 |
|
|
42 |
group by |
|
43 |
r.resultid, r.title, r.description, r.publisher, r.keywords, r.language, |
|
44 |
r.publication_date, r.embargo_end_date, r.access_mode, r.haskind, r.hastype, |
|
45 |
r.storagedate, r.createdfrom |
modules/uoa-claims/branches/newClaimSchema/src/main/resources/ehcache.xml | ||
---|---|---|
1 |
<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
3 |
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> |
|
4 |
<!-- |
|
5 |
| Please see http://ehcache.sourceforge.net/documentation/configuration.html for |
|
6 |
| detailed information on how to configurigure caches in this file |
|
7 |
+--> |
|
8 |
<!-- Location of persistent caches on disk --> |
|
9 |
<diskStore path="java.io.tmpdir/EhCacheSpringAnnotationsExampleApp" /> |
|
10 |
|
|
11 |
<defaultCache eternal="true" maxElementsInMemory="10000" |
|
12 |
overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" |
|
13 |
timeToLiveSeconds="0" memoryStoreEvictionPolicy="LRU"/> |
|
14 |
|
|
15 |
<cache name="claimator"/> |
|
16 |
<cache name="alertator.subscriptions"/> |
|
17 |
<cache name="querynator"/> |
|
18 |
</ehcache> |
modules/uoa-claims/branches/newClaimSchema/src/main/thrift/OpenAIREConnector.thrift | ||
---|---|---|
1 |
namespace java eu.dnetlib.openaire.thrift |
|
2 |
|
|
3 |
struct Author { |
|
4 |
1: string id, |
|
5 |
2: string lastName, |
|
6 |
3: string firstName |
|
7 |
} |
|
8 |
|
|
9 |
// alerts |
|
10 |
struct AlertSubscription { |
|
11 |
1: string templateId, |
|
12 |
2: string notificationService, |
|
13 |
3: string queryId, |
|
14 |
4: string resultId, |
|
15 |
5: string alertMode, |
|
16 |
6: string subscriber |
|
17 |
} |
|
18 |
|
|
19 |
struct ResultPage { |
|
20 |
1: i32 limit, |
|
21 |
2: i32 offset, |
|
22 |
3: list<string> columns, |
|
23 |
4: list<list<string>> rows |
|
24 |
} |
|
25 |
|
|
26 |
struct Claim { |
|
27 |
1: string userEmail, |
|
28 |
2: string resultid, |
|
29 |
3: i64 date, |
|
30 |
4: string type, |
|
31 |
5: string xml, |
|
32 |
6: string id |
|
33 |
} |
|
34 |
|
|
35 |
struct Project { |
|
36 |
1: string type, |
|
37 |
2: string projectId |
|
38 |
} |
|
39 |
|
|
40 |
// connector |
|
41 |
service OpenAIREConnector { |
|
42 |
// claim |
|
43 |
list<Claim> getClaimedPublications(1: string userEmail), |
|
44 |
|
|
45 |
// from: date in milisecs |
|
46 |
// to: ditto |
|
47 |
list<Claim> getAllClaimedPublications(1: i64 from, 2: i64 to), |
|
48 |
|
|
49 |
string insertDocument ( |
|
50 |
1: string originalId, |
|
51 |
2: string source, |
|
52 |
3: string title, |
|
53 |
4: string description, |
|
54 |
5: string access_mode, |
|
55 |
6: string embargoEndDate, |
|
56 |
7: list<Author> authors, |
|
57 |
8: string url, |
|
58 |
9: string dcSource, |
|
59 |
10: string userEmail, |
|
60 |
11: list<string> subjects, |
|
61 |
12: string publicationDate, |
|
62 |
13: string publisher, |
|
63 |
14: string language, |
|
64 |
15: string category, |
|
65 |
16: string doi), |
|
66 |
|
|
67 |
void insertConcept ( |
|
68 |
1: string docId, |
|
69 |
2: string documentSource, |
|
70 |
3: string concept, |
|
71 |
4: string userEmail, |
|
72 |
5: string doi), |
|
73 |
|
|
74 |
void insertProjectRelation ( |
|
75 |
1: string docId, |
|
76 |
2: string documentSource, |
|
77 |
3: Project project, |
|
78 |
4: string userEmail), |
|
79 |
|
|
80 |
void insertResultRelation ( |
|
81 |
1: string sourceResultId, |
|
82 |
2: string sourceResultType, |
|
83 |
3: string sourceResultSource, |
|
84 |
4: string targetResultId, |
|
85 |
5: string targetResultType, |
|
86 |
6: string userEmail |
|
87 |
), |
|
88 |
|
|
89 |
void deleteClaim(1: string userEmail, 2:string resultId), |
|
90 |
|
|
91 |
// alerts |
|
92 |
list<AlertSubscription> getSubscriptions( |
|
93 |
1: string alertMode, |
|
94 |
2: string subscriber, |
|
95 |
3: i32 limit, |
|
96 |
4: i32 offset), |
|
97 |
|
|
98 |
void addSubscription(1: AlertSubscription subscription), |
|
99 |
|
|
100 |
void removeSubscription(1: AlertSubscription subscription), |
|
101 |
|
|
102 |
i32 countAlertResults( |
|
103 |
1: string notificationService, |
|
104 |
2: string queryId, |
|
105 |
3: i64 date, |
|
106 |
5: string resultId), |
|
107 |
|
|
108 |
ResultPage getAlertResults( |
|
109 |
1: string notificationService, |
|
110 |
2: string queryId, |
|
111 |
3: string resultId, |
|
112 |
4: i64 fromDate, |
|
113 |
5: i64 toDate, |
|
114 |
6: i32 limit, |
|
115 |
7: i32 offset), |
|
116 |
|
|
117 |
list<string> getContexts(), |
|
118 |
} |
modules/uoa-claims/branches/newClaimSchema/src/main/java/eu/dnetlib/openaire/thrift/ThriftServer.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.thrift; |
|
2 |
|
|
3 |
import org.apache.log4j.Logger; |
|
4 |
import org.apache.thrift.server.TThreadPoolServer; |
|
5 |
import org.apache.thrift.transport.TServerSocket; |
|
6 |
import org.apache.thrift.transport.TTransportException; |
|
7 |
|
|
8 |
public class ThriftServer { |
|
9 |
private OpenAIREConnector.Iface openAireConnector; |
|
10 |
private int port; |
|
11 |
private int timeout; |
|
12 |
private Thread thread; |
|
13 |
|
|
14 |
public void setOpenAireConnector(final OpenAIREConnector.Iface openAireConnector) { |
|
15 |
this.openAireConnector = openAireConnector; |
|
16 |
} |
|
17 |
|
|
18 |
public void setPort(final int port) { |
|
19 |
this.port = port; |
|
20 |
} |
|
21 |
|
|
22 |
public void setTimeout(final int timeout) { |
|
23 |
this.timeout = timeout; |
|
24 |
} |
|
25 |
|
|
26 |
public void start() { |
|
27 |
thread = new Thread(new Runnable() { |
|
28 |
@Override |
|
29 |
public void run() { |
|
30 |
try { |
|
31 |
new TThreadPoolServer(new TThreadPoolServer.Args(new TServerSocket(port, timeout)).processor(new OpenAIREConnector.Processor<OpenAIREConnector.Iface>(openAireConnector))).serve(); |
|
32 |
} catch (final TTransportException e) { |
|
33 |
Logger.getLogger(ThriftServer.class).error("Error starting thrift server", e); |
|
34 |
} |
|
35 |
} |
|
36 |
}); |
|
37 |
thread.start(); |
|
38 |
} |
|
39 |
|
|
40 |
public void stop() { |
|
41 |
thread.interrupt(); |
|
42 |
} |
|
43 |
} |
modules/uoa-claims/branches/newClaimSchema/src/main/java/eu/dnetlib/openaire/thrift/OpenAIREConnectorImpl.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.thrift; |
|
2 |
|
|
3 |
import eu.dnetlib.api.functionality.AlertServiceException; |
|
4 |
import org.apache.log4j.Logger; |
|
5 |
import org.apache.thrift.TException; |
|
6 |
|
|
7 |
import java.net.MalformedURLException; |
|
8 |
import java.net.URISyntaxException; |
|
9 |
import java.util.Date; |
|
10 |
import java.util.List; |
|
11 |
|
|
12 |
public class OpenAIREConnectorImpl implements OpenAIREConnector.Iface { |
|
13 |
private static final Logger logger = Logger.getLogger(OpenAIREConnectorImpl.class); |
|
14 |
|
|
15 |
private ClaimConnector claimConnector; |
|
16 |
private AlertConnector alertConnector; |
|
17 |
|
|
18 |
public void setClaimConnector(final ClaimConnector claimConnector) { |
|
19 |
this.claimConnector = claimConnector; |
|
20 |
} |
|
21 |
|
|
22 |
public void setAlertConnector(final AlertConnector alertConnector) { |
|
23 |
this.alertConnector = alertConnector; |
|
24 |
} |
|
25 |
|
|
26 |
@Override |
|
27 |
public List<Claim> getClaimedPublications(final String user) throws TException { |
|
28 |
try { |
|
29 |
return claimConnector.getClaimedPublications(user); |
|
30 |
} catch (final Exception e) { |
|
31 |
logger.error("Error retrieving claimed publications (user: " + user + ")", e); |
|
32 |
throw new TException("Error retrieving claimed publications (user: " + user + ")", e); |
|
33 |
} |
|
34 |
} |
|
35 |
|
|
36 |
@Override |
|
37 |
public List<Claim> getAllClaimedPublications(long from, long to) throws TException { |
|
38 |
try { |
|
39 |
return claimConnector.getClaimedPublications(new Date(from), new Date(to)); |
|
40 |
} catch (Exception e) { |
|
41 |
logger.error("Error retrieving claimed publications", e); |
|
42 |
|
|
43 |
throw new TException("Error retrieving claimed publications", e); |
|
44 |
} |
|
45 |
} |
|
46 |
|
|
47 |
@Override |
|
48 |
public String insertDocument(String originalId, String source, String title, String description, String access_mode, String embargoEndDate, List<Author> authors, String url, String dcSource, String userEmail, List<String> subjects, String publicationDate, String publisher, String language, String category, String doi) throws org.apache.thrift.TException { |
|
49 |
try { |
|
50 |
return claimConnector.insertDocument(originalId, source, title, description, access_mode, embargoEndDate, authors, url, dcSource, userEmail, subjects, publicationDate, publisher, language, category, doi); |
|
51 |
} catch (Exception e) { |
|
52 |
logger.error("Error adding document", e); |
|
53 |
|
|
54 |
throw new TException(e); |
|
55 |
} |
|
56 |
} |
|
57 |
|
|
58 |
@Override |
|
59 |
public void insertConcept(String docId, String documentSource, String concept, String userEmail, String doi) throws org.apache.thrift.TException { |
|
60 |
try { |
|
61 |
claimConnector.insertConceptRelation(docId, documentSource, concept, userEmail, doi); |
|
62 |
} catch (Exception e) { |
|
63 |
logger.error("Error adding concept relation", e); |
|
64 |
|
|
65 |
throw new TException(e); |
|
66 |
} |
|
67 |
} |
|
68 |
|
|
69 |
@Override |
|
70 |
public void insertProjectRelation(String docId, String documentSource, Project project, String userEmail) throws org.apache.thrift.TException { |
|
71 |
try { |
|
72 |
claimConnector.insertProjectRelation(docId, documentSource, project, userEmail); |
|
73 |
} catch (Exception e) { |
|
74 |
logger.error("Error adding project relation", e); |
|
75 |
|
|
76 |
throw new TException(e); |
|
77 |
} |
|
78 |
} |
|
79 |
|
|
80 |
@Override |
|
81 |
public void insertResultRelation(String sourceResultId, String sourceResultType, String sourceResultSource, String targetResultId, String targetResultType, String userEmail) throws TException { |
|
82 |
try { |
|
83 |
claimConnector.insertResultRelation(sourceResultId, sourceResultType, sourceResultSource, targetResultId, targetResultType,userEmail); |
|
84 |
} catch (Exception e) { |
|
85 |
logger.error("Error adding result relation", e); |
|
86 |
|
|
87 |
throw new TException(e); |
|
88 |
} |
|
89 |
} |
|
90 |
|
|
91 |
@Override |
|
92 |
public List<AlertSubscription> getSubscriptions(final String alertMode, final String subscriber, final int limit, final int offset) throws TException { |
|
93 |
try { |
|
94 |
return alertConnector.getSubscriptions(alertMode, subscriber, limit, offset); |
|
95 |
} catch (final AlertServiceException e) { |
|
96 |
logger.error("Error retrieving subscriptions (alert mode: " + alertMode + ", subscriber: " + subscriber + ", limit: " + limit + ", offset: " + offset + ")", e); |
|
97 |
throw new TException("Error retrieving subscriptions (alert mode: " + alertMode + ", subscriber: " + subscriber + ", limit: " + limit + ", offset: " + offset + ")", e); |
|
98 |
} |
|
99 |
} |
|
100 |
|
|
101 |
@Override |
|
102 |
public void addSubscription(final AlertSubscription subscription) throws TException { |
|
103 |
try { |
|
104 |
alertConnector.addSubscription(subscription); |
|
105 |
} catch (final AlertServiceException e) { |
|
106 |
logger.error("Error adding subscription", e); |
|
107 |
throw new TException("Error adding subscription", e); |
|
108 |
} catch (final MalformedURLException e) { |
|
109 |
logger.error("Error adding subscription", e); |
|
110 |
throw new TException("Error adding subscription", e); |
|
111 |
} catch (final URISyntaxException e) { |
|
112 |
logger.error("Error adding subscription", e); |
|
113 |
throw new TException("Error adding subscription", e); |
|
114 |
} |
|
115 |
} |
|
116 |
|
|
117 |
@Override |
|
118 |
public void removeSubscription(final AlertSubscription subscription) throws TException { |
|
119 |
try { |
|
120 |
alertConnector.removeSubscription(subscription); |
|
121 |
} catch (final AlertServiceException e) { |
|
122 |
logger.error("Error removing subscription", e); |
|
123 |
throw new TException("Error removing subscription", e); |
|
124 |
} catch (final MalformedURLException e) { |
|
125 |
logger.error("Error removing subscription", e); |
|
126 |
throw new TException("Error removing subscription", e); |
|
127 |
} catch (final URISyntaxException e) { |
|
128 |
logger.error("Error removing subscription", e); |
|
129 |
throw new TException("Error removing subscription", e); |
|
130 |
} |
|
131 |
} |
|
132 |
|
|
133 |
@Override |
|
134 |
public int countAlertResults(final String notificationService, final String queryId, final long date, final String resultId) throws TException { |
|
135 |
try { |
|
136 |
return alertConnector.countAlertResults(notificationService, queryId, date, resultId); |
|
137 |
} catch (final AlertServiceException e) { |
|
138 |
logger.error("Error counting alert results (notification service: " + notificationService + ", query: " + queryId + ", date: " + date + ", result: " + resultId + ")", e); |
|
139 |
throw new TException("Error counting alert results (notification service: " + notificationService + ", query: " + queryId + ", date: " + date + ", result: " + resultId + ")", e); |
|
140 |
} catch (final MalformedURLException e) { |
|
141 |
logger.error("Error counting alert results (notification service: " + notificationService + ", query: " + queryId + ", date: " + date + ", result: " + resultId + ")", e); |
|
142 |
throw new TException("Error counting alert results (notification service: " + notificationService + ", query: " + queryId + ", date: " + date + ", result: " + resultId + ")", e); |
|
143 |
} |
|
144 |
} |
|
145 |
|
|
146 |
@Override |
|
147 |
public ResultPage getAlertResults(final String notificationService, final String queryId, final String resultId, final long fromDate, final long toDate, final int limit, final int offset) throws TException { |
|
148 |
try { |
|
149 |
return alertConnector.getAlertResults(notificationService, queryId, resultId, fromDate, toDate, limit, offset); |
|
150 |
} catch (final AlertServiceException e) { |
|
151 |
logger.error("Error retrieving alert results (notification service: " + notificationService + ", query: " + queryId + ", result: " + resultId + ", from date: " + fromDate + ", to date: " + toDate + ", limit: " + |
|
152 |
limit + ", offset: " + offset + ")", e); |
|
153 |
throw new TException("Error retrieving alert results (notification service: " + notificationService + ", query: " + queryId + ", result: " + resultId + ", from date: " + fromDate + ", to date: " + toDate + |
|
154 |
", limit: " + limit + ", offset: " + offset + ")", e); |
|
155 |
} catch (final MalformedURLException e) { |
|
156 |
logger.error("Error retrieving alert results (notification service: " + notificationService + ", query: " + queryId + ", result: " + resultId + ", from date: " + fromDate + ", to date: " + toDate + ", limit: " + |
|
157 |
limit + ", offset: " + offset + ")", e); |
|
158 |
throw new TException("Error retrieving alert results (notification service: " + notificationService + ", query: " + queryId + ", result: " + resultId + ", from date: " + fromDate + ", to date: " + toDate + |
|
159 |
", limit: " + limit + ", offset: " + offset + ")", e); |
|
160 |
} |
|
161 |
} |
|
162 |
|
|
163 |
@Override |
|
164 |
public void deleteClaim(String userEmail, String resultId) throws TException { |
|
165 |
try { |
|
166 |
claimConnector.deleteClaim(userEmail, resultId); |
|
167 |
} catch (Exception e) { |
|
168 |
logger.error("Error deleting claim", e); |
|
169 |
|
|
170 |
throw new TException(e); |
|
171 |
} |
|
172 |
} |
|
173 |
|
|
174 |
@Override |
|
175 |
public List<String> getContexts() throws TException { |
|
176 |
try { |
|
177 |
return claimConnector.getContexts(); |
|
178 |
} catch (Exception e) { |
|
179 |
logger.error("Error getting contexts from IS.", e); |
|
180 |
|
|
181 |
throw new TException(e); |
|
182 |
} |
|
183 |
|
|
184 |
} |
|
185 |
} |
modules/uoa-claims/branches/newClaimSchema/src/main/java/eu/dnetlib/openaire/thrift/ClaimConnector.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.thrift; |
|
2 |
|
|
3 |
|
|
4 |
import eu.dnetlib.api.enabling.ISLookUpService; |
|
5 |
import eu.dnetlib.api.enabling.ISLookUpServiceException; |
|
6 |
import eu.dnetlib.openaire.action.ActionUtils; |
|
7 |
import gr.uoa.di.driver.enabling.ISLookUpException; |
|
8 |
import gr.uoa.di.driver.util.ServiceLocator; |
|
9 |
import org.apache.log4j.Logger; |
|
10 |
import org.apache.velocity.exception.ParseErrorException; |
|
11 |
import org.apache.velocity.exception.ResourceNotFoundException; |
|
12 |
import org.springframework.jdbc.datasource.DataSourceUtils; |
|
13 |
import org.springframework.transaction.annotation.Transactional; |
|
14 |
|
|
15 |
import javax.sql.DataSource; |
|
16 |
import java.sql.Connection; |
|
17 |
import java.sql.PreparedStatement; |
|
18 |
import java.sql.ResultSet; |
|
19 |
import java.sql.SQLException; |
|
20 |
import java.sql.Timestamp; |
|
21 |
import java.util.ArrayList; |
|
22 |
import java.util.Arrays; |
|
23 |
import java.util.Collections; |
|
24 |
import java.util.Date; |
|
25 |
import java.util.List; |
|
26 |
|
|
27 |
@Transactional |
|
28 |
public class ClaimConnector { |
|
29 |
|
|
30 |
private static Logger logger = Logger.getLogger(ClaimConnector.class); |
|
31 |
|
|
32 |
private DataSource datasource = null; |
|
33 |
|
|
34 |
//Using an isLookUp Impl just to make an xQuery to IS. Maybe move all the |
|
35 |
//functionality to commons? |
|
36 |
private ServiceLocator<ISLookUpService> lookupServiceLocator = null; |
|
37 |
|
|
38 |
public List<Claim> getClaimedPublications(final String user) throws SQLException { |
|
39 |
Connection con = DataSourceUtils.getConnection(datasource); |
|
40 |
PreparedStatement stmt = con.prepareStatement("select \"resultid\", \"date\" , \"type\", \"xml\", \"id\" from claims where \"agent\" = ?"); |
|
41 |
stmt.setString(1, user); |
|
42 |
ResultSet rs = stmt.executeQuery(); |
|
43 |
List<Claim> res = new ArrayList<Claim>(); |
|
44 |
|
|
45 |
while (rs.next()) { |
|
46 |
res.add(new Claim(user, rs.getString(1), rs.getTimestamp(2).getTime(), rs.getString(3), rs.getString(4), rs.getString(5))); |
|
47 |
} |
|
48 |
|
|
49 |
rs.close(); |
|
50 |
stmt.close(); |
|
51 |
|
|
52 |
logger.info("Returning " + res.size() + " claimed publications for user " + user); |
|
53 |
|
|
54 |
return res; |
|
55 |
} |
|
56 |
|
|
57 |
public List<Claim> getClaimedPublications(Date from, Date to) throws SQLException { |
|
58 |
Connection con = DataSourceUtils.getConnection(datasource); |
|
59 |
|
|
60 |
PreparedStatement stmt = con.prepareStatement("select \"agent\", \"resultid\", \"date\" , \"type\", \"xml\", \"id\" from claims where \"agent\" != 'inference' and \"date\" >= ?::timestamp and \"date\" <= ?::timestamp "); |
|
61 |
stmt.setTimestamp(1, new Timestamp(from.getTime())); |
|
62 |
stmt.setTimestamp(2, new Timestamp(to.getTime())); |
|
63 |
|
|
64 |
ResultSet rs = stmt.executeQuery(); |
|
65 |
List<Claim> res = new ArrayList<Claim>(); |
|
66 |
|
|
67 |
while (rs.next()) { |
|
68 |
res.add(new Claim(rs.getString(1), rs.getString(2), rs.getTimestamp(3).getTime(), rs.getString(4), rs.getString(5), rs.getString(6))); |
|
69 |
} |
|
70 |
|
|
71 |
rs.close(); |
|
72 |
stmt.close(); |
|
73 |
|
|
74 |
logger.debug("number of claims: " + res.size()); |
|
75 |
logger.info("Returning " + res.size() + " claimed publications for date " + from + "-" + to); |
|
76 |
|
|
77 |
return res; |
|
78 |
} |
|
79 |
|
|
80 |
public void deleteClaim(String userEmail, String id) throws SQLException { |
|
81 |
logger.info("Deleting claim with id " + id + " for agent " + userEmail); |
|
82 |
|
|
83 |
Connection con = DataSourceUtils.getConnection(datasource); |
|
84 |
int claim_id = Integer.parseInt(id); |
|
85 |
String type = null; |
|
86 |
|
|
87 |
PreparedStatement stmt = con.prepareStatement("select \"resultid\", \"type\" from claims where \"id\" =?"); |
|
88 |
stmt.setInt(1, claim_id); |
|
89 |
|
|
90 |
ResultSet rs = stmt.executeQuery(); |
|
91 |
|
|
92 |
String resultid = null; |
|
93 |
String xml = null; |
|
94 |
|
|
95 |
while (rs.next()) { |
|
96 |
resultid = rs.getString("resultid"); |
|
97 |
type = rs.getString("type"); |
|
98 |
} |
|
99 |
|
|
100 |
if (resultid != null) { |
|
101 |
stmt = con.prepareStatement("delete from claims where \"agent\" =? and \"id\" =?"); |
|
102 |
stmt.setString(1, userEmail); |
|
103 |
stmt.setInt(2, claim_id); |
|
104 |
|
|
105 |
stmt.executeUpdate(); |
|
106 |
logger.info("Deleted claim with claim id: " + claim_id + ", result id: " + resultid + " and type: " + type +".") ; |
|
107 |
|
|
108 |
//prepare to get 2nd claim to be deleted |
|
109 |
int claim2_id = claim_id - 1; |
|
110 |
|
|
111 |
if (type != null && type.equals("rels2actions")) { |
|
112 |
con = DataSourceUtils.getConnection(datasource); |
|
113 |
stmt = con.prepareStatement("select \"type\", \"xml\" from claims where \"id\" =? and \"resultid\"=?"); |
|
114 |
stmt.setInt(1, claim2_id); |
|
115 |
stmt.setString(2, resultid); |
|
116 |
rs = stmt.executeQuery(); |
|
117 |
|
|
118 |
while (rs.next()) { |
|
119 |
type = rs.getString("type"); |
|
120 |
xml = rs.getString("xml"); |
|
121 |
} |
|
122 |
|
|
123 |
if(type!= null && type.equals("dmf2actions") && xml != null && !xml.contains("oaf:concept")) { //check if the relation has dmf |
|
124 |
stmt = con.prepareStatement("delete from claims where \"agent\" =? and \"id\" =? and \"resultid\" =? and \"type\" = ?"); |
|
125 |
stmt.setString(1, userEmail); |
|
126 |
stmt.setInt(2, claim2_id); |
|
127 |
stmt.setString(3, resultid); |
|
128 |
stmt.setString(4, "dmf2actions"); |
|
129 |
|
|
130 |
stmt.executeUpdate(); |
|
131 |
logger.info("Deleted claim with id " + claim2_id + " and type: dmf2actions."); |
|
132 |
} |
|
133 |
|
|
134 |
} /*else if (type != null && type.equals("dmf2actions")) { |
|
135 |
logger.info("dmf2actions"); |
|
136 |
con = DataSourceUtils.getConnection(datasource); |
|
137 |
stmt = con.prepareStatement("select \"type\", \"xml\" from claims where \"id\" =? and \"resultid\"=?"); |
|
138 |
stmt.setInt(1, claim2_id); |
|
139 |
stmt.setString(2, resultid); |
|
140 |
|
|
141 |
rs = stmt.executeQuery(); |
|
142 |
while (rs.next()) { |
|
143 |
type = rs.getString("type"); |
|
144 |
xml = rs.getString("xml"); |
|
145 |
} |
|
146 |
|
|
147 |
logger.info("xml: " + xml); |
|
148 |
logger.info("xml? " + xml.contains("oaf:concept")); |
|
149 |
|
|
150 |
if(type!= null && type.equals("dmf2actions") && xml != null && !xml.contains("oaf:concept")) { //delete concept with extra dmf (doi,orchid,... etc) |
|
151 |
logger.debug("dmf2actions and not concept"); |
|
152 |
|
|
153 |
stmt = con.prepareStatement("delete from claims where \"agent\" =? and \"id\" =? and \"resultid\" =? and \"type\" = ?"); |
|
154 |
stmt.setString(1, userEmail); |
|
155 |
stmt.setInt(2, claim2_id); |
|
156 |
stmt.setString(3, resultid); |
|
157 |
stmt.setString(4, "dmf2actions"); |
|
158 |
|
|
159 |
stmt.executeUpdate(); |
|
160 |
logger.info("Deleted claim with id " + claim2_id + " and type: dmf2actions."); |
|
161 |
} |
|
162 |
|
|
163 |
}*/ |
|
164 |
} |
|
165 |
|
|
166 |
stmt.close(); |
|
167 |
|
|
168 |
logger.info("Deleted claim with id " + id + " for agent " + userEmail); |
|
169 |
} |
|
170 |
|
|
171 |
/** |
|
172 |
* @param id {openaireId, publication doi, ORCIDId (personId-ORCIDPublicationId), data doi} |
|
173 |
* @param source {openaire, doi (crossref), orcid, datacite} |
|
174 |
* @throws ResourceNotFoundException |
|
175 |
* @throws ParseErrorException |
|
176 |
* @throws Exception |
|
177 |
*/ |
|
178 |
public String insertDocument( |
|
179 |
String id, |
|
180 |
String source, |
|
181 |
String title, |
|
182 |
String description, |
|
183 |
String access_mode, |
|
184 |
String embargoEndDate, |
|
185 |
List<Author> authors, |
|
186 |
String url, |
|
187 |
String dcSource, |
|
188 |
String userEmail, |
|
189 |
List<String> subjects, |
|
190 |
String publicationDate, |
|
191 |
String publisher, |
|
192 |
String language, |
|
193 |
String category, |
|
194 |
String doi) throws Exception { |
|
195 |
|
|
196 |
logger.info("Request to insert document with id " + id + " and source " + source); |
|
197 |
String resultId; |
|
198 |
|
|
199 |
try { |
|
200 |
Connection con = DataSourceUtils.getConnection(datasource); |
|
201 |
PreparedStatement stmt; |
|
202 |
String dmf; |
|
203 |
resultId = ActionUtils.getIdentifier(ActionUtils.getPrefix(source), id); |
|
204 |
Date now = new Date(); |
|
205 |
|
|
206 |
if (!source.toLowerCase().equals("openaire") && title != null) { |
|
207 |
stmt = con.prepareStatement("insert into claims (\"agent\", \"resultid\", \"date\", type, xml, set, provenance, nsprefix) values (?, ?, ?, ?, ?, ?, ?, ?)"); |
|
208 |
dmf = ActionUtils.createDMF(id, source, title, description, access_mode, embargoEndDate, authors, url, dcSource, doi, Collections.EMPTY_LIST, subjects, Collections.EMPTY_LIST, publicationDate, publisher, language, category, false); |
|
209 |
|
|
210 |
stmt.setString(1, userEmail); |
|
211 |
stmt.setString(2, resultId); |
|
212 |
stmt.setTimestamp(3, new Timestamp(new Date().getTime())); |
|
213 |
stmt.setString(4, "dmf2actions"); |
|
214 |
stmt.setString(5, dmf); |
|
215 |
stmt.setString(6, "userclaim_dmf"); |
|
216 |
stmt.setString(7, ActionUtils.getProvenance(source)); |
|
217 |
stmt.setString(8, ActionUtils.getPrefix(source)); |
|
218 |
|
|
219 |
stmt.executeUpdate(); |
|
220 |
stmt.close(); |
|
221 |
} |
|
222 |
} catch (Exception e) { |
|
223 |
logger.error("Error inserting document", e); |
|
224 |
throw e; |
|
225 |
} |
|
226 |
|
|
227 |
logger.info("Inserted document with id " + id + ", source " + source + " and given resultId " + resultId); |
|
228 |
return resultId; |
|
229 |
} |
|
230 |
|
|
231 |
public void insertConceptRelation(String documentId, String documentSource, String concept, String userEmail, String doi) throws Exception { |
|
232 |
logger.info("Request for concept relation between document with id " + documentId + " with source " + documentSource + " and concept " + concept + "with doi " + doi); |
|
233 |
|
|
234 |
try { |
|
235 |
Connection con = DataSourceUtils.getConnection(datasource); |
|
236 |
PreparedStatement stmt; |
|
237 |
String dmf; |
|
238 |
|
|
239 |
stmt = con.prepareStatement("insert into claims (\"agent\", \"resultid\", \"date\", type, xml, set, provenance, nsprefix) values (?, ?, ?, ?, ?, ?, ?, ?)"); |
|
240 |
dmf = ActionUtils.createDMF(documentId, documentSource, null, null, null, null, Collections.EMPTY_LIST, null, null, doi, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Arrays.asList(concept), null, null, null, null, true); |
|
241 |
|
|
242 |
stmt.setString(1, userEmail); |
|
243 |
stmt.setString(2, documentId); |
|
244 |
stmt.setTimestamp(3, new Timestamp(new Date().getTime())); |
|
245 |
stmt.setString(4, "updates2actions"); |
|
246 |
stmt.setString(5, dmf); |
|
247 |
stmt.setString(6, "userclaim_dmf"); |
|
248 |
stmt.setString(7, ActionUtils.getProvenance(documentSource)); |
|
249 |
stmt.setString(8, ActionUtils.getPrefix(documentSource)); |
|
250 |
|
|
251 |
stmt.executeUpdate(); |
|
252 |
stmt.close(); |
|
253 |
} catch (Exception e) { |
|
254 |
logger.error("Error adding concept", e); |
|
255 |
throw e; |
|
256 |
} |
|
257 |
|
|
258 |
logger.info("Inserted concept relation between document with id " + documentId + " with source " + documentSource + " and concept " + concept); |
|
259 |
} |
|
260 |
|
|
261 |
public void insertProjectRelation(String docId, String documentSource, Project project, String userEmail) throws Exception { |
|
262 |
logger.info("Request for project relation between document with id " + docId + " with source " + documentSource + " and project " + project); |
|
263 |
|
|
264 |
try { |
|
265 |
Connection con = DataSourceUtils.getConnection(datasource); |
|
266 |
PreparedStatement stmt; |
|
267 |
String xml = ActionUtils.createResultProjectRelation("openaire".equals(documentSource) ? null : documentSource, docId, project.getType(), project.getProjectId()); |
|
268 |
|
|
269 |
stmt = con.prepareStatement("insert into claims (\"agent\", \"resultid\", \"date\", type, xml, set, provenance, nsprefix) values (?, ?, ?, ?, ?, ?, ?, ?)"); |
|
270 |
|
|
271 |
stmt.setString(1, userEmail); |
|
272 |
stmt.setString(2, docId); |
|
273 |
stmt.setTimestamp(3, new Timestamp(new Date().getTime())); |
|
274 |
stmt.setString(4, "rels2actions"); |
|
275 |
stmt.setString(5, xml); |
|
276 |
stmt.setString(6, "userclaim_result_project"); |
|
277 |
stmt.setString(7, ActionUtils.getProvenance(documentSource)); |
|
278 |
stmt.setString(8, ActionUtils.getPrefix(documentSource)); |
|
279 |
|
|
280 |
stmt.executeUpdate(); |
|
281 |
stmt.close(); |
|
282 |
} catch (Exception e) { |
|
283 |
logger.error("Error adding project", e); |
|
284 |
throw e; |
|
285 |
} |
|
286 |
|
|
287 |
logger.info("Inserted project relation between document with id " + docId + " with source " + documentSource + " and project " + project); |
|
288 |
} |
|
289 |
|
|
290 |
public void insertResultRelation(String sourceResultId, String sourceResultType, String sourceResultSource, String targetResultId, String targetResultType, String userEmail) throws Exception { |
|
291 |
logger.info("Request for result relation between source document with id " + sourceResultId + ", type " + sourceResultType + "and source " + sourceResultSource + " and " + |
|
292 |
"target document with id " + targetResultId + ", type " + targetResultType); |
|
293 |
try { |
|
294 |
Connection con = DataSourceUtils.getConnection(datasource); |
|
295 |
PreparedStatement stmt; |
|
296 |
String xml = ActionUtils.createResultResultRelation(sourceResultId, sourceResultType, targetResultId, targetResultType); |
|
297 |
|
|
298 |
stmt = con.prepareStatement("insert into claims (\"agent\", \"resultid\", \"date\", type, xml, set, provenance, nsprefix) values (?, ?, ?, ?, ?, ?, ?, ?)"); |
|
299 |
|
|
300 |
stmt.setString(1, userEmail); |
|
301 |
stmt.setString(2, sourceResultId); |
|
302 |
stmt.setTimestamp(3, new Timestamp(new Date().getTime())); |
|
303 |
stmt.setString(4, "rels2actions"); |
|
304 |
stmt.setString(5, xml); |
|
305 |
stmt.setString(6, "userclaim_result_result"); |
|
306 |
stmt.setString(7, ActionUtils.getProvenance(sourceResultSource)); |
|
307 |
stmt.setString(8, ActionUtils.getPrefix(sourceResultSource)); |
|
308 |
|
|
309 |
stmt.executeUpdate(); |
|
310 |
stmt.close(); |
|
311 |
} catch (Exception e) { |
|
312 |
logger.error("Error adding result relation", e); |
|
313 |
throw e; |
|
314 |
} |
|
315 |
|
|
316 |
logger.info("Inserted result relation between source document with id " + sourceResultId + ", type " + sourceResultType + "and source " + sourceResultSource + " and " + |
|
317 |
"target document with id " + targetResultId + ", type " + targetResultType); |
|
318 |
} |
|
319 |
|
|
320 |
public DataSource getDatasource() { |
|
321 |
return datasource; |
|
322 |
} |
|
323 |
|
|
324 |
public void setDatasource(DataSource datasource) { |
|
325 |
this.datasource = datasource; |
|
326 |
} |
|
327 |
|
|
328 |
public ServiceLocator<ISLookUpService> getLookupServiceLocator() { |
|
329 |
return lookupServiceLocator; |
|
330 |
} |
|
331 |
|
|
332 |
public void setLookupServiceLocator( |
|
333 |
ServiceLocator<ISLookUpService> lookupServiceLocator) { |
|
334 |
this.lookupServiceLocator = lookupServiceLocator; |
|
335 |
} |
|
336 |
|
|
337 |
public List<String> getContexts() throws ISLookUpException, ISLookUpServiceException { |
|
338 |
return lookupServiceLocator.getService().quickSearchProfile("for $x in collection('/db/DRIVER/ContextDSResources/ContextDSResourceType') return $x"); |
|
339 |
} |
|
340 |
} |
modules/uoa-claims/branches/newClaimSchema/src/main/java/eu/dnetlib/openaire/thrift/AlertConnector.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.thrift; |
|
2 |
|
|
3 |
import eu.dnetlib.api.functionality.AlertService; |
|
4 |
import eu.dnetlib.api.functionality.AlertServiceException; |
|
5 |
import gr.uoa.di.driver.util.ServiceLocator; |
|
6 |
|
|
7 |
import java.net.MalformedURLException; |
|
8 |
import java.net.URI; |
|
9 |
import java.net.URISyntaxException; |
|
10 |
import java.net.URL; |
|
11 |
import java.util.ArrayList; |
|
12 |
import java.util.Arrays; |
|
13 |
import java.util.Date; |
|
14 |
import java.util.List; |
|
15 |
|
|
16 |
public class AlertConnector { |
|
17 |
private ServiceLocator<AlertService> alertServiceLocator; |
|
18 |
|
|
19 |
public void setAlertServiceLocator( |
|
20 |
final ServiceLocator<AlertService> alertServiceLocator) { |
|
21 |
this.alertServiceLocator = alertServiceLocator; |
|
22 |
} |
|
23 |
|
|
24 |
public List<AlertSubscription> getSubscriptions(final String alertMode, |
|
25 |
final String subscriber, final int limit, final int offset) |
|
26 |
throws AlertServiceException { |
|
27 |
final List<AlertSubscription> subscriptions = new ArrayList<AlertSubscription>(); |
|
28 |
for (eu.dnetlib.domain.functionality.AlertSubscription subscription : alertServiceLocator |
|
29 |
.getService().getSubscriptions(alertMode, subscriber, limit, |
|
30 |
offset)) |
|
31 |
subscriptions.add(new AlertSubscription(subscription |
|
32 |
.getTemplateId(), subscription.getNotificationService() |
|
33 |
.toString(), subscription.getQueryId(), subscription |
|
34 |
.getResultId(), subscription.getAlertMode(), subscription |
|
35 |
.getSubscriber().toString())); |
|
36 |
return subscriptions; |
|
37 |
} |
|
38 |
|
|
39 |
public void addSubscription(final AlertSubscription subscription) |
|
40 |
throws AlertServiceException, MalformedURLException, |
|
41 |
URISyntaxException { |
|
42 |
alertServiceLocator.getService().addSubscription( |
|
43 |
new eu.dnetlib.domain.functionality.AlertSubscription( |
|
44 |
subscription.getTemplateId(), new URL(subscription |
|
45 |
.getNotificationService()), subscription |
|
46 |
.getQueryId(), subscription.getResultId(), |
|
47 |
subscription.getAlertMode(), new URI(subscription |
|
48 |
.getSubscriber()), true)); |
|
49 |
} |
|
50 |
|
|
51 |
public void removeSubscription(final AlertSubscription subscription) |
|
52 |
throws AlertServiceException, MalformedURLException, |
|
53 |
URISyntaxException { |
|
54 |
alertServiceLocator.getService().removeSubscription( |
|
55 |
subscription.getTemplateId(), |
|
56 |
new URL(subscription.getNotificationService()), |
|
57 |
subscription.getQueryId(), subscription.getResultId(), |
|
58 |
subscription.getAlertMode(), |
|
59 |
new URI(subscription.getSubscriber())); |
|
60 |
} |
|
61 |
|
|
62 |
public int countAlertResults(final String notificationService, |
|
63 |
final String queryId, final long date, final String resultId) |
|
64 |
throws AlertServiceException, MalformedURLException { |
|
65 |
return alertServiceLocator.getService() |
|
66 |
.countAlertResults(new URL(notificationService), queryId, |
|
67 |
new Date(date), resultId); |
|
68 |
} |
|
69 |
|
|
70 |
public ResultPage getAlertResults(final String notificationService, |
|
71 |
final String queryId, final String resultId, final long fromDate, |
|
72 |
final long toDate, final int limit, final int offset) |
|
73 |
throws AlertServiceException, MalformedURLException { |
|
74 |
final eu.dnetlib.domain.functionality.ResultPage resultPage = alertServiceLocator |
|
75 |
.getService().getAlertResults(new URL(notificationService), |
|
76 |
queryId, resultId, new Date(fromDate), |
|
77 |
new Date(toDate), limit, offset); |
|
78 |
final List<List<String>> rows = new ArrayList<List<String>>(); |
|
79 |
for (String[] row : resultPage.getRows()) |
|
80 |
rows.add(Arrays.asList(row)); |
|
81 |
return new ResultPage(resultPage.getLimit(), resultPage.getOffset(), |
|
82 |
Arrays.asList(resultPage.getColumns()), rows); |
|
83 |
} |
|
84 |
} |
modules/uoa-claims/branches/newClaimSchema/src/main/java/eu/dnetlib/openaire/action/Relation.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.action; |
|
2 |
|
|
3 |
public class Relation { |
|
4 |
private String type; |
|
5 |
private String sourceId; |
|
6 |
private String targetId; |
|
7 |
|
|
8 |
public Relation(String type, String sourceId, String targetId) { |
|
9 |
super(); |
|
10 |
this.type = type; |
|
11 |
this.sourceId = sourceId; |
|
12 |
this.targetId = targetId; |
|
13 |
} |
|
14 |
|
|
15 |
public String getType() { |
|
16 |
return type; |
|
17 |
} |
|
18 |
|
|
19 |
public void setType(String type) { |
|
20 |
this.type = type; |
|
21 |
} |
|
22 |
|
|
23 |
public String getSourceId() { |
|
24 |
return sourceId; |
|
25 |
} |
|
26 |
|
|
27 |
public void setSourceId(String sourceId) { |
|
28 |
this.sourceId = sourceId; |
|
29 |
} |
|
30 |
|
|
31 |
public String getTargetId() { |
|
32 |
return targetId; |
|
33 |
} |
|
34 |
|
|
35 |
public void setTargetId(String targetId) { |
|
36 |
this.targetId = targetId; |
|
37 |
} |
|
38 |
|
|
39 |
} |
modules/uoa-claims/branches/newClaimSchema/src/main/java/eu/dnetlib/openaire/action/ActionUtils.java | ||
---|---|---|
1 |
package eu.dnetlib.openaire.action; |
|
2 |
|
|
3 |
import eu.dnetlib.miscutils.datetime.DateUtils; |
|
4 |
import eu.dnetlib.openaire.thrift.Author; |
|
5 |
import eu.dnetlib.openaire.thrift.Project; |
|
6 |
import org.apache.commons.codec.binary.Hex; |
|
7 |
import org.apache.commons.lang.StringEscapeUtils; |
|
8 |
import org.apache.log4j.Logger; |
|
9 |
import org.apache.velocity.Template; |
|
10 |
import org.apache.velocity.VelocityContext; |
|
11 |
import org.apache.velocity.app.VelocityEngine; |
|
12 |
import org.apache.velocity.runtime.RuntimeConstants; |
|
13 |
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; |
|
14 |
|
|
15 |
import java.io.StringWriter; |
|
16 |
import java.security.MessageDigest; |
|
17 |
import java.util.ArrayList; |
|
18 |
import java.util.List; |
|
19 |
import java.util.regex.Pattern; |
|
20 |
|
|
21 |
public class ActionUtils { |
|
22 |
|
|
23 |
private static Logger logger = Logger.getLogger(ActionUtils.class); |
|
24 |
|
|
25 |
public static String createResultProjectRelation(String source, |
|
26 |
String resultId, String projectType, String projectId) |
|
27 |
throws Exception { |
|
28 |
VelocityEngine ve = new VelocityEngine(); |
|
29 |
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); |
|
30 |
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); |
|
31 |
ve.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogSystem"); |
|
32 |
|
|
33 |
ve.init(); |
|
34 |
|
|
35 |
Template t = ve.getTemplate("/eu/dnetlib/openaire/action/relation.vm"); |
|
36 |
VelocityContext vc = new VelocityContext(); |
|
37 |
|
|
38 |
List<Relation> rels = new ArrayList<Relation>(); |
|
39 |
|
|
40 |
rels.add(createRelation(source, resultId, projectType, projectId)); |
|
41 |
|
|
42 |
vc.put("relations", rels); |
|
43 |
|
|
44 |
StringWriter sw = new StringWriter(); |
|
45 |
t.merge(vc, sw); |
|
46 |
|
|
47 |
return sw.toString(); |
|
48 |
} |
|
49 |
|
|
50 |
public static String createResultResultRelation(String sourceResultId, String sourceResultType, String targetResultId, String targetResultType) { |
|
51 |
VelocityEngine ve = new VelocityEngine(); |
|
52 |
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); |
|
53 |
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); |
|
54 |
ve.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogSystem"); |
|
55 |
|
|
56 |
ve.init(); |
|
57 |
|
|
58 |
Template t = ve.getTemplate("/eu/dnetlib/openaire/action/relation.vm"); |
|
59 |
VelocityContext vc = new VelocityContext(); |
|
60 |
|
|
61 |
List<Relation> rels = new ArrayList<Relation>(); |
|
62 |
|
|
63 |
rels.add(new Relation("resultResult_" + sourceResultType + targetResultType + "_isRelatedTo", "50|" + sourceResultId, "50|" + targetResultId)); |
|
64 |
|
|
65 |
vc.put("relations", rels); |
|
66 |
|
|
67 |
StringWriter sw = new StringWriter(); |
|
68 |
t.merge(vc, sw); |
|
69 |
|
|
70 |
return sw.toString(); |
|
71 |
} |
|
72 |
|
|
73 |
// input id: 1306.3402 |
|
74 |
// oai:arXiv.org:1306.3402 |
|
75 |
// MD5("od________18::oai:arXiv.org:1306.3402") |
|
76 |
|
|
77 |
/** |
|
78 |
* Creates a new relation action. |
|
79 |
* @param source the result source. If not null, the resultId is transformed to openaire id. If null, the result is |
|
80 |
* considered to be already an openaire result and is used verbatim |
|
81 |
* @param resultId the result id |
|
82 |
* @param projectType the project type. If not null, the projectId is transformed to openaire id. If null, the projectId is |
|
83 |
* considered to be already in openaire format and is used verbatim |
|
84 |
* @param projectId the project id |
|
85 |
* |
|
86 |
* @return a relation |
|
87 |
*/ |
|
88 |
private static Relation createRelation(String source, String resultId, |
|
89 |
String projectType, String projectId) { |
|
90 |
String resultPrefix; |
|
91 |
String projectPrefix = null; |
|
92 |
|
|
93 |
if (!isValidOpenaireId(resultId) && source != null) { |
|
94 |
if (source.equals("arxiv")) { |
|
95 |
resultId = "oai:arXiv.org:" + resultId; |
|
96 |
} else if (source.equals("pubmed")) { |
|
97 |
resultId = "oai:europepmc.org:" + resultId; |
|
98 |
} |
|
99 |
|
|
100 |
resultPrefix = getPrefix(source); |
|
101 |
resultId = getIdentifier(resultPrefix, resultId); |
|
102 |
} |
|
103 |
|
|
104 |
resultId = "50|" + resultId; |
|
105 |
|
|
106 |
if (projectType != null) { |
|
107 |
if (projectType.equals("ec")) { |
|
108 |
projectPrefix = "corda_______"; |
|
109 |
} else if (projectType.equals("wt")) { |
|
110 |
projectPrefix = "wt__________::WT"; |
|
111 |
} |
|
112 |
|
|
113 |
projectId = projectPrefix + "::" + projectId; |
|
114 |
} |
|
115 |
|
|
116 |
projectId = "40|" + projectId; |
|
117 |
|
|
118 |
return new Relation("resultProject", resultId, projectId); |
|
119 |
} |
|
120 |
|
|
121 |
private static boolean isValidOpenaireId(String resultId) { |
|
122 |
|
|
123 |
return Pattern.matches("\\w{12}::[a-f0-9]{32}", resultId); |
|
124 |
} |
|
125 |
|
|
126 |
public static String getPrefix(String source) { |
|
127 |
logger.debug("SOURCE " + source); |
|
128 |
if (source == null || source.equals("openaire")) { |
|
129 |
return "openaire____"; |
|
130 |
} else if (source.equals("doi")) { |
|
131 |
return "crossref____"; |
|
132 |
} if (source.equals("orcid")) { |
|
133 |
return "orcid_______"; |
|
134 |
} else if (source.equals("datacite")) { |
|
135 |
return "datacite____"; |
|
136 |
} else if (source.equals("driver")) { |
|
137 |
return "driver______"; |
|
138 |
} else |
|
139 |
return null; |
|
140 |
} |
|
141 |
|
|
142 |
public static String getProvenance(String source) { |
|
143 |
if (source == null || source.equals("openaire")) |
|
144 |
return "user:claim:search"; |
|
145 |
else if (source.equals("doi") || source.equals("orcid")) |
|
146 |
return "user:claim:pid"; |
|
147 |
else if (source.equals("datacite")) |
|
148 |
return "user:claim:datacite"; |
|
149 |
else |
|
150 |
return null; |
|
151 |
} |
|
152 |
|
|
153 |
public static String createDMF(String id, String source, String title, |
|
154 |
String description, String access_mode, String embargoEndDate, |
|
155 |
List<Author> authors, String url, String dcSource, String doi, |
|
156 |
List<Project> projects, List<String> subjects, List<String> concepts, String publicationDate, String publisher, String language, String category, boolean isConcept) throws Exception { |
|
157 |
|
|
158 |
logger.info("create with doi " + doi); |
|
159 |
|
|
160 |
VelocityEngine ve = new VelocityEngine(); |
|
161 |
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); |
|
162 |
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); |
|
163 |
ve.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogSystem"); |
|
164 |
ve.init(); |
|
165 |
|
|
166 |
|
|
167 |
Template t = ve.getTemplate("/eu/dnetlib/openaire/action/dmf.vm"); |
|
168 |
VelocityContext vc = new VelocityContext(); |
|
169 |
|
|
170 |
String hostedby = null; |
|
171 |
String hostedbyName = null; |
|
172 |
String collectedFrom = null; |
|
173 |
String collectedFromName = null; |
|
174 |
String recordIdentifier = id; |
|
175 |
String prefix = getPrefix(source); |
|
176 |
|
|
177 |
|
|
178 |
//if the orcid id exists |
|
179 |
String orcid = null; |
|
180 |
|
|
181 |
if (source.equals("doi") && !isConcept) { |
|
182 |
hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18"; |
|
183 |
hostedbyName = "Unknown Repository"; |
|
184 |
collectedFrom = "openaire____::crossref"; |
|
185 |
collectedFromName = "Crossref"; |
|
186 |
doi = id; |
|
187 |
|
|
188 |
} else if (source.equals("datacite")) { |
|
189 |
hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18"; |
|
190 |
hostedbyName = "Unknown Repository"; |
|
191 |
collectedFrom = "openaire____::datacite"; |
|
192 |
collectedFromName = "Datacite"; |
|
193 |
|
|
194 |
} else if (source.equals("orcid")) { |
|
195 |
orcid = id; |
|
196 |
hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18"; |
|
197 |
hostedbyName = "Unknown Repository"; |
|
198 |
collectedFrom = "openaire____::orcid"; |
|
199 |
collectedFromName = "ORCID"; |
|
200 |
|
|
201 |
} else if (source.equals("driver")) { |
|
202 |
hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18"; |
|
203 |
hostedbyName = "Unknown Repository"; |
|
204 |
collectedFrom = "openaire____::driver"; |
|
205 |
collectedFromName = "Digital Repository Infrastructure Vision for European Research"; |
|
206 |
} |
|
207 |
|
|
208 |
logger.info("create with doi " + doi); |
|
209 |
|
|
210 |
if (doi != null) { |
|
211 |
vc.put("doi", doi); |
|
212 |
} else if (orcid != null){ |
|
213 |
//if there is no doi but we have an orcid, id we store it |
|
214 |
vc.put("orcid", orcid); |
|
215 |
} |
|
216 |
|
|
217 |
// openaire ids should not be touched! |
|
218 |
if (!source.equals("openaire")) |
|
219 |
id = getIdentifier(prefix, id); |
|
220 |
|
|
221 |
vc.put("objIdentifier", id); |
|
222 |
vc.put("recordIdentifier", recordIdentifier); |
|
223 |
vc.put("dateOfCollection", DateUtils.calculate_ISO8601(System.currentTimeMillis())); |
|
224 |
vc.put("hostedby", hostedby); |
|
225 |
vc.put("collectedFrom", collectedFrom); |
|
226 |
vc.put("hostedbyName", hostedbyName); |
|
227 |
vc.put("collectedFromName", collectedFromName); |
|
228 |
vc.put("embargoEndDate", embargoEndDate); |
|
229 |
vc.put("title", title); |
|
230 |
vc.put("description", description); |
|
231 |
vc.put("accessMode", access_mode); |
|
232 |
vc.put("dcSource", dcSource); |
|
233 |
vc.put("url", url); |
|
234 |
vc.put("publisher", publisher); |
|
235 |
vc.put("language", language); |
|
236 |
vc.put("objCategory", category); |
|
237 |
|
|
238 |
vc.put("datasourceprefix", prefix); |
|
239 |
|
|
240 |
List<String> creators = new ArrayList<String>(); |
|
241 |
for (Author author : authors) { |
|
242 |
String name = author.getLastName(); |
|
243 |
|
|
244 |
|
|
245 |
if (author.getFirstName() != null && !author.getFirstName().trim().isEmpty()) |
|
246 |
name += ", " + author.getFirstName(); |
|
247 |
|
|
248 |
creators.add(name); |
|
249 |
} |
|
250 |
|
|
251 |
vc.put("creators", creators); |
|
252 |
vc.put("projects", projects); |
|
253 |
vc.put("subjects", subjects); |
|
254 |
vc.put("concepts", concepts); |
|
255 |
|
|
256 |
if (publicationDate != null && !publicationDate.equals("")) |
|
257 |
vc.put("publicationDate", publicationDate + "-01-01T00:00:00Z"); |
|
258 |
|
|
259 |
vc.put("StringEscapeUtils", StringEscapeUtils.class); |
|
260 |
|
|
261 |
StringWriter sw = new StringWriter(); |
|
262 |
t.merge(vc, sw); |
|
263 |
|
|
264 |
return sw.toString(); |
|
265 |
} |
|
266 |
|
|
267 |
// private static String getIdentifier(String prefix, String id) { |
|
268 |
// return prefix + "::" + |
|
269 |
// com.google.common.hash.Hashing.md5().hashString(id).toString(); |
|
270 |
// } |
|
271 |
|
|
272 |
public static String getIdentifier(String prefix, String id) { |
|
273 |
try { |
|
274 |
logger.debug("PREFIX " + prefix); |
|
275 |
MessageDigest md = MessageDigest.getInstance("MD5"); |
|
276 |
|
|
277 |
md.update(id.getBytes("UTF-8")); |
|
278 |
|
|
279 |
return prefix + "::" + new String(Hex.encodeHex(md.digest())); |
|
280 |
} catch (Exception e) { |
|
281 |
logger.error("Error creating id", e); |
|
282 |
return null; |
|
283 |
} |
|
284 |
} |
|
285 |
} |
modules/uoa-claims/branches/newClaimSchema/pom.xml | ||
---|---|---|
1 |
<?xml version="1.0"?> |
|
2 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
|
3 |
<parent> |
|
4 |
<groupId>eu.dnetlib</groupId> |
|
5 |
<artifactId>dnet-parent</artifactId> |
|
6 |
<version>1.0.0</version> |
|
7 |
</parent> |
|
8 |
<modelVersion>4.0.0</modelVersion> |
|
9 |
<groupId>eu.dnetlib</groupId> |
|
10 |
<artifactId>uoa-openaire-connector</artifactId> |
|
11 |
<version>1.3.1-SNAPSHOT</version> |
|
12 |
<scm> |
|
13 |
<developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-openaire-connector/trunk</developerConnection> |
|
14 |
</scm> |
|
15 |
<pluginRepositories> |
|
16 |
<pluginRepository> |
|
17 |
<id>dtrotts</id> |
|
18 |
<name>Repository for maven thrift plugin</name> |
|
19 |
<url>http://maven.davidtrott.com/repository</url> |
|
20 |
<layout>default</layout> |
|
21 |
</pluginRepository> |
|
22 |
</pluginRepositories> |
|
23 |
<build> |
|
24 |
<plugins> |
|
25 |
<plugin> |
|
26 |
<artifactId>maven-assembly-plugin</artifactId> |
|
27 |
<configuration> |
|
28 |
<archive> |
|
29 |
|
|
30 |
</archive> |
|
31 |
<descriptorRefs> |
|
32 |
<descriptorRef>jar-with-dependencies</descriptorRef> |
|
33 |
</descriptorRefs> |
|
34 |
</configuration> |
|
35 |
</plugin> |
|
36 |
<plugin> |
|
37 |
<groupId>org.apache.thrift.tools</groupId> |
|
38 |
<artifactId>maven-thrift-plugin</artifactId> |
|
39 |
<version>0.1.10</version> |
|
40 |
<executions> |
|
41 |
<execution> |
|
42 |
<id>thrift-sources</id> |
|
43 |
<phase>generate-sources</phase> |
|
44 |
<goals> |
|
45 |
<goal>compile</goal> |
|
46 |
</goals> |
|
47 |
</execution> |
|
48 |
<execution> |
|
49 |
<id>thrift-test-sources</id> |
|
50 |
<phase>generate-test-sources</phase> |
|
51 |
<goals> |
|
52 |
<goal>testCompile</goal> |
|
53 |
</goals> |
|
54 |
</execution> |
|
55 |
</executions> |
|
56 |
</plugin> |
|
57 |
</plugins> |
|
58 |
<pluginManagement> |
|
59 |
<plugins> |
|
60 |
<!--This plugin's configuration is used to store Eclipse m2e settings |
|
61 |
only. It has no influence on the Maven build itself. --> |
|
62 |
<plugin> |
|
63 |
<groupId>org.eclipse.m2e</groupId> |
|
64 |
<artifactId>lifecycle-mapping</artifactId> |
|
65 |
<version>1.0.0</version> |
|
66 |
<configuration> |
|
67 |
<lifecycleMappingMetadata> |
|
68 |
<pluginExecutions> |
|
69 |
<pluginExecution> |
|
70 |
<pluginExecutionFilter> |
|
71 |
<groupId>org.apache.thrift.tools</groupId> |
|
72 |
<artifactId>maven-thrift-plugin</artifactId> |
|
73 |
<versionRange>[0.1.10,)</versionRange> |
|
74 |
<goals> |
|
75 |
<goal>testCompile</goal> |
|
76 |
</goals> |
|
77 |
</pluginExecutionFilter> |
|
78 |
<action> |
|
79 |
<ignore /> |
|
80 |
</action> |
|
81 |
</pluginExecution> |
|
82 |
</pluginExecutions> |
|
83 |
</lifecycleMappingMetadata> |
|
84 |
</configuration> |
|
85 |
</plugin> |
|
86 |
</plugins> |
|
87 |
</pluginManagement> |
|
88 |
</build> |
|
89 |
<dependencies> |
|
90 |
<dependency> |
|
91 |
<groupId>junit</groupId> |
|
92 |
<artifactId>junit</artifactId> |
|
93 |
<version>[0.0.0,)</version> |
|
94 |
<scope>test</scope> |
|
95 |
</dependency> |
Also available in: Unified diff
Delete