Project

General

Profile

« Previous | Next » 

Revision 32658

[maven-release-plugin] copy for tag dnet-oai-store-service-4.0.0

View differences:

modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/deploy.info
1
{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/dnet-oai-store-service/trunk/", "deploy_repository": "dnet4-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", "name": "dnet-oai-store-service"}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/test/java/eu/dnetlib/data/oai/store/mongo/MongoPublisherStoreDAOTest.java
1
package eu.dnetlib.data.oai.store.mongo;
2

  
3
import static org.junit.Assert.assertEquals;
4
import static org.junit.Assert.assertFalse;
5
import static org.junit.Assert.assertNotNull;
6
import static org.junit.Assert.assertTrue;
7

  
8
import java.util.List;
9

  
10
import javax.annotation.Resource;
11

  
12
import org.junit.After;
13
import org.junit.Before;
14
import org.junit.Ignore;
15
import org.junit.Test;
16
import org.junit.runner.RunWith;
17
import org.springframework.test.context.ContextConfiguration;
18
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
19

  
20
import com.mongodb.DB;
21
import com.mongodb.Mongo;
22

  
23
import eu.dnetlib.data.information.oai.publisher.OaiPublisherException;
24
import eu.dnetlib.data.oai.store.Cursor;
25
import eu.dnetlib.data.oai.store.PublisherStore;
26
import eu.dnetlib.data.oai.store.PublisherStoreDAO;
27

  
28
@RunWith(SpringJUnit4ClassRunner.class)
29
@ContextConfiguration
30
@Ignore
31
public class MongoPublisherStoreDAOTest {
32

  
33
	@Resource
34
	private PublisherStoreDAO<PublisherStore<Cursor>, Cursor> dao;
35
	private String storeId;
36
	@Resource
37
	private Mongo mongoServer;
38
	private String dbName = "test";
39

  
40
	@Before
41
	public void setUp() throws Exception {
42
		PublisherStore<Cursor> theStore = dao.createStore("oai_dc", "final", "index", dbName);
43
		this.storeId = theStore.getId();
44
	}
45

  
46
	@After
47
	public void tearDown() throws Exception {
48
		DB db = mongoServer.getDB(dbName);
49
		db.dropDatabase();
50
	}
51

  
52
	@Test
53
	public void testListPublisherStores() throws OaiPublisherException {
54
		List<PublisherStore<Cursor>> list = dao.listPublisherStores(dbName);
55
		assertEquals(1, list.size());
56
		dao.createStore("oai_dc2", "final", "index", dbName);
57
		List<PublisherStore<Cursor>> list2 = dao.listPublisherStores(dbName);
58
		assertEquals(2, list2.size());
59
	}
60

  
61
	@Test
62
	public void testGetStoreString() {
63
		PublisherStore<Cursor> theStore = dao.getStore(storeId, dbName);
64
		assertEquals("oai_dc", theStore.getMetadataFormat());
65
		assertEquals("final", theStore.getInterpretation());
66
		assertEquals("index", theStore.getLayout());
67
	}
68

  
69
	@Test
70
	public void testGetStoreStringStringString() {
71
		PublisherStore<Cursor> theStore = dao.getStore("oai_dc", "final", "index", dbName);
72
		assertEquals(this.storeId, theStore.getId());
73
	}
74

  
75
	@Ignore
76
	@Test
77
	public void testGetStoreFor() {
78
		PublisherStore<Cursor> theStore = dao.getStoreFor("oai_dc", dbName);
79
		assertEquals("oai_dc", theStore.getMetadataFormat());
80
		assertEquals("final", theStore.getInterpretation());
81
		assertEquals("index", theStore.getLayout());
82
		assertEquals(this.storeId, theStore.getId());
83
	}
84

  
85
	@Test
86
	public void testCreateStore() throws OaiPublisherException {
87
		PublisherStore<Cursor> store = dao.createStore("foo", "fooInterp", "fooLayout", dbName);
88
		assertNotNull(store);
89
		assertTrue(dao.listPublisherStores(dbName).contains(store));
90
	}
91

  
92
	@Test
93
	public void testDeleteStoreString() throws OaiPublisherException {
94
		PublisherStore<Cursor> store = dao.createStore("foo", "fooInterp", "fooLayout", dbName);
95
		assertNotNull(store);
96
		String id = store.getId();
97
		assertTrue(dao.deleteStore(id, dbName));
98
		assertFalse(dao.deleteStore(id, dbName));
99
	}
100

  
101
	@Test
102
	public void testDeleteStoreStringStringString() throws OaiPublisherException {
103
		PublisherStore<Cursor> store = dao.createStore("foo", "fooInterp", "fooLayout", dbName);
104
		assertNotNull(store);
105
		assertTrue(dao.deleteStore("foo", "fooInterp", "fooLayout", dbName));
106
		assertFalse(dao.deleteStore("foo", "fooInterp", "fooLayout", dbName));
107
	}
108

  
109
	@Test
110
	public void testTwoDBs() throws OaiPublisherException {
111
		String db2 = "test2";
112
		PublisherStore<Cursor> store = dao.createStore("foo", "fooInterp", "fooLayout", dbName);
113
		assertTrue(dao.listPublisherStores(dbName).contains(store));
114
		assertFalse(dao.listPublisherStores(db2).contains(store));
115
	}
116
}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/test/java/eu/dnetlib/data/oai/store/parser/MongoQueryParserTest.java
1
package eu.dnetlib.data.oai.store.parser;
2

  
3
import static org.junit.Assert.assertEquals;
4

  
5
import java.util.Date;
6

  
7
import org.apache.commons.logging.Log;
8
import org.apache.commons.logging.LogFactory;
9
import org.bson.types.ObjectId;
10
import org.joda.time.format.DateTimeFormat;
11
import org.joda.time.format.DateTimeFormatter;
12
import org.joda.time.format.ISODateTimeFormat;
13
import org.junit.Test;
14

  
15
import com.google.common.collect.Lists;
16
import com.mongodb.BasicDBObject;
17
import com.mongodb.DBObject;
18

  
19
public class MongoQueryParserTest {
20

  
21
	private final MongoQueryParser mongoParser = new MongoQueryParser();
22
	private static final Log log = LogFactory.getLog(MongoQueryParserTest.class); // NOPMD by marko on 11/24/08 5:02 PM
23

  
24
	@Test
25
	public void testParseEq() {
26
		DBObject expected = new BasicDBObject("set", "CEDIASManuscripts");
27
		DBObject o = this.mongoParser.parse("set = \"CEDIASManuscripts\"");
28
		assertEquals(expected, o);
29

  
30
	}
31

  
32
	@Test
33
	public void testParseNeq() {
34
		DBObject expected = new BasicDBObject("set", new BasicDBObject("$ne", "CEDIASManuscripts"));
35
		DBObject o = this.mongoParser.parse("set <> \"CEDIASManuscripts\"");
36
		assertEquals(expected, o);
37
	}
38

  
39
	@Test
40
	public void testParseAnd() {
41
		DBObject expected = new BasicDBObject("$and", Lists.newArrayList(new BasicDBObject("set", new BasicDBObject("$ne", "CEDIASManuscripts")),
42
				new BasicDBObject("pippo", new BasicDBObject("$gt", "x"))));
43
		DBObject o = this.mongoParser.parse("set <> \"CEDIASManuscripts\" AND pippo > x");
44
		log.info(o);
45
		assertEquals(expected, o);
46
	}
47

  
48
	@Test
49
	public void testParseOr() {
50
		DBObject expected = new BasicDBObject("$or", Lists.newArrayList(new BasicDBObject("set", new BasicDBObject("$ne", "CEDIASManuscripts")),
51
				new BasicDBObject("pippo", new BasicDBObject("$gt", "x"))));
52
		DBObject o = this.mongoParser.parse("set <> \"CEDIASManuscripts\" OR pippo > x");
53
		log.info(o);
54
		assertEquals(expected, o);
55
	}
56

  
57
	@Test
58
	public void testParseNot() {
59
		DBObject expected = new BasicDBObject("$and", Lists.newArrayList(new BasicDBObject("set", "CEDIASManuscripts"), new BasicDBObject("$not",
60
				new BasicDBObject("pippo", new BasicDBObject("$gt", "x")))));
61
		DBObject o = this.mongoParser.parse("set = \"CEDIASManuscripts\" NOT pippo > x");
62
		log.info(o);
63
		assertEquals(expected, o);
64
	}
65

  
66
	@Test
67
	public void testParseStar() {
68
		DBObject expected = new BasicDBObject();
69
		DBObject o = this.mongoParser.parse("*");
70
		DBObject o2 = this.mongoParser.parse("*=*");
71
		assertEquals(expected, o);
72
		assertEquals(expected, o2);
73
	}
74

  
75
	@Test
76
	public void testParseStarAnd() {
77
		DBObject expected = new BasicDBObject("$and", Lists.newArrayList(new BasicDBObject(), new BasicDBObject("pippo", new BasicDBObject("$gt", "x"))));
78
		DBObject o = this.mongoParser.parse("* AND pippo > x");
79
		DBObject o2 = this.mongoParser.parse("*=* AND pippo > x");
80
		assertEquals(expected, o);
81
		assertEquals(expected, o2);
82
	}
83

  
84
	@Test
85
	public void testParseIdQuery() {
86
		DBObject expected = new BasicDBObject("_id", new BasicDBObject("$gt", new ObjectId("5225e093aabf055637bf2c65")));
87
		DBObject o = this.mongoParser.parse("_id > 5225e093aabf055637bf2c65");
88
		assertEquals(expected, o);
89
	}
90

  
91
	@Test
92
	public void testParseUntilDatestamp() {
93
		Date dateTime = this.parseDate("2014-04-02T00:00:00.000Z");
94
		// { "$and" : [ { "oaftype" : { "$ne" : "person"}} , { "datestamp" : { "$lte" : { "$date" : "2014-04-02T00:00:00.000Z"}}}]}
95
		DBObject expected = new BasicDBObject("$and", Lists.newArrayList(new BasicDBObject("oaftype", new BasicDBObject("$ne", "person")), new BasicDBObject(
96
				"datestamp", new BasicDBObject("$lte", dateTime))));
97
		// System.out.println(expected);
98
		DBObject o = this.mongoParser.parse("(oaftype <> \"person\") AND datestamp <= 2014-04-02");
99
		assertEquals(expected, o);
100
		// System.out.println(o);
101
	}
102

  
103
	private Date parseDate(final String date) {
104
		DateTimeFormatter dateNoTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd").withZoneUTC();
105
		DateTimeFormatter iso8601NoMsTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZoneUTC();
106
		DateTimeFormatter iso8601Formatter = ISODateTimeFormat.dateTime().withZoneUTC();
107
		try {
108
			log.debug("Using default " + iso8601Formatter.getClass());
109
			return iso8601Formatter.parseDateTime(date).toDate();
110
		} catch (Exception e) {
111
			try {
112
				log.debug("Switching to ISO with no millisecond date formatter: yyyy-MM-dd'T'HH:mm:ssZ");
113
				return iso8601NoMsTimeFormatter.parseDateTime(date).toDate();
114
			} catch (Exception ex) {
115
				log.debug("Switching to simple date formatter: yyyy-MM-dd");
116
				return dateNoTimeFormatter.parseDateTime(date).toDate();
117
			}
118
		}
119
	}
120
}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/test/java/eu/dnetlib/data/oai/store/sets/MongoSetCollectionTest.java
1
package eu.dnetlib.data.oai.store.sets;
2

  
3
import static org.junit.Assert.assertEquals;
4

  
5
import org.junit.Before;
6
import org.junit.Test;
7

  
8
public class MongoSetCollectionTest {
9

  
10
	private MongoSetCollection mongoSetCollection;
11
	private String strangeSet = "Наукові журнали Національного Авіаційного Університету";
12

  
13
	@Before
14
	public void setup() {
15
		this.mongoSetCollection = new MongoSetCollection();
16
	}
17

  
18
	@Test
19
	public void test() {
20
		String normalised = this.mongoSetCollection.normalizeSetSpec(strangeSet);
21
		assertEquals(MongoSetCollection.DEFAULT_SET, normalised);
22
	}
23

  
24
}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/test/resources/eu/dnetlib/test/profiles/OAIPublisherConfigurationDSResources/OAIPublisherConfigurationDSResourceType/OAIPublisherConfiguration-1.xml
1
<RESOURCE_PROFILE>
2
	<HEADER>
3
		<RESOURCE_IDENTIFIER value="OAIPublisherConfiguration" />
4
		<RESOURCE_TYPE value="OAIPublisherConfigurationDSResourceType" />
5
		<RESOURCE_KIND value="OAIPublisherConfigurationDSResources" />
6
		<RESOURCE_URI value="" />
7
		<DATE_OF_CREATION value="2001-12-31T12:00:00" />
8
	</HEADER>
9
	<BODY>
10
		    <CONFIGURATION>
11
            <OAISETS>
12
                <OAISET enabled="true">
13
                    <spec>OpenAccess</spec>
14
                    <name>Set of Open Access articles</name>
15
                    <description>Set of records having 'OPEN' license</description>
16
                    <query>(license = "OPEN")</query>
17
                </OAISET>
18
                <OAISET enabled="true">
19
                    <spec>ArticlesInNature</spec>
20
                    <name>Articles published by Nature</name>
21
                    <description>Set of articles published by Nature Publishing Group</description>
22
                    <query>(publisher = "Nature Publishing Group")</query>
23
                </OAISET>
24
                <OAISET enabled="true">
25
                    <spec>publications</spec>
26
                    <name>Publications</name>
27
                    <description>Set of all Publications</description>
28
                    <query>resulttypeid="publication"</query>
29
                </OAISET>
30
            </OAISETS>
31
            <METADATAFORMATS>
32
                <METADATAFORMAT exportable="true" metadataPrefix="oaf">
33
                    <NAMESPACE>http://namespace.openaire.eu/oaf</NAMESPACE>
34
                    <SCHEMA>http://www.openaire.eu/schema/0.1/oaf-0.1.xsd</SCHEMA>
35
                    <SOURCE_METADATA_FORMAT interpretation="openaire" layout="index" name="oaf"/>
36
                    <TRANSFORMATION_RULE/>
37
                    <BASE_QUERY>*</BASE_QUERY>
38
                </METADATAFORMAT>
39
                <METADATAFORMAT metadataPrefix="oai_dc" exportable="false">
40
                    <NAMESPACE>http://www.openarchives.org/OAI/2.0/oai_dc/</NAMESPACE>
41
                    <SCHEMA>http://www.openarchives.org/OAI/2.0/oai_dc.xsd</SCHEMA>
42
                    <SOURCE_METADATA_FORMAT interpretation="openaire" layout="index" name="oaf"/>
43
                    <TRANSFORMATION_RULE>oaf2dc_VHJhbnNmb3JtYXRpb25SdWxlRFNSZXNvdXJjZXMvVHJhbnNmb3JtYXRpb25SdWxlRFNSZXNvdXJjZVR5cGU=</TRANSFORMATION_RULE>
44
                    <BASE_QUERY>oaftype="result"</BASE_QUERY>
45
                </METADATAFORMAT>
46
            </METADATAFORMATS>
47
            <INDICES>
48
                <INDEX name="objIdentifier" repeatable="false">
49
                    <SOURCE name="oaf" layout="index" interpretation="openaire" path="//*[local-name() ='objIdentifier']"/>
50
                </INDEX>
51
                <INDEX name="set" repeatable="true">
52
                    <SOURCE name="oaf" layout="index" interpretation="openaire" path="//collectedfrom/@name"/>
53
                </INDEX>
54
                <INDEX name="publisher" repeatable="true">
55
                    <SOURCE name="oaf" layout="index" interpretation="openaire" path="//publisher"/>
56
                </INDEX>
57
                <INDEX name="license" repeatable="false">
58
                    <SOURCE name="oaf" layout="index" interpretation="openaire" path="//bestlicense/@classid"/>
59
                </INDEX>
60
                <INDEX name="oaftype" repeatable="false">
61
                    <SOURCE name="oaf" layout="index" interpretation="openaire" path="local-name(//*[local-name()='entity']/*)"/>
62
                </INDEX>
63
                <INDEX name="resulttypeid" repeatable="false">
64
                    <SOURCE name="oaf" layout="index" interpretation="openaire" path="//*[local-name()='entity']/*[local-name()='result']/resulttype/@classid"/>
65
                </INDEX>
66
            </INDICES>
67
        </CONFIGURATION>
68
		<STATUS>
69
			<LAST_UPDATE value="2001-12-31T12:00:00" />
70
		</STATUS>
71
		<SECURITY_PARAMETERS>SECURITY_PARAMETERS</SECURITY_PARAMETERS>
72
	</BODY>
73
</RESOURCE_PROFILE>
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/test/resources/eu/dnetlib/data/oai/store/mongo/MongoPublisherStoreDAOTest-context.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" xmlns:p="http://www.springframework.org/schema/p"
4
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5

  
6
	<bean id="mongodbPublisherStoreDao" class="eu.dnetlib.data.oai.store.mongo.MongoPublisherStoreDAO"
7
		p:metadataCollection="metadata" />
8

  
9
	<bean id="publisherMongoServer" class="com.mongodb.Mongo">
10
		<constructor-arg index="0" type="com.mongodb.ServerAddress">
11
			<bean class="com.mongodb.ServerAddress">
12
				<constructor-arg index="0" value="localhost" />
13
				<constructor-arg index="1" value="27017" />
14
			</bean>
15
		</constructor-arg>
16
	</bean>
17

  
18
	<bean id="mongoQueryParser" class="eu.dnetlib.data.oai.store.parser.MongoQueryParser" />
19

  
20
	<bean id="oaiISLookupClient" class="eu.dnetlib.data.information.oai.publisher.conf.ISLookUpClient" />
21

  
22
	<bean id="oaiConfigurationExistReader" class="eu.dnetlib.data.information.oai.publisher.conf.OAIConfigurationExistReader" p:idScheme="${services.oai.publisher.id.scheme}" p:idNamespace="${services.oai.publisher.id.namespace}" />
23

  
24
	<bean id="oaiConfigurationStringReader" class="eu.dnetlib.data.information.oai.publisher.conf.OAIConfigurationStringReader" p:idScheme="${services.oai.publisher.id.scheme}" p:idNamespace="${services.oai.publisher.id.namespace}" />
25

  
26
	<bean id="configurationParser" class="eu.dnetlib.data.information.oai.publisher.conf.OAIConfigurationParser" />
27

  
28
	<bean id="publisherConfigurationWriter" class="eu.dnetlib.data.information.oai.publisher.conf.OAIConfigurationWriter" />
29

  
30
	<bean id="queryExecutor" class="eu.dnetlib.enabling.tools.SplittedQueryExecutor"
31
		p:lookupLocator-ref="lookupLocator" />
32

  
33
	<bean id="lookupLocator" class="eu.dnetlib.enabling.tools.StaticServiceLocator">
34
		<property name="service">
35
			<bean class="eu.dnetlib.test.utils.MockBeanFactory" p:clazz="eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService" />
36
		</property>
37
	</bean>
38

  
39
	<bean id="recordInfoGenerator" class="eu.dnetlib.data.oai.store.mongo.RecordInfoGenerator" />
40

  
41
	<bean id="metadataExtractor" class="eu.dnetlib.data.oai.store.mongo.MetadataExtractor" />
42

  
43
	<bean id="recordChangeDetector" class="eu.dnetlib.data.oai.store.DummyRecordChangeDetector" />
44
	
45
	<bean id="mongoSetCollection" class="eu.dnetlib.data.oai.store.sets.MongoSetCollection" />
46
	
47
	<bean id="oaiSetHelper" class="eu.dnetlib.data.oai.store.conf.OAISetHelper"
48
		p:configurationReader-ref="oaiConfigurationExistReader"
49
		p:mongoSetCollection-ref="mongoSetCollection" />
50

  
51
	<bean id="oaiSetsCounter" class="eu.dnetlib.data.oai.store.conf.OAISetsCounter" />
52

  
53
</beans>
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/test/resources/log4j.properties
1
org.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger
2

  
3
log4j.rootLogger=WARN, CONSOLE
4
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
5
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
6
log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
7

  
8
log4j.logger.eu.dnetlib=INFO
9
log4j.logger.eu.dnetlib.data=DEBUG
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/main/java/eu/dnetlib/data/oai/store/mongo/RecordInfoGenerator.java
1
package eu.dnetlib.data.oai.store.mongo;
2

  
3
import java.io.StringReader;
4
import java.util.Date;
5
import java.util.List;
6

  
7
import javax.annotation.Resource;
8

  
9
import org.apache.commons.lang.StringEscapeUtils;
10
import org.dom4j.Document;
11
import org.dom4j.DocumentException;
12
import org.dom4j.io.SAXReader;
13

  
14
import com.google.common.collect.Sets;
15
import com.mongodb.DBObject;
16

  
17
import eu.dnetlib.data.information.oai.publisher.OaiPublisherRuntimeException;
18
import eu.dnetlib.data.information.oai.publisher.conf.OAIConfigurationReader;
19
import eu.dnetlib.data.information.oai.publisher.info.RecordInfo;
20

  
21
/**
22
 * Helper class to generate a RecordInfo object from a Mongo DBObject.
23
 * 
24
 * @author alessia
25
 * 
26
 */
27
public class RecordInfoGenerator {
28

  
29
	@Resource
30
	private MetadataExtractor metadataExtractor;
31

  
32
	@SuppressWarnings("unchecked")
33
	public RecordInfo transformDBObject(final DBObject object, final boolean includeBody) {
34
		String id = (String) object.get(OAIConfigurationReader.ID_FIELD);
35
		// need to escape the identifier, otherwise the XML breaks
36
		id = StringEscapeUtils.escapeXml(id);
37
		boolean deleted = (Boolean) object.get("deleted");
38
		RecordInfo record = new RecordInfo();
39
		record.setIdentifier(id);
40
		record.setInternalId(object.get("_id").toString());
41
		record.setDatestamp((Date) object.get(OAIConfigurationReader.DATESTAMP_FIELD));
42
		record.setDeleted(deleted);
43
		List<String> sets = (List<String>) object.get(OAIConfigurationReader.SET_FIELD);
44
		if (sets != null) {
45
			record.setSetspecs(Sets.newHashSet(sets));
46
		}
47
		if (includeBody && !deleted) {
48
			String body = (String) object.get(OAIConfigurationReader.BODY_FIELD);
49
			final SAXReader reader = new SAXReader();
50
			Document doc;
51
			try {
52
				doc = reader.read(new StringReader(body));
53
				record.setMetadata(this.metadataExtractor.evaluate(doc));
54

  
55
			} catch (DocumentException e) {
56
				throw new OaiPublisherRuntimeException(e);
57
			}
58
		}
59
		return record;
60

  
61
	}
62

  
63
	public MetadataExtractor getMetadataExtractor() {
64
		return metadataExtractor;
65
	}
66

  
67
	public void setMetadataExtractor(final MetadataExtractor metadataExtractor) {
68
		this.metadataExtractor = metadataExtractor;
69
	}
70

  
71
}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/main/java/eu/dnetlib/data/oai/store/mongo/MongoPublisherStore.java
1
package eu.dnetlib.data.oai.store.mongo;
2

  
3
import java.util.Collection;
4
import java.util.Date;
5
import java.util.List;
6
import java.util.concurrent.ArrayBlockingQueue;
7
import java.util.concurrent.BlockingQueue;
8
import java.util.concurrent.TimeUnit;
9

  
10
import org.apache.commons.lang.StringUtils;
11
import org.apache.commons.logging.Log;
12
import org.apache.commons.logging.LogFactory;
13

  
14
import com.google.common.base.Function;
15
import com.google.common.base.Predicate;
16
import com.google.common.base.Stopwatch;
17
import com.google.common.collect.Iterables;
18
import com.google.common.collect.Multimap;
19
import com.mongodb.BasicDBObject;
20
import com.mongodb.BasicDBObjectBuilder;
21
import com.mongodb.DBCollection;
22
import com.mongodb.DBCursor;
23
import com.mongodb.DBObject;
24
import com.mongodb.WriteResult;
25

  
26
import eu.dnetlib.data.information.oai.publisher.PublisherField;
27
import eu.dnetlib.data.information.oai.publisher.conf.OAIConfigurationReader;
28
import eu.dnetlib.data.information.oai.publisher.info.RecordInfo;
29
import eu.dnetlib.data.information.oai.publisher.info.SetInfo;
30
import eu.dnetlib.data.oai.store.PublisherStore;
31
import eu.dnetlib.data.oai.store.RecordChangeDetector;
32
import eu.dnetlib.data.oai.store.parser.MongoQueryParser;
33
import eu.dnetlib.data.oai.store.parser.PublisherRecordParser;
34
import eu.dnetlib.data.oai.store.sets.MongoSetCollection;
35
import eu.dnetlib.miscutils.functional.UnaryFunction;
36

  
37
public class MongoPublisherStore implements PublisherStore<MongoCursor> {
38

  
39
	private static final Log log = LogFactory.getLog(MongoPublisherStore.class); // NOPMD by marko on 11/24/08 5:02 PM
40

  
41
	private String id, metadataFormat, interpretation, layout;
42
	/** Keeps information about the fields to be created in mongo. **/
43
	private List<PublisherField> mongoFields;
44

  
45
	private DBCollection collection;
46
	private DBCollection discardedCollection;
47

  
48
	private RecordInfoGenerator recordInfoGenerator;
49
	private MetadataExtractor metadataExtractor;
50

  
51
	private MongoQueryParser queryParser;
52

  
53
	private RecordChangeDetector recordChangeDetector;
54

  
55
	private MongoSetCollection mongoSetCollection;
56

  
57
	/**
58
	 * Used to generate the OAI identifiers compliant to the protocol. See
59
	 * http://www.openarchives.org/OAI/openarchivesprotocol.html#UniqueIdentifier. See property services.oai.publisher.id.scheme.
60
	 */
61
	private String idScheme;
62
	/**
63
	 * Used to generate the OAI identifiers compliant to the protocol. See
64
	 * http://www.openarchives.org/OAI/openarchivesprotocol.html#UniqueIdentifier. See property services.oai.publisher.id.namespace.
65
	 */
66
	private String idNamespace;
67

  
68
	@Override
69
	public RecordInfo getRecord(final String recordId) {
70
		DBObject query = new BasicDBObject(OAIConfigurationReader.ID_FIELD, recordId);
71
		DBObject result = this.collection.findOne(query);
72
		log.debug(result);
73
		return this.recordInfoGenerator.transformDBObject(result, true);
74
	}
75

  
76
	@Override
77
	public RecordInfo getRecord(final String recordId, final UnaryFunction<String, String> unaryFunction) {
78
		RecordInfo result = this.getRecord(recordId);
79
		if (result != null) {
80
			String transformedBody = unaryFunction.evaluate(result.getMetadata());
81
			result.setMetadata(transformedBody);
82
		}
83
		return result;
84
	}
85

  
86
	@Override
87
	public MongoCursor getRecords(final String queryString, final boolean bodyIncluded, final int limit) {
88
		DBCursor cursor = loggedFindByQuery(queryString, limit);
89
		return new MongoCursor(cursor, bodyIncluded, this.recordInfoGenerator, this.metadataExtractor);
90
	}
91

  
92
	@Override
93
	public MongoCursor getRecords(final String queryString, final UnaryFunction<String, String> unaryFunction, final boolean bodyIncluded, final int limit) {
94
		DBCursor cursor = loggedFindByQuery(queryString, limit);
95
		return new MongoCursor(cursor, unaryFunction, bodyIncluded, this.recordInfoGenerator, this.metadataExtractor);
96
	}
97

  
98
	private DBCursor loggedFindByQuery(final String queryString, final int limit) {
99
		DBObject query = this.queryParser.parse(queryString);
100
		long start = System.currentTimeMillis();
101
		DBCursor cursor = this.collection.find(query).sort(new BasicDBObject("_id", 1)).limit(limit);
102
		long end = System.currentTimeMillis();
103
		log.debug("Query:" + query + "\ntime to get mongo cursor (ms): " + (end - start));
104
		return cursor;
105
	}
106

  
107
	@Override
108
	public List<PublisherField> getIndices() {
109
		return this.mongoFields;
110
	}
111

  
112
	/**
113
	 * <p>
114
	 * Ensure indices on the configuration-defined fields and on the system fields DATESTAMP_FIELD and LAST_COLLECTION_DATE_FIELD.
115
	 * <p>
116
	 * <p>
117
	 * Note that by default ID_FIELD, SET_FIELD, DELETED_FIELD, BODY_FIELD, UPDATED_FIELD are not indexed. If you want an index on those,
118
	 * then you have to specify it in the configuration file of the OAI Publisher: <br>
119
	 * <INDEX name="deleted">
120
	 * </p>
121
	 * 
122
	 * {@inheritDoc}
123
	 * 
124
	 * @see eu.dnetlib.data.information.oai.publisher.store.PublisherStore#ensureIndices()
125
	 */
126
	@Override
127
	public void ensureIndices() {
128
		List<DBObject> list = this.collection.getIndexInfo();
129
		this.collection.resetIndexCache();
130
		Stopwatch sw = new Stopwatch();
131
		sw.start();
132
		// I want to keep the composite indexes that might have been defined manually
133
		log.debug("Ensuring currently defined composite indexes:");
134
		DBObject indexOptions = new BasicDBObject("background", true);
135
		for (DBObject o : list) {
136
			DBObject fieldIndexed = (DBObject) o.get("key");
137
			if (fieldIndexed.keySet().size() > 1) {
138
				log.debug(o);
139
				this.collection.ensureIndex(fieldIndexed, indexOptions);
140
			}
141
		}
142
		// Indexes on single fields.
143
		for (PublisherField field : this.mongoFields) {
144
			DBObject mongoIdx = new BasicDBObject(field.getFieldName(), 1);
145
			log.debug("Creating index : " + mongoIdx);
146
			this.collection.ensureIndex(mongoIdx, indexOptions);
147
		}
148
		log.debug("Creating index over : " + OAIConfigurationReader.DATESTAMP_FIELD);
149
		this.collection.ensureIndex(new BasicDBObject(OAIConfigurationReader.DATESTAMP_FIELD, 1));
150
		log.debug("Creating index over : " + OAIConfigurationReader.LAST_COLLECTION_DATE_FIELD);
151
		this.collection.ensureIndex(new BasicDBObject(OAIConfigurationReader.LAST_COLLECTION_DATE_FIELD, 1));
152
		sw.stop();
153
		log.info("All indexes have been updated in " + sw.elapsed(TimeUnit.MILLISECONDS) + " milliseconds");
154
	}
155

  
156
	/**
157
	 * Creates a compound index over the specified fields on the given store.
158
	 * <p>
159
	 * The creation is performed on the background
160
	 * </p>
161
	 * 
162
	 * @param fieldNames
163
	 *            List of fields to be included in the compound index
164
	 * @theStore MongoPublisherStore where to create the index
165
	 */
166
	public void createCompoundIndex(final List<String> fieldNames) {
167
		if ((fieldNames == null) || fieldNames.isEmpty()) {
168
			log.fatal("No fields specified for the creation of the compound index");
169
		}
170
		DBObject indexOptions = new BasicDBObject("background", true);
171
		BasicDBObjectBuilder theIndexBuilder = BasicDBObjectBuilder.start();
172
		for (String f : fieldNames) {
173
			theIndexBuilder.add(f, 1);
174
		}
175
		DBObject theIndex = theIndexBuilder.get();
176
		log.info("Creating index " + theIndex + " on " + this.getId());
177
		this.getCollection().ensureIndex(theIndex, indexOptions);
178
	}
179

  
180
	private void dropDiscarded(final String source) {
181
		if (StringUtils.isBlank(source)) {
182
			log.debug("Dropping discarded records from publisherStore " + id);
183
			discardedCollection.drop();
184
		} else {
185
			log.debug("Dropping discarded records for source " + source + " from publisherStore " + id);
186
			discardedCollection.remove(new BasicDBObject(OAIConfigurationReader.SET_FIELD, source));
187
		}
188
	}
189

  
190
	@Override
191
	public int feed(final Iterable<String> records, final String source) {
192
		final BlockingQueue<Object> queue = new ArrayBlockingQueue<Object>(80);
193
		final Object sentinel = new Object();
194
		this.dropDiscarded(source);
195
		final Date feedDate = new Date();
196
		Thread background = new Thread(new Runnable() {
197

  
198
			@Override
199
			public void run() {
200
				while (true) {
201
					try {
202
						Object record = queue.take();
203
						if (record == sentinel) {
204
							break;
205
						}
206
						safeFeedRecord((String) record, source, feedDate);
207
					} catch (InterruptedException e) {
208
						log.fatal("got exception in background thread", e);
209
						throw new IllegalStateException(e);
210
					}
211
				}
212
			}
213
		});
214
		background.start();
215
		long startFeed = feedDate.getTime();
216
		try {
217
			log.info("feeding publisherStore " + id);
218
			for (final String record : records) {
219
				queue.put(record);
220
			}
221
			queue.put(sentinel);
222
			log.info("finished feeding publisherStore " + id);
223

  
224
			background.join();
225
		} catch (InterruptedException e) {
226
			throw new IllegalStateException(e);
227
		}
228
		long endFeed = System.currentTimeMillis();
229
		log.fatal("OAI STORE " + id + " FEEDING COMPLETED IN " + (endFeed - startFeed) + "ms");
230
		this.setDeletedFlags(feedDate, source);
231
		return this.count();
232
	}
233

  
234
	/**
235
	 * Launches the thread that flags the records to be considered as 'deleted'.
236
	 * <p>
237
	 * The datestamp of the deleted records must be updated as well, according to the OAI specs available at
238
	 * http://www.openarchives.org/OAI/openarchivesprotocol.html#DeletedRecords: if a repository does keep track of deletions then the
239
	 * datestamp of the deleted record must be the date and time that it was deleted.
240
	 * </p>
241
	 * 
242
	 * @param feedDate
243
	 * @param source
244
	 */
245
	private void setDeletedFlags(final Date feedDate, final String source) {
246
		Thread deletedSetter = new Thread(new Runnable() {
247

  
248
			@Override
249
			public void run() {
250
				DBObject query = BasicDBObjectBuilder.start(OAIConfigurationReader.DELETED_FIELD, false)
251
						.append(OAIConfigurationReader.LAST_COLLECTION_DATE_FIELD, new BasicDBObject("$lt", feedDate)).get();
252
				if (!StringUtils.isBlank(source)) {
253
					query.put(OAIConfigurationReader.SET_FIELD, source);
254
				}
255
				log.debug("Delete flag query: " + query.toString());
256
				DBObject update = new BasicDBObject("$set", BasicDBObjectBuilder.start(OAIConfigurationReader.DELETED_FIELD, true)
257
						.append(OAIConfigurationReader.DATESTAMP_FIELD, feedDate).append(OAIConfigurationReader.UPDATED_FIELD, true).get());
258
				log.debug("Updating as: " + update.toString());
259
				WriteResult wr = collection.update(query, update, false, true);
260
				log.debug("Deleted flags set for source: " + source + " #records = " + wr.getN());
261
			}
262
		});
263

  
264
		deletedSetter.start();
265
		try {
266
			deletedSetter.join();
267
		} catch (InterruptedException e) {
268
			throw new IllegalStateException(e);
269
		}
270
	}
271

  
272
	@Override
273
	public void drop() {
274
		this.collection.drop();
275
	}
276

  
277
	@Override
278
	public void drop(final String queryString) {
279
		DBObject query = this.queryParser.parse(queryString);
280
		this.collection.remove(query);
281
	}
282

  
283
	@Override
284
	public int count() {
285
		return (int) this.collection.count();
286
	}
287

  
288
	@Override
289
	public int count(final String queryString) {
290
		if (StringUtils.isBlank(queryString)) return (int) this.collection.count();
291
		DBObject query = this.queryParser.parse(queryString);
292
		return (int) this.collection.count(query);
293
	}
294

  
295
	public List<String> getDistinctSetNamesFromRecords() {
296
		log.info("Going to ask for all distinct sets in the oaistore " + id + ": this may take a long time...");
297
		@SuppressWarnings("unchecked")
298
		List<String> distinctSets = this.collection.distinct(OAIConfigurationReader.SET_FIELD);
299
		return distinctSets;
300
	}
301

  
302
	// ***********************************************************************************************//
303
	// Feed utilities
304
	// ***********************************************************************************************//
305
	private boolean safeFeedRecord(final String record, final String source, final Date feedDate) {
306
		try {
307
			if (!record.isEmpty()) return feedRecord(record, source, feedDate);
308
		} catch (final Throwable e) {
309
			log.error("Got unhandled exception while parsing record", e);
310
			discardedCollection.insert(new BasicDBObject(OAIConfigurationReader.SET_FIELD, source).append(OAIConfigurationReader.BODY_FIELD, record));
311
		}
312
		return false;
313
	}
314

  
315
	/**
316
	 * Feed the record to the store.
317
	 * 
318
	 * @return true if the record is new, false otherwise
319
	 */
320
	private boolean feedRecord(final String record, final String source, final Date feedDate) {
321
		PublisherRecordParser parser = new PublisherRecordParser(this.mongoFields);
322
		final Multimap<String, String> recordProperties = parser.parseRecord(record);
323
		String id = "";
324
		String oaiID = "";
325
		if (recordProperties.containsKey(OAIConfigurationReader.ID_FIELD)) {
326
			id = recordProperties.get(OAIConfigurationReader.ID_FIELD).iterator().next();
327
			oaiID = getOAIIdentifier(id);
328
			if (isNewRecord(oaiID)) {
329
				feedNew(oaiID, record, recordProperties, feedDate);
330
				return true;
331
			} else {
332
				if (isChanged(oaiID, record)) {
333
					updateRecord(oaiID, record, recordProperties, feedDate);
334
				} else {
335
					// it is not changed, I only have to update the last collection date
336
					handleRecord(oaiID, feedDate);
337
				}
338
			}
339
		} else {
340
			log.error("parsed record seems invalid -- no identifier property with name: " + OAIConfigurationReader.ID_FIELD);
341
			discardedCollection.insert(new BasicDBObject(OAIConfigurationReader.SET_FIELD, source).append(OAIConfigurationReader.BODY_FIELD, record).append(
342
					OAIConfigurationReader.DATESTAMP_FIELD, feedDate));
343
		}
344
		return false;
345
	}
346

  
347
	private DBObject createBasicObject(final String oaiID, final String record, final Multimap<String, String> recordProperties) {
348
		DBObject obj = new BasicDBObject();
349
		for (final String key : recordProperties.keySet()) {
350
			if (key.equals(OAIConfigurationReader.ID_FIELD)) {
351
				obj.put(key, oaiID);
352
			} else {
353
				Collection<String> values = recordProperties.get(key);
354
				if (key.equals(OAIConfigurationReader.SET_FIELD)) {
355

  
356
					Iterable<String> setSpecs = Iterables.transform(values, new Function<String, String>() {
357

  
358
						@Override
359
						public String apply(final String s) {
360
							return mongoSetCollection.normalizeSetSpec(s);
361
						}
362

  
363
					});
364
					obj.put(key, setSpecs);
365
				} else {
366
					// let's check if the key is the name of a repeatable field or not
367
					PublisherField keyField = Iterables.find(this.mongoFields, new Predicate<PublisherField>() {
368

  
369
						@Override
370
						public boolean apply(final PublisherField field) {
371
							return field.getFieldName().equals(key);
372
						}
373
					}, null);
374
					if (keyField == null) {
375
						log.warn("Expected field to index: " + key + " could not be found, but we keep going...");
376
					}
377
					if ((keyField != null) && !keyField.isRepeatable()) {
378
						if ((values != null) && !values.isEmpty()) {
379
							obj.put(key, values.iterator().next());
380
						}
381
					} else {
382
						obj.put(key, values);
383
					}
384
				}
385
			}
386
		}
387
		obj.put(OAIConfigurationReader.BODY_FIELD, record);
388
		obj.put(OAIConfigurationReader.DELETED_FIELD, false);
389
		return obj;
390
	}
391

  
392
	private void feedNew(final String oaiID, final String record, final Multimap<String, String> recordProperties, final Date feedDate) {
393
		log.debug("New record received. Assigned oai id: " + oaiID);
394
		DBObject obj = this.createBasicObject(oaiID, record, recordProperties);
395
		obj.put(OAIConfigurationReader.LAST_COLLECTION_DATE_FIELD, feedDate);
396
		obj.put(OAIConfigurationReader.DATESTAMP_FIELD, feedDate);
397
		obj.put(OAIConfigurationReader.UPDATED_FIELD, false);
398
		collection.insert(obj);
399
		this.upsertSets(recordProperties.get(OAIConfigurationReader.SET_FIELD));
400
	}
401

  
402
	private void updateRecord(final String oaiID, final String record, final Multimap<String, String> recordProperties, final Date feedDate) {
403
		log.debug("updating record " + oaiID);
404
		DBObject obj = this.createBasicObject(oaiID, record, recordProperties);
405
		obj.put(OAIConfigurationReader.LAST_COLLECTION_DATE_FIELD, feedDate);
406
		obj.put(OAIConfigurationReader.DATESTAMP_FIELD, feedDate);
407
		obj.put(OAIConfigurationReader.UPDATED_FIELD, true);
408
		DBObject oldObj = new BasicDBObject(OAIConfigurationReader.ID_FIELD, oaiID);
409
		collection.update(oldObj, obj, true, false);
410
		this.upsertSets(recordProperties.get(OAIConfigurationReader.SET_FIELD));
411
	}
412

  
413
	public void upsertSets(final Iterable<String> setNames) {
414
		// feed the list of sets, if any
415
		if (setNames != null) {
416
			for (String setName : setNames) {
417
				if (StringUtils.isNotBlank(setName)) {
418
					final SetInfo set = new SetInfo();
419
					String setSpec = this.mongoSetCollection.normalizeSetSpec(setName);
420
					set.setSetSpec(setSpec);
421
					set.setSetName(setName);
422
					set.setSetDescription("This set contains metadata records whose provenance is " + setName);
423
					set.setEnabled(true);
424
					String query = "(" + OAIConfigurationReader.SET_FIELD + " = \"" + setSpec + "\") ";
425
					set.setQuery(query);
426
					this.mongoSetCollection.upsertSet(set, false, getCollection().getDB().getName());
427
				}
428
			}
429
		}
430
	}
431

  
432
	private void handleRecord(final String oaiID, final Date lastCollectionDate) {
433
		log.debug("handling unchanged record " + oaiID);
434
		DBObject oldObj = new BasicDBObject(OAIConfigurationReader.ID_FIELD, oaiID);
435
		DBObject update = new BasicDBObject("$set", new BasicDBObject(OAIConfigurationReader.LAST_COLLECTION_DATE_FIELD, lastCollectionDate));
436
		collection.update(oldObj, update, true, false);
437
	}
438

  
439
	private boolean isNewRecord(final String oaiIdentifier) {
440
		return this.collection.findOne(new BasicDBObject(OAIConfigurationReader.ID_FIELD, oaiIdentifier)) == null;
441
	}
442

  
443
	private boolean isChanged(final String oaiID, final String record) {
444
		RecordInfo oldRecord = getRecord(oaiID);
445
		return this.recordChangeDetector.differs(oldRecord.getMetadata(), record);
446
	}
447

  
448
	private String getOAIIdentifier(final String id) {
449
		return this.idScheme + ":" + this.idNamespace + ":" + id;
450
	}
451

  
452
	// ***********************************************************************************************//
453
	// Setters / Getters / Basic utilities
454
	// ***********************************************************************************************//
455

  
456
	@Override
457
	public int hashCode() {
458
		final int prime = 31;
459
		int result = 1;
460
		result = (prime * result) + ((collection == null) ? 0 : collection.hashCode());
461
		result = (prime * result) + ((id == null) ? 0 : id.hashCode());
462
		result = (prime * result) + ((interpretation == null) ? 0 : interpretation.hashCode());
463
		result = (prime * result) + ((layout == null) ? 0 : layout.hashCode());
464
		result = (prime * result) + ((metadataFormat == null) ? 0 : metadataFormat.hashCode());
465
		return result;
466
	}
467

  
468
	@Override
469
	public boolean equals(final Object obj) {
470
		if (this == obj) return true;
471
		if (obj == null) return false;
472
		if (!(obj instanceof MongoPublisherStore)) return false;
473
		MongoPublisherStore other = (MongoPublisherStore) obj;
474
		if (collection == null) {
475
			if (other.collection != null) return false;
476
		} else if (!collection.equals(other.collection)) return false;
477
		if (id == null) {
478
			if (other.id != null) return false;
479
		} else if (!id.equals(other.id)) return false;
480
		if (interpretation == null) {
481
			if (other.interpretation != null) return false;
482
		} else if (!interpretation.equals(other.interpretation)) return false;
483
		if (layout == null) {
484
			if (other.layout != null) return false;
485
		} else if (!layout.equals(other.layout)) return false;
486
		if (metadataFormat == null) {
487
			if (other.metadataFormat != null) return false;
488
		} else if (!metadataFormat.equals(other.metadataFormat)) return false;
489
		return true;
490
	}
491

  
492
	public MongoPublisherStore() {
493
		super();
494
	}
495

  
496
	public MongoPublisherStore(final String id, final String metadataFormat, final String interpretation, final String layout, final DBCollection collection,
497
			final List<PublisherField> mongoFields, final MongoQueryParser queryParser, final RecordInfoGenerator recordInfoGenerator, final String idScheme,
498
			final String idNamespace, final MetadataExtractor metadataExtractor, final RecordChangeDetector recordChangeDetector) {
499
		super();
500
		this.id = id;
501
		this.metadataFormat = metadataFormat;
502
		this.interpretation = interpretation;
503
		this.layout = layout;
504
		this.collection = collection;
505
		this.discardedCollection = collection.getDB().getCollection("discarded-" + collection.getName());
506
		this.mongoFields = mongoFields;
507
		this.queryParser = queryParser;
508
		this.recordInfoGenerator = recordInfoGenerator;
509
		this.idScheme = idScheme;
510
		this.idNamespace = idNamespace;
511
		this.recordChangeDetector = recordChangeDetector;
512
	}
513

  
514
	public void setId(final String id) {
515
		this.id = id;
516
	}
517

  
518
	public void setMetadataFormat(final String metadataFormat) {
519
		this.metadataFormat = metadataFormat;
520
	}
521

  
522
	public void setInterpretation(final String interpretation) {
523
		this.interpretation = interpretation;
524
	}
525

  
526
	public void setLayout(final String layout) {
527
		this.layout = layout;
528
	}
529

  
530
	public DBCollection getCollection() {
531
		return collection;
532
	}
533

  
534
	public void setCollection(final DBCollection collection) {
535
		this.collection = collection;
536
	}
537

  
538
	public MongoQueryParser getQueryParser() {
539
		return queryParser;
540
	}
541

  
542
	public void setQueryParser(final MongoQueryParser queryParser) {
543
		this.queryParser = queryParser;
544
	}
545

  
546
	public DBCollection getDiscardedCollection() {
547
		return discardedCollection;
548
	}
549

  
550
	public void setDiscardedCollection(final DBCollection discardedCollection) {
551
		this.discardedCollection = discardedCollection;
552
	}
553

  
554
	public String getIdScheme() {
555
		return idScheme;
556
	}
557

  
558
	public void setIdScheme(final String idScheme) {
559
		this.idScheme = idScheme;
560
	}
561

  
562
	public String getIdNamespace() {
563
		return idNamespace;
564
	}
565

  
566
	public void setIdNamespace(final String idNamespace) {
567
		this.idNamespace = idNamespace;
568
	}
569

  
570
	public RecordInfoGenerator getRecordInfoGenerator() {
571
		return recordInfoGenerator;
572
	}
573

  
574
	public void setRecordInfoGenerator(final RecordInfoGenerator recordInfoGenerator) {
575
		this.recordInfoGenerator = recordInfoGenerator;
576
	}
577

  
578
	public MetadataExtractor getMetadataExtractor() {
579
		return metadataExtractor;
580
	}
581

  
582
	public void setMetadataExtractor(final MetadataExtractor metadataExtractor) {
583
		this.metadataExtractor = metadataExtractor;
584
	}
585

  
586
	public RecordChangeDetector getRecordChangeDetector() {
587
		return recordChangeDetector;
588
	}
589

  
590
	public void setRecordChangeDetector(final RecordChangeDetector recordChangeDetector) {
591
		this.recordChangeDetector = recordChangeDetector;
592
	}
593

  
594
	@Override
595
	public String getId() {
596
		return this.id;
597
	}
598

  
599
	@Override
600
	public String getMetadataFormat() {
601
		return this.metadataFormat;
602
	}
603

  
604
	@Override
605
	public String getInterpretation() {
606
		return this.interpretation;
607
	}
608

  
609
	@Override
610
	public String getLayout() {
611
		return this.layout;
612
	}
613

  
614
	public MongoSetCollection getMongoSetCollection() {
615
		return mongoSetCollection;
616
	}
617

  
618
	public void setMongoSetCollection(final MongoSetCollection mongoSetCollection) {
619
		this.mongoSetCollection = mongoSetCollection;
620
	}
621

  
622
	public List<PublisherField> getMongoFields() {
623
		return mongoFields;
624
	}
625

  
626
	public void setMongoFields(final List<PublisherField> mongoFields) {
627
		this.mongoFields = mongoFields;
628
	}
629

  
630
}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/main/java/eu/dnetlib/data/oai/store/mongo/MetadataExtractor.java
1
package eu.dnetlib.data.oai.store.mongo;
2

  
3
import org.dom4j.Document;
4
import org.dom4j.Node;
5

  
6
import eu.dnetlib.miscutils.functional.UnaryFunction;
7

  
8
/**
9
 * Function to skip the header of the record and deliver only its metadata content as XML String.
10
 */
11
public class MetadataExtractor implements UnaryFunction<String, Document> {
12

  
13
	@Override
14
	public String evaluate(final Document xmlDoc) {
15
		Node metadataNode = xmlDoc.selectSingleNode("//*[local-name() = 'metadata']/*");
16
		return metadataNode.asXML();
17
	}
18
}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/main/java/eu/dnetlib/data/oai/store/mongo/MongoCursor.java
1
package eu.dnetlib.data.oai.store.mongo;
2

  
3
import java.util.Iterator;
4

  
5
import com.mongodb.DBCursor;
6
import com.mongodb.DBObject;
7

  
8
import eu.dnetlib.data.information.oai.publisher.info.RecordInfo;
9
import eu.dnetlib.data.oai.store.Cursor;
10
import eu.dnetlib.miscutils.functional.UnaryFunction;
11

  
12
public class MongoCursor implements Cursor {
13

  
14
	/**
15
	 * Underlying mongo cursor.
16
	 */
17
	private DBCursor dbCursor;
18
	/**
19
	 * Function to apply to records before delivering.
20
	 */
21
	private UnaryFunction<String, String> function;
22

  
23
	/**
24
	 * true if the RecordInfo returned by this Cursor must include the record body, false otherwise.
25
	 */
26
	private boolean bodyIncluded;
27

  
28
	private RecordInfoGenerator recordInfoGenerator;
29
	private MetadataExtractor metadataExtractor;
30

  
31
	/**
32
	 * 
33
	 * {@inheritDoc}
34
	 * 
35
	 * @see eu.dnetlib.data.information.oai.publisher.store.Cursor#count()
36
	 */
37
	@Override
38
	public int count() {
39
		return this.dbCursor.count();
40
	}
41

  
42
	/**
43
	 * 
44
	 * {@inheritDoc}
45
	 * 
46
	 * @see java.lang.Iterable#iterator()
47
	 */
48
	@Override
49
	public Iterator<RecordInfo> iterator() {
50

  
51
		return new Iterator<RecordInfo>() {
52

  
53
			@Override
54
			public boolean hasNext() {
55
				return dbCursor.hasNext();
56
			}
57

  
58
			@Override
59
			public RecordInfo next() {
60
				DBObject res = dbCursor.next();
61
				RecordInfo info = recordInfoGenerator.transformDBObject(res, bodyIncluded);
62
				if ((function != null) && bodyIncluded) {
63
					info.setMetadata(function.evaluate(info.getMetadata()));
64
				}
65
				return info;
66
			}
67

  
68
			@Override
69
			public void remove() {
70
				throw new UnsupportedOperationException();
71
			}
72

  
73
		};
74
	}
75

  
76
	public MongoCursor() {
77
		super();
78
	}
79

  
80
	public MongoCursor(final DBCursor dbCursor, final boolean bodyIncluded, final RecordInfoGenerator recordInfoGenerator,
81
			final MetadataExtractor metadataExtractor) {
82
		this(dbCursor, null, bodyIncluded, recordInfoGenerator, metadataExtractor);
83
	}
84

  
85
	public MongoCursor(final DBCursor dbCursor, final UnaryFunction<String, String> function, final boolean bodyIncluded,
86
			final RecordInfoGenerator recordInfoGenerator, final MetadataExtractor metadataExtractor) {
87
		super();
88
		this.dbCursor = dbCursor;
89
		this.function = function;
90
		this.bodyIncluded = bodyIncluded;
91
		this.recordInfoGenerator = recordInfoGenerator;
92
		this.metadataExtractor = metadataExtractor;
93
	}
94

  
95
	public UnaryFunction<String, String> getFunction() {
96
		return function;
97
	}
98

  
99
	public void setFunction(final UnaryFunction<String, String> function) {
100
		this.function = function;
101
	}
102

  
103
	public DBCursor getDbCursor() {
104
		return dbCursor;
105
	}
106

  
107
	public void setDbCursor(final DBCursor dbCursor) {
108
		this.dbCursor = dbCursor;
109
	}
110

  
111
	@Override
112
	public boolean isBodyIncluded() {
113
		return this.bodyIncluded;
114
	}
115

  
116
	@Override
117
	public void setBodyIncluded(final boolean bodyIncluded) {
118
		this.bodyIncluded = bodyIncluded;
119
	}
120

  
121
	public RecordInfoGenerator getRecordInfoGenerator() {
122
		return recordInfoGenerator;
123
	}
124

  
125
	public void setRecordInfoGenerator(final RecordInfoGenerator recordInfoGenerator) {
126
		this.recordInfoGenerator = recordInfoGenerator;
127
	}
128

  
129
	public MetadataExtractor getMetadataExtractor() {
130
		return metadataExtractor;
131
	}
132

  
133
	public void setMetadataExtractor(final MetadataExtractor metadataExtractor) {
134
		this.metadataExtractor = metadataExtractor;
135
	}
136

  
137
}
modules/dnet-oai-store-service/tags/dnet-oai-store-service-4.0.0/src/main/java/eu/dnetlib/data/oai/store/mongo/MongoPublisherStoreDAO.java
1
package eu.dnetlib.data.oai.store.mongo;
2

  
3
import java.util.List;
4

  
5
import javax.annotation.Resource;
6

  
7
import org.springframework.beans.factory.annotation.Autowired;
8
import org.springframework.beans.factory.annotation.Required;
9

  
10
import com.google.common.collect.Lists;
11
import com.mongodb.BasicDBObject;
12
import com.mongodb.BasicDBObjectBuilder;
13
import com.mongodb.DB;
14
import com.mongodb.DBCollection;
15
import com.mongodb.DBCursor;
16
import com.mongodb.DBObject;
17
import com.mongodb.Mongo;
18

  
19
import eu.dnetlib.data.information.oai.publisher.OaiPublisherException;
20
import eu.dnetlib.data.information.oai.publisher.OaiPublisherRuntimeException;
21
import eu.dnetlib.data.information.oai.publisher.conf.OAIConfigurationReader;
22
import eu.dnetlib.data.information.oai.publisher.info.MDFInfo;
23
import eu.dnetlib.data.oai.store.PublisherStoreDAO;
24
import eu.dnetlib.data.oai.store.RecordChangeDetector;
25
import eu.dnetlib.data.oai.store.parser.MongoQueryParser;
26
import eu.dnetlib.data.oai.store.sets.MongoSetCollection;
27

  
28
public class MongoPublisherStoreDAO implements PublisherStoreDAO<MongoPublisherStore, MongoCursor> {
29

  
30
	@Autowired
31
	private Mongo publisherMongoServer;
32

  
33
	/** Name of the collection with information about the OAI stores. **/
34
	private String metadataCollection;
35

  
36
	@Resource
37
	private RecordInfoGenerator recordInfoGenerator;
38
	@Resource
39
	private MetadataExtractor metadataExtractor;
40
	@Resource
41
	private MongoQueryParser queryParser;
42
	@Resource(name = "oaiConfigurationExistReader")
43
	private OAIConfigurationReader configuration;
44
	@Resource
45
	private RecordChangeDetector recordChangeDetector;
46
	@Resource
47
	private MongoSetCollection mongoSetCollection;
48

  
49
	protected DB getDB(final String dbName) {
50
		return this.publisherMongoServer.getDB(dbName);
51
	}
52

  
53
	@Override
54
	public List<MongoPublisherStore> listPublisherStores(final String dbName) {
55
		List<MongoPublisherStore> stores = Lists.newArrayList();
56
		DB db = getDB(dbName);
57
		DBCursor cursor = db.getCollection(this.metadataCollection).find();
58
		for (DBObject storeInfo : cursor) {
59
			stores.add(this.createFromDBObject(storeInfo, db));
60
		}
61
		return stores;
62
	}
63

  
64
	@Override
65
	public MongoPublisherStore getStore(final String storeId, final String dbName) {
66
		DBObject storeInfo = getDB(dbName).getCollection(this.metadataCollection).findOne(new BasicDBObject("id", storeId));
67
		return this.createFromDBObject(storeInfo, getDB(dbName));
68
	}
69

  
70
	@Override
71
	public MongoPublisherStore getStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName) {
72
		return this.getStore(this.generateStoreId(mdfName, mdfInterpretation, mdfLayout), dbName);
73
	}
74

  
75
	@Override
76
	public MongoPublisherStore getStoreFor(final String targetMetadataPrefix, final String dbName) {
77
		MDFInfo info = this.configuration.getMetadataFormatInfo(targetMetadataPrefix);
78
		return this.getStore(info.getSourceFormatName(), info.getSourceFormatInterpretation(), info.getSourceFormatLayout(), dbName);
79
	}
80

  
81
	@Override
82
	public MongoPublisherStore createStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName)
83
			throws OaiPublisherException {
84
		DB db = getDB(dbName);
85
		DBObject store = createMetadataEntry(mdfName, mdfInterpretation, mdfLayout);
86
		DBCollection metadata = db.getCollection(this.metadataCollection);
87
		metadata.insert(store);
88
		MongoPublisherStore theStore = this.createFromDBObject(store, db);
89
		return theStore;
90

  
91
	}
92

  
93
	@Override
94
	public boolean deleteStore(final String storeId, final String dbName) {
95
		DB db = getDB(dbName);
96
		DBCollection metadata = db.getCollection(this.metadataCollection);
97
		DBObject storeInfo = metadata.findOne(new BasicDBObject("id", storeId));
98
		if (storeInfo == null) return false;
99
		else {
100
			db.getCollection(storeId).drop();
101
			metadata.remove(storeInfo);
102
			// TODO: should drop entries related to mdPrefix served by the store we are deleting, not all of them.
103
			this.mongoSetCollection.dropOAISets(dbName);
104
			return true;
105
		}
106
	}
107

  
108
	@Override
109
	public boolean deleteStore(final String mdfName, final String mdfInterpretation, final String mdfLayout, final String dbName) {
110
		return this.deleteStore(this.generateStoreId(mdfName, mdfInterpretation, mdfLayout), dbName);
111
	}
112

  
113
	public void ensureIndex(final MongoPublisherStore store) {
114
		if (store == null) throw new OaiPublisherRuntimeException("Can't ensure index on null store");
115
		Thread t = new Thread() {
116

  
117
			@Override
118
			public void run() {
119
				store.ensureIndices();
120
			}
121
		};
122
		t.start();
123
	}
124

  
125
	public void ensureIndex(final String dbName) {
126
		List<MongoPublisherStore> stores = this.listPublisherStores(dbName);
127
		for (final MongoPublisherStore s : stores) {
128
			s.ensureIndices();
129
		}
130

  
131
	}
132

  
133
	private MongoPublisherStore createFromDBObject(final DBObject storeInfo, final DB db) {
134
		if (storeInfo == null) return null;
135
		String storeId = (String) storeInfo.get("id");
136
		String mdFormat = (String) storeInfo.get("metadataFormat");
137
		String mdInterpreation = (String) storeInfo.get("interpretation");
138
		String mdLayout = (String) storeInfo.get("layout");
139

  
140
		MongoPublisherStore store = new MongoPublisherStore(storeId, mdFormat, mdInterpreation, mdLayout, db.getCollection(storeId),
141
				this.configuration.getFields(mdFormat, mdInterpreation, mdLayout), queryParser, recordInfoGenerator, this.configuration.getIdScheme(),
142
				this.configuration.getIdNamespace(), this.metadataExtractor, this.recordChangeDetector);
143
		store.setMongoSetCollection(mongoSetCollection);
144
		return store;
145
	}
146

  
147
	private DBObject createMetadataEntry(final String mdfName, final String mdfInterpretation, final String mdfLayout) {
148
		DBObject info = BasicDBObjectBuilder.start("id", generateStoreId(mdfName, mdfInterpretation, mdfLayout)).append("metadataFormat", mdfName)
149
				.append("interpretation", mdfInterpretation).append("layout", mdfLayout).get();
150
		return info;
151

  
152
	}
153

  
154
	private String generateStoreId(final String mdfName, final String mdfInterpretation, final String mdfLayout) {
155
		return mdfName + "-" + mdfLayout + "-" + mdfInterpretation;
156
	}
157

  
158
	public String getMetadataCollection() {
159
		return metadataCollection;
160
	}
161

  
162
	@Required
163
	public void setMetadataCollection(final String metadataCollection) {
164
		this.metadataCollection = metadataCollection;
165
	}
166

  
167
	public MongoQueryParser getQueryParser() {
168
		return queryParser;
169
	}
170

  
171
	public void setQueryParser(final MongoQueryParser queryParser) {
172
		this.queryParser = queryParser;
173
	}
174

  
175
	public OAIConfigurationReader getConfiguration() {
176
		return configuration;
177
	}
178

  
179
	public void setConfiguration(final OAIConfigurationReader configuration) {
180
		this.configuration = configuration;
181
	}
182

  
183
	public RecordInfoGenerator getRecordInfoGenerator() {
184
		return recordInfoGenerator;
185
	}
186

  
187
	public void setRecordInfoGenerator(final RecordInfoGenerator recordInfoGenerator) {
188
		this.recordInfoGenerator = recordInfoGenerator;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff