Project

General

Profile

1
package eu.dnetlib.parthenos.registry;
2

    
3
import java.io.IOException;
4
import java.io.StringWriter;
5
import java.util.Map;
6
import java.util.Set;
7
import java.util.UUID;
8
import javax.annotation.PostConstruct;
9

    
10
import com.fasterxml.jackson.core.JsonFactory;
11
import com.fasterxml.jackson.core.JsonGenerator;
12
import com.google.common.collect.Maps;
13
import com.google.common.collect.Sets;
14
import eu.dnetlib.parthenos.CRM;
15
import eu.dnetlib.parthenos.CRMdig;
16
import eu.dnetlib.parthenos.CRMpe;
17
import eu.dnetlib.parthenos.publisher.ParthenosPublisherException;
18
import org.apache.commons.io.IOUtils;
19
import org.apache.commons.lang3.StringUtils;
20
import org.apache.commons.logging.Log;
21
import org.apache.commons.logging.LogFactory;
22
import org.apache.jena.assembler.AssemblerHelp;
23
import org.apache.jena.ontology.OntModel;
24
import org.apache.jena.ontology.OntModelSpec;
25
import org.apache.jena.rdf.model.*;
26
import org.apache.jena.vocabulary.RDF;
27
import org.gcube.common.authorization.client.Constants;
28
import org.gcube.common.authorization.library.AuthorizationEntry;
29
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
30
import org.gcube.common.scope.api.ScopeProvider;
31
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
32
import org.gcube.informationsystem.resourceregistry.client.ParthenosRegistryClientSetter;
33
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClient;
34
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClientFactory;
35
import org.gcube.informationsystem.resourceregistry.publisher.ParthenosRegistryPublisherSetter;
36
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisher;
37
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisherFactory;
38
import org.springframework.beans.factory.annotation.Autowired;
39
import org.springframework.beans.factory.annotation.Value;
40
import org.springframework.stereotype.Component;
41

    
42
/**
43
 * Created by Alessia Bardi on 26/09/2017.
44
 *
45
 * @author Alessia Bardi
46
 */
47
@Component
48
public class GCubeResourceRegistrator {
49

    
50
	private static final Log log = LogFactory.getLog(GCubeResourceRegistrator.class);
51

    
52
	@Value("${gcube.registry.baseurl}")
53
	private String registryBaseURL;
54
	@Value("${gcube.registry.application.token}")
55
	private String applicationToken;
56

    
57
	@Autowired
58
	private FacetWriter facetWriter;
59
	@Autowired
60
	private RelWriter relWriter;
61

    
62
	private ResourceRegistryPublisher resourceRegistryPublisher;
63
	private ResourceRegistryClient resourceRegistryClient;
64

    
65
	private OntModel baseModel;
66

    
67
	@PostConstruct
68
	public void init() throws Exception {
69
		ParthenosRegistryClientSetter.forceToURL(getRegistryBaseURL());
70
		ParthenosRegistryPublisherSetter.forceToURL(getRegistryBaseURL());
71
		log.info("Registry URL forced to " + getRegistryBaseURL());
72
		if (StringUtils.isNotBlank(getApplicationToken())) {
73
			GCubeResourceRegistrator.setContext(getApplicationToken());
74
			log.info("GCube Context set");
75
		} else {
76
			log.fatal("GCube context cannot be configured without a value in gcube.registry.application.token");
77
		}
78
		this.resourceRegistryPublisher = ResourceRegistryPublisherFactory.create();
79
		this.resourceRegistryClient = ResourceRegistryClientFactory.create();
80
		baseModel = ModelFactory.createOntologyModel(OntModelSpec.RDFS_MEM_TRANS_INF);
81
		baseModel.read(CRMpe.RDFS_URL);
82
		baseModel.read(CRM.RDFS_URL);
83
		baseModel.read(CRMdig.RDFS_URL);
84
	}
85

    
86
	protected static String getCurrentScope(String token) throws Exception {
87
		AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
88
		String context = authorizationEntry.getContext();
89
		log.info("Context of token " + token + " is: " + context);
90
		return context;
91
	}
92

    
93
	protected static void setContext(String token) throws Exception {
94
		SecurityTokenProvider.instance.set(token);
95
		ScopeProvider.instance.set(getCurrentScope(token));
96
	}
97

    
98
	public int unregister(final String datasourceApi) {
99
		//TODO: implement me
100
		return -1;
101
	}
102

    
103
	/**
104
	 * Registers resources and relationships into the Parthenos Registry
105
	 *
106
	 * @param rdfRecord RDF record in RDF/XML PLAIN format
107
	 */
108
	public void register(final String rdfRecord, final String objIdentifier) throws ParthenosPublisherException, IOException {
109
		log.info("Processing record " + objIdentifier + " for registration on JRR");
110
		if (StringUtils.isBlank(rdfRecord)) {
111
			log.warn("Got empty record " + objIdentifier);
112
		} else {
113
			InfModel model = loadBaseModel();
114
			model.read(IOUtils.toInputStream(rdfRecord, "UTF-8"), CRMpe.NS);
115

    
116
			JsonFactory jsonFactory = new JsonFactory();
117
			Set<String> uriProcessed = Sets.newHashSet();
118
			/* Maps URI to ParthenosRegistryResource (with uuids) */
119
			Map<String, ParthenosRegistryResource> idMap = Maps.newHashMap();
120
			try {
121
			/* Resource */
122
				int registeredServices = processServices(model, uriProcessed, jsonFactory, idMap);
123
				int registeredDigitalObjects = processDigitalObjects(model, uriProcessed, jsonFactory, idMap);
124
				int registeredActors = processActors(model, uriProcessed, jsonFactory, idMap);
125
				int registeredProjects = processProjects(model, uriProcessed, jsonFactory, idMap);
126
				int registeredTypes = processBasicResources(model, uriProcessed, jsonFactory, idMap, CRM.E55_Type);
127
				int registeredCurationPlans = processBasicResources(model, uriProcessed, jsonFactory, idMap, CRMpe.PE28_Curation_Plan);
128

    
129
				int total = registeredActors + registeredDigitalObjects + registeredProjects + registeredServices+registeredTypes+registeredCurationPlans;
130
				log.info(String.format("Registered %d resources from record with objIdentifier %s", total, objIdentifier));
131

    
132
			/* Relationships */
133
				int relTotal = 0;
134
				for (String uri : uriProcessed) {
135
					relTotal += processRelationships(model, uri, idMap);
136
				}
137
				log.info(String.format("Registered %d relationships from record with objIdentifier %s", relTotal, objIdentifier));
138
			} catch (Throwable e) {
139
				String msg = "Registration of " + objIdentifier + " could not be completed correctly";
140
				log.error(msg, e);
141
				throw new ParthenosPublisherException(msg, e);
142
			}
143
		}
144
	}
145

    
146
	private int processRelationships(final InfModel model, final String uri, final Map<String, ParthenosRegistryResource> idMap)
147
			throws IOException, ResourceRegistryException, ParthenosPublisherException {
148
		Resource subject = model.getResource(uri);
149
		String uuid = idMap.get(uri).getUuid();
150
		JsonFactory jsonFactory = new JsonFactory();
151
		int relCount = 0;
152

    
153
		if (subject.hasProperty(RDF.type, CRMpe.PE1_Service)) {
154
			StmtIterator itOfferedBy = subject.listProperties(CRMpe.PP1i_is_currently_offered_by);
155
			while (itOfferedBy.hasNext()) {
156
				Resource project = itOfferedBy.nextStatement().getResource();
157
				ParthenosRegistryResource source = idMap.get(uri);
158
				ParthenosRegistryResource projectRes = idMap.get(project.getURI());
159
				String relJson = relWriter
160
						.writeRelationship(jsonFactory, "PP1_currently_offers", projectRes.getUuid(), projectRes.getRegistryType(), source.getUuid(),
161
								source.getRegistryType());
162
				this.resourceRegistryPublisher.createIsRelatedTo("PP1_currently_offers", relJson);
163
				relCount++;
164
			}
165
			StmtIterator itProvidedBy = subject.listProperties(CRMpe.PP2_provided_by);
166
			while (itProvidedBy.hasNext()) {
167
				Resource provider = itProvidedBy.nextStatement().getResource();
168
				ParthenosRegistryResource prr = idMap.get(uri);
169
				ParthenosRegistryResource providerRes = idMap.get(provider.getURI());
170
				String relJson = relWriter.writeRelationship(jsonFactory, "PP2_provided_by", prr.getUuid(), prr.getRegistryType(), providerRes.getUuid(),
171
						providerRes.getRegistryType());
172
				this.resourceRegistryPublisher.createIsRelatedTo("PP2_provided_by", relJson);
173
				relCount++;
174
				//TODO: IsRelatedTo the contact person of the provider. Interpret '"Follow path of service ‘Provided by’ and switch E39 for E21: E21- >p76->E51""
175
			}
176
			relCount += registerRelationship(CRMpe.PP45_has_competency, subject, idMap, jsonFactory);
177
			relCount += registerRelationship(CRMpe.PP4_hosts_object, subject, idMap, jsonFactory);
178
			relCount += registerRelationship(CRMpe.PP31_uses_curation_plan, subject, idMap, jsonFactory);
179
			relCount += registerRelationship(CRMpe.PP32_curates, subject, idMap, jsonFactory);
180
			relCount += registerRelationship(CRMpe.PP6_hosts_digital_object, subject, idMap, jsonFactory);
181
			relCount += registerRelationship(CRMpe.PP7_hosts_software_object, subject, idMap, jsonFactory);
182
			relCount += registerRelationship(CRMpe.PP8_hosts_dataset, subject, idMap, jsonFactory);
183
			relCount += registerRelationship(CRMpe.PP29_uses_access_protocol, subject, idMap, jsonFactory);
184
			relCount += registerRelationship(CRMpe.PP47_has_protocol_type, subject, idMap, jsonFactory);
185
			relCount += registerRelationship(CRMpe.PP48_uses_protocol_parameter, subject, idMap, jsonFactory);
186
			relCount += registerRelationship(CRMpe.PP46_brokers_access_to, subject, idMap, jsonFactory);
187
			relCount += registerRelationship(CRMpe.PP11_curates_volatile_digital_object, subject, idMap, jsonFactory);
188
			relCount += registerRelationship(CRMpe.PP12_curates_volatile_software, subject, idMap, jsonFactory);
189
			relCount += registerRelationship(CRMpe.PP13_curates_volatile_dataset, subject, idMap, jsonFactory);
190
			relCount += registerRelationship(CRMpe.PP15_delivers_on_request, subject, idMap, jsonFactory);
191
			relCount += registerRelationship(CRMpe.PP46_brokers_access_to, subject, idMap, jsonFactory);
192
		}
193
		if (subject.hasProperty(RDF.type, CRMpe.PE18_Dataset)) {
194
			StmtIterator itPartOf = subject.listProperties(CRMpe.PP23i_is_dataset_part_of);
195
			while (itPartOf.hasNext()) {
196
				Resource obj = itPartOf.nextStatement().getResource();
197
				ParthenosRegistryResource prr = idMap.get(uri);
198
				ParthenosRegistryResource objres = idMap.get(obj.getURI());
199
				String relJson = relWriter.writeRelationship(jsonFactory, "PP23_has_dataset_part", objres.getUuid(), objres.getRegistryType(), prr.getUuid(),
200
						prr.getRegistryType());
201
				this.resourceRegistryPublisher.createIsRelatedTo("PP23_has_dataset_part", relJson);
202
				relCount++;
203
			}
204
			//TODO: this is in the registry model but I am not sure what's going to happen...
205
			StmtIterator itIsAbout = subject.listProperties(CRM.P129_is_about);
206
			while (itIsAbout.hasNext()) {
207
				Resource obj = itIsAbout.nextStatement().getResource();
208
				if (obj.hasProperty(RDF.type, CRM.E55_Type)) {
209
					ParthenosRegistryResource prr = idMap.get(uri);
210
					ParthenosRegistryResource objres = idMap.get(obj.getURI());
211
					String relJson = relWriter
212
							.writeRelationship(jsonFactory, "P129_is_about", prr.getUuid(), prr.getRegistryType(), objres.getUuid(), objres.getRegistryType());
213
					this.resourceRegistryPublisher.createIsRelatedTo("P129_is_about", relJson);
214
					relCount++;
215
				}
216
			}
217
		}
218
		if (subject.hasProperty(RDF.type, CRMpe.PE19_Persistent_Digital_Object)) {
219
			relCount += registerRelationship(CRMpe.PP16_has_persistent_digital_object_part, subject, idMap, jsonFactory);
220
		}
221
		if (subject.hasProperty(RDF.type, CRMpe.PE20_Volatile_Digital_Object)) {
222
			relCount += registerRelationship(CRMpe.PP17_has_snapshot, subject, idMap, jsonFactory);
223
			relCount += registerRelationship(CRMpe.PP18_has_digital_object_part, subject, idMap, jsonFactory);
224
		}
225
		if (subject.hasProperty(RDF.type, CRMpe.PE21_Persistent_Software)) {
226
			relCount += registerRelationship(CRMpe.PP19_has_persistent_software_part, subject, idMap, jsonFactory);
227
		}
228
		if (subject.hasProperty(RDF.type, CRMpe.PE22_Persistent_Dataset)) {
229
			relCount += registerRelationship(CRMpe.PP20_has_persistent_dataset_part, subject, idMap, jsonFactory);
230
			relCount += registerRelationship(CRMpe.PP39_is_metadata_for, subject, idMap, jsonFactory);
231
		}
232
		if (subject.hasProperty(RDF.type, CRMpe.PE23_Volatile_Software)) {
233
			relCount += registerRelationship(CRMpe.PP21_has_software_part, subject, idMap, jsonFactory);
234
			relCount += registerRelationship(CRMpe.PP22_has_release, subject, idMap, jsonFactory);
235
		}
236
		if (subject.hasProperty(RDF.type, CRMpe.PE24_Volatile_Dataset)) {
237
			relCount += registerRelationship(CRMpe.PP23_has_dataset_part, subject, idMap, jsonFactory);
238
			relCount += registerRelationship(CRMpe.PP24_has_dataset_snapshot, subject, idMap, jsonFactory);
239
			relCount += registerRelationship(CRMpe.PP41_is_index_of, subject, idMap, jsonFactory);
240
		}
241
		if (subject.hasProperty(RDF.type, CRMpe.PE26_RI_Project)) {
242
			relCount += registerRelationship(CRMpe.PP25_has_maintaining_RI, subject, idMap, jsonFactory);
243
		}
244
		if (subject.hasProperty(RDF.type, CRMpe.PE35_Project)) {
245
			relCount += registerRelationship(CRMpe.PP43_supported_project_activity, subject, idMap, jsonFactory);
246
			relCount += registerRelationship(CRMpe.PP44_has_maintaining_team, subject, idMap, jsonFactory);
247
		}
248
		log.debug(String.format("Registered %d relationships for uri %s, uuid %s", relCount, uri, uuid));
249
		return relCount;
250
	}
251

    
252
	protected int registerRelationship(final Property rel,
253
			final Resource subject,
254
			final Map<String, ParthenosRegistryResource> idMap,
255
			final JsonFactory jsonFactory)
256
			throws IOException, ResourceRegistryException, ParthenosPublisherException {
257
		int relCount = 0;
258
		StmtIterator it = subject.listProperties(rel);
259
		while (it.hasNext()) {
260
			Resource obj = it.nextStatement().getResource();
261
			if (obj == null) throw new ParthenosPublisherException(String.format("No target resource available for %s --> %s", subject.getURI(), rel.getURI()));
262
			ParthenosRegistryResource source = idMap.get(subject.getURI());
263
			ParthenosRegistryResource target = idMap.get(obj.getURI());
264
			if(target == null){
265
				log.error("Can't create rel "+rel.getLocalName()+" among "+subject.getURI()+" and "+obj.getURI());
266
			}
267
			else {
268
				String relJson = relWriter
269
						.writeRelationship(jsonFactory, rel.getLocalName(), source.getUuid(), source.getRegistryType(), target.getUuid(),
270
								target.getRegistryType());
271
				this.resourceRegistryPublisher.createIsRelatedTo(rel.getLocalName(), relJson);
272
				relCount++;
273
			}
274
		}
275
		return relCount;
276
	}
277

    
278
	protected InfModel loadBaseModel() {
279
		return ModelFactory.createRDFSModel(baseModel);
280
	}
281

    
282
	protected int processServices(final InfModel model,
283
			final Set<String> uriProcessed,
284
			final JsonFactory jsonFactory,
285
			final Map<String, ParthenosRegistryResource> idMap)
286
			throws IOException, ParthenosPublisherException {
287
		log.debug("Processing services");
288
		int count = 0;
289
		int total = 0;
290

    
291
		ResIterator iter = model.listResourcesWithProperty(RDF.type, CRMpe.PE1_Service);
292
		while (iter.hasNext()) {
293
			total++;
294
			Resource res = iter.nextResource();
295
			String resourceURI = res.getURI();
296
			//ensure we are not registering generic PE1_Service because the class is abstract and the registry complaints
297
			if (!uriProcessed.contains(resourceURI) && (res.hasProperty(RDF.type, CRMpe.PE8_E_Service)
298
					|| res.hasProperty(RDF.type, CRMpe.PE2_Hosting_Service)
299
					|| res.hasProperty(RDF.type, CRMpe.PE3_Curating_Service))) {
300
				ParthenosRegistryResource prr = processService(res, jsonFactory, idMap);
301
				//TODO: if something goes wrong we stop the registration but we are not rolling back the one that may have succeeded before.
302
				//Let's decide if this is ok or if we must be smarter than this
303
				try {
304
					this.resourceRegistryPublisher.createResource(prr.getRegistryType(), prr.getJson());
305
					uriProcessed.add(resourceURI);
306
					idMap.put(resourceURI, prr);
307
					count++;
308
				} catch (ResourceRegistryException e) {
309
					log.error("Sent json: "+prr.getJson());
310
					throw new ParthenosPublisherException(e);
311
				}
312

    
313
			} else {
314
				log.debug(resourceURI + " already processed, now skipping it");
315
			}
316
		}
317
		log.debug(String.format("Registered %d/%d services", count, total));
318
		return count;
319

    
320
	}
321

    
322
	private ParthenosRegistryResource processService(final Resource res, final JsonFactory jsonFactory, final Map<String, ParthenosRegistryResource> idMap)
323
			throws IOException {
324
		log.debug("Processing " + res.getURI());
325

    
326
		StringWriter sw = new StringWriter();
327
		JsonGenerator jg = jsonFactory.createGenerator(sw);
328
		jg.writeStartObject();
329
		//it should never happen to get PE1_Service as a specific type
330
		String specificType = findSpecificType(res, CRMpe.PE1_Service).getLocalName();
331
		String uuid = writeCommon(res, specificType, jg, idMap);
332
		//******THE FACETS *******//
333
		jg.writeArrayFieldStart("consistsOf");
334
		//list of facets
335
		writeCommonFacets(res, jg);
336
		facetWriter.writeEventFacet(jg);
337
		facetWriter.writeRightsFacet(jg, res);
338
		if (res.hasProperty(CRMpe.PP2_provided_by)) {
339
			//TODO: shouldn't this be a rel to an actor?
340
			Resource provider = res.getPropertyResourceValue(CRMpe.PP2_provided_by);
341
			facetWriter.writeContactReferenceFacet(jg, provider);
342
		}
343
		facetWriter.writeDesignatedAccessPointFacet(jg, res);
344
		jg.writeEndArray();
345
		jg.writeEndObject();
346
		jg.close();
347
		String json = sw.toString();
348
		log.debug(json);
349
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
350
	}
351

    
352
	protected int processBasicResources(final InfModel model,
353
			final Set<String> uriProcessed,
354
			final JsonFactory jsonFactory,
355
			final Map<String, ParthenosRegistryResource> idMap, final Resource entityType)
356
			throws IOException, ResourceRegistryException {
357
		log.debug("Processing "+entityType.getLocalName());
358
		int count = 0;
359
		int total = 0;
360
		ResIterator iter = model.listResourcesWithProperty(RDF.type, entityType);
361
		while (iter.hasNext()) {
362
			total++;
363
			Resource res = iter.nextResource();
364
			String resourceURI = res.getURI();
365
			if (!uriProcessed.contains(resourceURI)) {
366
				ParthenosRegistryResource prr = processBasicResource(res, entityType, jsonFactory, idMap);
367
				//TODO: if something goes wrong we stop the registration but we are not rolling back the one that may have succeeded before.
368
				//Let's decide if this is ok or if we must be smarter than this
369
				this.resourceRegistryPublisher.createResource(prr.getRegistryType(), prr.getJson());
370
				uriProcessed.add(resourceURI);
371
				idMap.put(resourceURI, prr);
372
				count++;
373
			} else {
374
				log.debug(resourceURI + " already processed, now skipping it");
375
			}
376
		}
377
		log.debug(String.format("Registered %d/%d %s", count, total, entityType.getLocalName()));
378
		return count;
379
	}
380

    
381
	private ParthenosRegistryResource processBasicResource(final Resource res, final Resource basicType, final JsonFactory jsonFactory, final Map<String, ParthenosRegistryResource> idMap)
382
			throws IOException {
383
		log.debug("Processing " + res.getURI());
384

    
385
		StringWriter sw = new StringWriter();
386
		JsonGenerator jg = jsonFactory.createGenerator(sw);
387
		jg.writeStartObject();
388
		String specificType = findSpecificType(res, basicType).getLocalName();
389
		String uuid = writeCommon(res, specificType, jg, idMap);
390
		//******THE FACETS *******//
391
		jg.writeArrayFieldStart("consistsOf");
392
		writeCommonFacets(res, jg);
393
		jg.writeEndArray();
394
		jg.writeEndObject();
395
		jg.close();
396
		String json = sw.toString();
397
		log.debug(json);
398
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
399
	}
400

    
401

    
402
	/**
403
	 * Write the common properties: header, class for all resources
404
	 *
405
	 * @param resource  input Resource.
406
	 * @param className name of the class for the registry
407
	 * @param jg        JsonGenerator to write with.
408
	 * @param idMap     map of the already assigned UUID
409
	 * @return the uuid of the resource
410
	 */
411
	protected String writeCommon(final Resource resource, final String className, final JsonGenerator jg, final Map<String, ParthenosRegistryResource> idMap)
412
			throws IOException {
413
		String uuid;
414
		if (idMap.containsKey(resource.getURI())) {
415
			uuid = idMap.get(resource.getURI()).getUuid();
416
		} else {
417
			uuid = UUID.randomUUID().toString();
418
			idMap.put(resource.getURI(), new ParthenosRegistryResource().setUuid(uuid));
419
		}
420
		jg.writeObjectFieldStart("header");
421
		jg.writeStringField("uuid", uuid);
422
		jg.writeEndObject();
423
		jg.writeStringField("@class", StringUtils.remove(className, '-'));
424
		return uuid;
425
	}
426

    
427
	/**
428
	 * Write the common facets: identifier and info facets
429
	 *
430
	 * @param res
431
	 * @param jg
432
	 */
433
	protected void writeCommonFacets(final Resource res, final JsonGenerator jg) throws IOException {
434
		facetWriter.writeIdentifierFacet(jg, res.getURI());
435
		facetWriter.writeP1Facets(jg, res);
436
		facetWriter.writeInfoFacet(jg, res);
437
	}
438

    
439
	protected int processDigitalObjects(final InfModel model,
440
			final Set<String> uriProcessed,
441
			final JsonFactory jsonFactory,
442
			final Map<String, ParthenosRegistryResource> idMap)
443
			throws IOException, ResourceRegistryException {
444
		log.debug("Processing digital objects (include dataset and software)");
445
		int count = 0;
446
		int total = 0;
447
		ResIterator iterDo = model.listResourcesWithProperty(RDF.type, CRMdig.D1_Digital_Object);
448
		while (iterDo.hasNext()) {
449
			total++;
450
			Resource res = iterDo.nextResource();
451
			String resourceURI = res.getURI();
452
			if (!uriProcessed.contains(resourceURI)) {
453
				ParthenosRegistryResource prr = processDigitalObject(res, jsonFactory, idMap);
454
				this.resourceRegistryPublisher.createResource(prr.getRegistryType(), prr.getJson());
455
				uriProcessed.add(resourceURI);
456
				idMap.put(resourceURI, prr);
457
				count++;
458
			} else {
459
				log.debug(resourceURI + " already processed, now skipping it");
460
			}
461
		}
462
		log.debug(String.format("Registered %d/%d digital objects", count, total));
463
		return count;
464
	}
465

    
466
	protected ParthenosRegistryResource processDigitalObject(final Resource res,
467
			final JsonFactory jsonFactory,
468
			final Map<String, ParthenosRegistryResource> idMap)
469
			throws IOException {
470
		log.debug("Processing " + res.getURI());
471
		String specificType = findSpecificType(res, CRMdig.D1_Digital_Object).getLocalName();
472
		StringWriter sw = new StringWriter();
473
		JsonGenerator jg = jsonFactory.createGenerator(sw);
474
		jg.writeStartObject();
475

    
476
		String uuid = writeCommon(res, specificType, jg, idMap);
477
		//******THE FACETS *******//
478
		jg.writeArrayFieldStart("consistsOf");
479
		//list of facets
480
		writeCommonFacets(res, jg);
481
		facetWriter.writeTemporalCoverageFacet(jg, res);
482
		facetWriter.writeRightsFacet(jg, res);
483

    
484
		jg.writeEndArray();
485
		jg.writeEndObject();
486
		jg.close();
487
		String json = sw.toString();
488
		log.debug(json);
489
		return new ParthenosRegistryResource().setUuid(uuid).setType(specificType).setJson(json);
490
	}
491

    
492
	protected int processActors(final InfModel model,
493
			Set<String> uriProcessed,
494
			final JsonFactory jsonFactory,
495
			final Map<String, ParthenosRegistryResource> idMap)
496
			throws IOException {
497
		log.debug("Processing actors");
498
		int count = 0;
499
		int total = 0;
500
		ResIterator iterActors = model.listResourcesWithProperty(RDF.type, CRM.E39_Actor);
501
		while (iterActors.hasNext()) {
502
			total++;
503
			Resource res = iterActors.nextResource();
504
			String resourceURI = res.getURI();
505
			if (!uriProcessed.contains(resourceURI)) {
506
				ParthenosRegistryResource prr = processActor(res, jsonFactory, idMap);
507
				uriProcessed.add(resourceURI);
508
				idMap.put(resourceURI, prr);
509
				count++;
510

    
511
			} else {
512
				log.debug(resourceURI + " already processed, now skipping it");
513
			}
514
		}
515
		log.debug(String.format("Registered %d/%d actors", count, total));
516
		return count;
517
	}
518

    
519
	protected ParthenosRegistryResource processActor(final Resource r, final JsonFactory jsonFactory, final Map<String, ParthenosRegistryResource> idMap)
520
			throws IOException {
521
		log.debug("Processing " + r.getURI());
522
		String specificType = findSpecificType(r, CRM.E39_Actor).getLocalName();
523
		StringWriter sw = new StringWriter();
524
		JsonGenerator jg = jsonFactory.createGenerator(sw);
525
		jg.writeStartObject();
526

    
527
		String uuid = writeCommon(r, specificType, jg, idMap);
528
		//******THE FACETS *******//
529
		jg.writeArrayFieldStart("consistsOf");
530
		//list of facets
531
		writeCommonFacets(r, jg);
532
		facetWriter.writeContactReferenceFacet(jg, r);
533

    
534
		jg.writeEndArray();
535
		jg.writeEndObject();
536
		jg.close();
537
		String json = sw.toString();
538
		log.debug(json);
539
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
540
	}
541

    
542
	protected int processProjects(final InfModel model,
543
			Set<String> uriProcessed,
544
			final JsonFactory jsonFactory,
545
			final Map<String, ParthenosRegistryResource> idMap)
546
			throws IOException, ResourceRegistryException {
547
		log.debug("Processing projects");
548
		int count = 0;
549
		int total = 0;
550
		ResIterator iterProjects = model.listResourcesWithProperty(RDF.type, CRMpe.PE35_Project);
551
		while (iterProjects.hasNext()) {
552
			total++;
553
			Resource res = iterProjects.nextResource();
554
			String resourceURI = res.getURI();
555
			if (!uriProcessed.contains(resourceURI)) {
556
				ParthenosRegistryResource prr = processProject(res, jsonFactory, idMap);
557
				this.resourceRegistryPublisher.createResource(prr.getRegistryType(), prr.getJson());
558
				uriProcessed.add(resourceURI);
559
				idMap.put(resourceURI, prr);
560
				count++;
561
			} else {
562
				log.debug(resourceURI + " already processed, now skipping it");
563
			}
564
		}
565
		log.debug(String.format("Registered %d/%d projects", count, total));
566
		return count;
567
	}
568

    
569
	protected ParthenosRegistryResource processProject(final Resource res, final JsonFactory jsonFactory, final Map<String, ParthenosRegistryResource> idMap)
570
			throws IOException {
571
		log.debug("Processing " + res.getURI());
572
		String specificType = findSpecificType(res, CRMpe.PE35_Project).getLocalName();
573
		StringWriter sw = new StringWriter();
574
		JsonGenerator jg = jsonFactory.createGenerator(sw);
575
		jg.writeStartObject();
576

    
577
		String uuid = writeCommon(res, specificType, jg, idMap);
578
		jg.writeArrayFieldStart("consistsOf");
579
		writeCommonFacets(res, jg);
580

    
581
		jg.writeEndArray();
582
		jg.writeEndObject();
583
		jg.close();
584
		String json = sw.toString();
585
		log.debug(json);
586
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
587
	}
588

    
589
	/**
590
	 * Finds the most specific type of res.
591
	 *
592
	 * @param res          Resource you want to find the most specific type
593
	 * @param fallbackType Resource representing the type to return if there is no type or if we get AmbiguousSpecificTypeException
594
	 * @return Resource: the most specific type, if any. fallbackType otherwise
595
	 */
596
	protected Resource findSpecificType(final Resource res, final Resource fallbackType) {
597
		Resource type = fallbackType;
598
		Set<Resource> types = AssemblerHelp.findSpecificTypes(res, fallbackType);
599
		if (types == null || types.isEmpty()) {
600
			log.warn("No specific type found. Returning the fallback type: " + fallbackType);
601
		}
602
		if(types.size() == 1){
603
			type = types.iterator().next();
604
		}
605
		if (types.size() > 1) {
606
			log.warn("Found more than one possible specific type: choosing the first");
607
			types.stream().forEach((t) -> log.warn(t));
608
			type = types.iterator().next();
609
		}
610
		return type;
611
	}
612

    
613
	public FacetWriter getFacetWriter() {
614
		return facetWriter;
615
	}
616

    
617
	public void setFacetWriter(final FacetWriter facetWriter) {
618
		this.facetWriter = facetWriter;
619
	}
620

    
621
	public String getApplicationToken() {
622
		return applicationToken;
623
	}
624

    
625
	public void setApplicationToken(final String applicationToken) {
626
		this.applicationToken = applicationToken;
627
	}
628

    
629
	public String getRegistryBaseURL() {
630
		return registryBaseURL;
631
	}
632

    
633
	public void setRegistryBaseURL(final String registryBaseURL) {
634
		this.registryBaseURL = registryBaseURL;
635
	}
636

    
637
	public RelWriter getRelWriter() {
638
		return relWriter;
639
	}
640

    
641
	public void setRelWriter(final RelWriter relWriter) {
642
		this.relWriter = relWriter;
643
	}
644

    
645
	public ResourceRegistryPublisher getResourceRegistryPublisher() {
646
		return resourceRegistryPublisher;
647
	}
648

    
649
	public void setResourceRegistryPublisher(final ResourceRegistryPublisher resourceRegistryPublisher) {
650
		this.resourceRegistryPublisher = resourceRegistryPublisher;
651
	}
652

    
653
	public ResourceRegistryClient getResourceRegistryClient() {
654
		return resourceRegistryClient;
655
	}
656

    
657
	public void setResourceRegistryClient(final ResourceRegistryClient resourceRegistryClient) {
658
		this.resourceRegistryClient = resourceRegistryClient;
659
	}
660

    
661
	public OntModel getBaseModel() {
662
		return baseModel;
663
	}
664

    
665
	public void setBaseModel(final OntModel baseModel) {
666
		this.baseModel = baseModel;
667
	}
668
}
(2-2/6)