Project

General

Profile

1
package eu.dnetlib.parthenos.registry;
2

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

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

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

    
52
	private static final Log log = LogFactory.getLog(GCubeResourceRegistrator.class);
53

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

    
59
	@Autowired
60
	private FacetWriter facetWriter;
61
	@Autowired
62
	private RelWriter relWriter;
63

    
64
	private ResourceRegistryPublisher resourceRegistryPublisher;
65
	private ResourceRegistryClient resourceRegistryClient;
66

    
67
	private OntModel baseModel;
68

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

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

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

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

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

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

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

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

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

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

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

    
285
	protected InfModel loadBaseModel() {
286
		return ModelFactory.createRDFSModel(baseModel);
287
	}
288

    
289
	protected int processServices(final InfModel model,
290
			final Set<String> uriProcessed,
291
			final JsonFactory jsonFactory,
292
			final Map<String, ParthenosRegistryResource> idMap)
293
			throws IOException, ParthenosPublisherException {
294
		log.debug("Processing services");
295
		int count = 0;
296
		int total = 0;
297

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

    
320
			} else {
321
				log.debug(resourceURI + " already processed, now skipping it");
322
			}
323
		}
324
		log.debug(String.format("Registered %d/%d services", count, total));
325
		return count;
326

    
327
	}
328

    
329
	private ParthenosRegistryResource processService(final Resource res, final JsonFactory jsonFactory, final Map<String, ParthenosRegistryResource> idMap)
330
			throws IOException {
331
		log.debug("Processing " + res.getURI());
332

    
333
		final ByteArrayOutputStream out = new ByteArrayOutputStream();
334
		BufferedOutputStream bos = new BufferedOutputStream(out);
335
		JsonGenerator jg = jsonFactory.createGenerator(bos, JsonEncoding.UTF8);
336
		jg.writeStartObject();
337
		//it should never happen to get PE1_Service as a specific type
338
		String specificType = findSpecificType(res, CRMpe.PE1_Service).getLocalName();
339
		String uuid = writeCommon(res, specificType, jg, idMap);
340
		//******THE FACETS *******//
341
		jg.writeArrayFieldStart("consistsOf");
342
		//list of facets
343
		writeCommonFacets(res, jg);
344
		facetWriter.writeEventFacet(jg);
345
		facetWriter.writeRightsFacet(jg, res);
346
		if (res.hasProperty(CRMpe.PP2_provided_by)) {
347
			//TODO: shouldn't this be a rel to an actor?
348
			Resource provider = res.getPropertyResourceValue(CRMpe.PP2_provided_by);
349
			facetWriter.writeContactReferenceFacet(jg, provider);
350
		}
351
		facetWriter.writeDesignatedAccessPointFacet(jg, res);
352
		jg.writeEndArray();
353
		jg.writeEndObject();
354
		jg.close();
355
		String json = out.toString("UTF-8");
356
		log.debug(json);
357
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
358
	}
359

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

    
389
	private ParthenosRegistryResource processBasicResource(final Resource res,
390
			final Resource basicType,
391
			final JsonFactory jsonFactory,
392
			final Map<String, ParthenosRegistryResource> idMap)
393
			throws IOException {
394
		log.debug("Processing " + res.getURI());
395

    
396
		final ByteArrayOutputStream out = new ByteArrayOutputStream();
397
		BufferedOutputStream bos = new BufferedOutputStream(out);
398
		JsonGenerator jg = jsonFactory.createGenerator(bos, JsonEncoding.UTF8);
399
		jg.writeStartObject();
400
		String specificType = findSpecificType(res, basicType).getLocalName();
401
		String uuid = writeCommon(res, specificType, jg, idMap);
402
		//******THE FACETS *******//
403
		jg.writeArrayFieldStart("consistsOf");
404
		writeCommonFacets(res, jg);
405
		jg.writeEndArray();
406
		jg.writeEndObject();
407
		jg.close();
408
		String json = out.toString("UTF-8");
409
		log.debug(json);
410
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
411
	}
412

    
413
	/**
414
	 * Write the common properties: header, class for all resources
415
	 *
416
	 * @param resource  input Resource.
417
	 * @param className name of the class for the registry
418
	 * @param jg        JsonGenerator to write with.
419
	 * @param idMap     map of the already assigned UUID
420
	 * @return the uuid of the resource
421
	 */
422
	protected String writeCommon(final Resource resource, final String className, final JsonGenerator jg, final Map<String, ParthenosRegistryResource> idMap)
423
			throws IOException {
424
		String uuid;
425
		if (idMap.containsKey(resource.getURI())) {
426
			uuid = idMap.get(resource.getURI()).getUuid();
427
		} else {
428
			//TODO: need to find if a resource with the given URI is already in the registry?
429
			uuid = UUID.randomUUID().toString();
430
			idMap.put(resource.getURI(), new ParthenosRegistryResource().setUuid(uuid));
431
		}
432
		jg.writeObjectFieldStart("header");
433
		jg.writeStringField("uuid", uuid);
434
		jg.writeEndObject();
435
		jg.writeStringField("@class", StringUtils.remove(className, '-'));
436
		return uuid;
437
	}
438

    
439
	/**
440
	 * Write the common facets: identifier and info facets
441
	 *
442
	 * @param res
443
	 * @param jg
444
	 */
445
	protected void writeCommonFacets(final Resource res, final JsonGenerator jg) throws IOException {
446
		facetWriter.writeIdentifierFacet(jg, res.getURI());
447
		facetWriter.writeP1Facets(jg, res);
448
		facetWriter.writeInfoFacet(jg, res);
449
	}
450

    
451
	protected int processDigitalObjects(final InfModel model,
452
			final Set<String> uriProcessed,
453
			final JsonFactory jsonFactory,
454
			final Map<String, ParthenosRegistryResource> idMap)
455
			throws IOException, ResourceRegistryException {
456
		log.debug("Processing digital objects (include dataset and software)");
457
		int count = 0;
458
		int total = 0;
459
		ResIterator iterDo = model.listResourcesWithProperty(RDF.type, CRMdig.D1_Digital_Object);
460
		while (iterDo.hasNext()) {
461
			total++;
462
			Resource res = iterDo.nextResource();
463
			String resourceURI = res.getURI();
464
			if (!uriProcessed.contains(resourceURI)) {
465
				ParthenosRegistryResource prr = processDigitalObject(res, jsonFactory, idMap);
466
				this.resourceRegistryPublisher.createResource(prr.getRegistryType(), prr.getJson());
467
				uriProcessed.add(resourceURI);
468
				idMap.put(resourceURI, prr);
469
				count++;
470
			} else {
471
				log.debug(resourceURI + " already processed, now skipping it");
472
			}
473
		}
474
		log.debug(String.format("Registered %d/%d digital objects", count, total));
475
		return count;
476
	}
477

    
478
	protected ParthenosRegistryResource processDigitalObject(final Resource res,
479
			final JsonFactory jsonFactory,
480
			final Map<String, ParthenosRegistryResource> idMap)
481
			throws IOException {
482
		log.debug("Processing " + res.getURI());
483
		String specificType = findSpecificType(res, CRMdig.D1_Digital_Object).getLocalName();
484
		final ByteArrayOutputStream out = new ByteArrayOutputStream();
485
		BufferedOutputStream bos = new BufferedOutputStream(out);
486
		JsonGenerator jg = jsonFactory.createGenerator(bos, JsonEncoding.UTF8);
487
		jg.writeStartObject();
488

    
489
		String uuid = writeCommon(res, specificType, jg, idMap);
490
		//******THE FACETS *******//
491
		jg.writeArrayFieldStart("consistsOf");
492
		//list of facets
493
		writeCommonFacets(res, jg);
494
		facetWriter.writeTemporalCoverageFacet(jg, res);
495
		facetWriter.writeRightsFacet(jg, res);
496

    
497
		jg.writeEndArray();
498
		jg.writeEndObject();
499
		jg.close();
500
		String json = out.toString("UTF-8");
501
		log.debug(json);
502
		return new ParthenosRegistryResource().setUuid(uuid).setType(specificType).setJson(json);
503
	}
504

    
505
	protected int processActors(final InfModel model,
506
			Set<String> uriProcessed,
507
			final JsonFactory jsonFactory,
508
			final Map<String, ParthenosRegistryResource> idMap)
509
			throws IOException {
510
		log.debug("Processing actors");
511
		int count = 0;
512
		int total = 0;
513
		ResIterator iterActors = model.listResourcesWithProperty(RDF.type, CRM.E39_Actor);
514
		while (iterActors.hasNext()) {
515
			total++;
516
			Resource res = iterActors.nextResource();
517
			String resourceURI = res.getURI();
518
			if (!uriProcessed.contains(resourceURI)) {
519
				ParthenosRegistryResource prr = processActor(res, jsonFactory, idMap);
520
				uriProcessed.add(resourceURI);
521
				idMap.put(resourceURI, prr);
522
				count++;
523

    
524
			} else {
525
				log.debug(resourceURI + " already processed, now skipping it");
526
			}
527
		}
528
		log.debug(String.format("Registered %d/%d actors", count, total));
529
		return count;
530
	}
531

    
532
	protected ParthenosRegistryResource processActor(final Resource r, final JsonFactory jsonFactory, final Map<String, ParthenosRegistryResource> idMap)
533
			throws IOException {
534
		log.debug("Processing " + r.getURI());
535
		String specificType = findSpecificType(r, CRM.E39_Actor).getLocalName();
536
		final ByteArrayOutputStream out = new ByteArrayOutputStream();
537
		BufferedOutputStream bos = new BufferedOutputStream(out);
538
		JsonGenerator jg = jsonFactory.createGenerator(bos, JsonEncoding.UTF8);
539
		jg.writeStartObject();
540

    
541
		String uuid = writeCommon(r, specificType, jg, idMap);
542
		//******THE FACETS *******//
543
		jg.writeArrayFieldStart("consistsOf");
544
		//list of facets
545
		writeCommonFacets(r, jg);
546
		facetWriter.writeContactReferenceFacet(jg, r);
547

    
548
		jg.writeEndArray();
549
		jg.writeEndObject();
550
		jg.close();
551
		String json = out.toString("UTF-8");
552
		log.debug(json);
553
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
554
	}
555

    
556
	protected int processProjects(final InfModel model,
557
			Set<String> uriProcessed,
558
			final JsonFactory jsonFactory,
559
			final Map<String, ParthenosRegistryResource> idMap)
560
			throws IOException, ResourceRegistryException {
561
		log.debug("Processing projects");
562
		int count = 0;
563
		int total = 0;
564
		ResIterator iterProjects = model.listResourcesWithProperty(RDF.type, CRMpe.PE35_Project);
565
		while (iterProjects.hasNext()) {
566
			total++;
567
			Resource res = iterProjects.nextResource();
568
			String resourceURI = res.getURI();
569
			if (!uriProcessed.contains(resourceURI)) {
570
				ParthenosRegistryResource prr = processProject(res, jsonFactory, idMap);
571
				this.resourceRegistryPublisher.createResource(prr.getRegistryType(), prr.getJson());
572
				uriProcessed.add(resourceURI);
573
				idMap.put(resourceURI, prr);
574
				count++;
575
			} else {
576
				log.debug(resourceURI + " already processed, now skipping it");
577
			}
578
		}
579
		log.debug(String.format("Registered %d/%d projects", count, total));
580
		return count;
581
	}
582

    
583
	protected ParthenosRegistryResource processProject(final Resource res, final JsonFactory jsonFactory, final Map<String, ParthenosRegistryResource> idMap)
584
			throws IOException {
585
		log.debug("Processing " + res.getURI());
586
		String specificType = findSpecificType(res, CRMpe.PE35_Project).getLocalName();
587
		final ByteArrayOutputStream out = new ByteArrayOutputStream();
588
		BufferedOutputStream bos = new BufferedOutputStream(out);
589
		JsonGenerator jg = jsonFactory.createGenerator(bos, JsonEncoding.UTF8);
590
		jg.writeStartObject();
591

    
592
		String uuid = writeCommon(res, specificType, jg, idMap);
593
		jg.writeArrayFieldStart("consistsOf");
594
		writeCommonFacets(res, jg);
595

    
596
		jg.writeEndArray();
597
		jg.writeEndObject();
598
		jg.close();
599
		String json = out.toString("UTF-8");
600
		log.debug(json);
601
		return new ParthenosRegistryResource().setJson(json).setType(specificType).setUuid(uuid);
602
	}
603

    
604
	/**
605
	 * Finds the most specific type of res.
606
	 *
607
	 * @param res          Resource you want to find the most specific type
608
	 * @param fallbackType Resource representing the type to return if there is no type or if we get AmbiguousSpecificTypeException
609
	 * @return Resource: the most specific type, if any. fallbackType otherwise
610
	 */
611
	protected Resource findSpecificType(final Resource res, final Resource fallbackType) {
612
		Resource type = fallbackType;
613
		Set<Resource> types = AssemblerHelp.findSpecificTypes(res, fallbackType);
614
		if (types == null || types.isEmpty()) {
615
			log.warn("No specific type found. Returning the fallback type: " + fallbackType);
616
		}
617
		if (types.size() == 1) {
618
			type = types.iterator().next();
619
		}
620
		if (types.size() > 1) {
621
			log.warn("Found more than one possible specific type: choosing the first");
622
			types.stream().forEach((t) -> log.warn(t));
623
			type = types.iterator().next();
624
		}
625
		return type;
626
	}
627

    
628
	public FacetWriter getFacetWriter() {
629
		return facetWriter;
630
	}
631

    
632
	public void setFacetWriter(final FacetWriter facetWriter) {
633
		this.facetWriter = facetWriter;
634
	}
635

    
636
	public String getApplicationToken() {
637
		return applicationToken;
638
	}
639

    
640
	public void setApplicationToken(final String applicationToken) {
641
		this.applicationToken = applicationToken;
642
	}
643

    
644
	public String getRegistryBaseURL() {
645
		return registryBaseURL;
646
	}
647

    
648
	public void setRegistryBaseURL(final String registryBaseURL) {
649
		this.registryBaseURL = registryBaseURL;
650
	}
651

    
652
	public RelWriter getRelWriter() {
653
		return relWriter;
654
	}
655

    
656
	public void setRelWriter(final RelWriter relWriter) {
657
		this.relWriter = relWriter;
658
	}
659

    
660
	public ResourceRegistryPublisher getResourceRegistryPublisher() {
661
		return resourceRegistryPublisher;
662
	}
663

    
664
	public void setResourceRegistryPublisher(final ResourceRegistryPublisher resourceRegistryPublisher) {
665
		this.resourceRegistryPublisher = resourceRegistryPublisher;
666
	}
667

    
668
	public ResourceRegistryClient getResourceRegistryClient() {
669
		return resourceRegistryClient;
670
	}
671

    
672
	public void setResourceRegistryClient(final ResourceRegistryClient resourceRegistryClient) {
673
		this.resourceRegistryClient = resourceRegistryClient;
674
	}
675

    
676
	public OntModel getBaseModel() {
677
		return baseModel;
678
	}
679

    
680
	public void setBaseModel(final OntModel baseModel) {
681
		this.baseModel = baseModel;
682
	}
683
}
(2-2/6)