ActivityPubObjectFactory.java

package org.linkedopenactors.rdfpub.domain.commonsrdf;

import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.rdf.api.BlankNodeOrIRI;
import org.apache.commons.rdf.api.Graph;
import org.apache.commons.rdf.api.IRI;
import org.apache.commons.rdf.api.RDF;
import org.apache.commons.rdf.api.Triple;
import org.linkedopenactors.rdfpub.domain.commonsrdf.vocab.Vocabularies;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class ActivityPubObjectFactory {

	private StringToGraphConverter stringToGraphConverter;
	private GraphToStringConverter graphToStringConverter;
	private RDF rdf;
	private SubjectProvider subjectProvider;
	private Vocabularies vocabularies;
	private InstanceProperties instanceProperties;

	public ActivityPubObjectFactory(RDF rdf, StringToGraphConverter stringToGraphConverter,
			GraphToStringConverter graphToStringConverter, SubjectProvider subjectProvider, Vocabularies vocabularies,
			InstanceProperties instanceProperties) {
		this.rdf = rdf;
		this.stringToGraphConverter = stringToGraphConverter;
		this.graphToStringConverter = graphToStringConverter;
		this.subjectProvider = subjectProvider;
		this.vocabularies = vocabularies;
		this.instanceProperties = instanceProperties;		
	}
	
	public ActivityPubObject create(IRI subject, Graph graph) {
		if(subject == null) {
			Set<BlankNodeOrIRI> subjects = graph.stream().map(Triple::getSubject).collect(Collectors.toSet());
			if(subjects.size()!=1) {
				throw new IllegalStateException("passed subject is null, but the graph has not exact one subject: " + subjects);
			} else {
				subject = subjects.stream()
						.findFirst()
						.filter(IRI.class::isInstance)
						.map(IRI.class::cast)
						.orElseThrow();
			}
		}	
		return new ActivityPubObjectDefault(rdf, subject, graph, graphToStringConverter, subjectProvider, vocabularies, instanceProperties);
	}
		
	public ActivityPubObject create(String subject, String modelAsTurtleString) {
		return create(RdfFormat.TURTLE, modelAsTurtleString, subject);
	}
	
	public ActivityPubObject create(String modelAsTurtleString) {
		return create(RdfFormat.TURTLE, modelAsTurtleString);
	}
	
	public ActivityPubObject create(RdfFormat format, String modelAsTurtleString, String root) {		
		Graph graph = stringToGraphConverter.convert(format, modelAsTurtleString);
		return create(graph, rdf.createIRI(root));
	}
	
	public ActivityPubObject create(RdfFormat format, String modelAsTurtleString) {
		Graph graph = stringToGraphConverter.convert(format, modelAsTurtleString);	
		IRI root = findRoot(graph)
				.orElseThrow(()-> new IllegalStateException("Problem finding root for: \n" + modelAsTurtleString));
		return create(graph, root);
//		return new ActivityPubObjectDefault(rdf, root, graph, graphToStringConverter, subjectProvider, vocabularies, instanceProperties);
	}

	private ActivityPubObject create(Graph graph, IRI root) {
//		Graph graph = stringToGraphConverter.convert(format, modelAsTurtleString);	
//		IRI root = findRoot(graph)
//				.orElseThrow(()-> new IllegalStateException("Problem finding root for: \n" + modelAsTurtleString));
		ActivityPubObjectDefault ao = new ActivityPubObjectDefault(rdf, root, graph, graphToStringConverter, subjectProvider, vocabularies, instanceProperties);
		
		return ao;
	}

	private Optional<IRI> findRoot(Graph graph) {
		
		Set<IRI> subjects = graph.stream()
				.map(Triple::getSubject)
				.filter(sub->sub instanceof IRI)
				.map(IRI.class::cast)
				.collect(Collectors.toSet());
		
		Set<IRI> referencedSubjects2 = graph.stream()
			.map(t->t.getObject())
			.filter(o -> o instanceof IRI)
			.map(IRI.class::cast)
			.collect(Collectors.toSet());
		
		Set<IRI> unreferenced2 = subjects.stream()
				.filter(s->!referencedSubjects2.contains(s))
				.collect(Collectors.toSet());
		
		if(unreferenced2.size()!=1) {
			log.warn("found ["+unreferenced2.size()+"]) subjects: " + unreferenced2);
			return Optional.empty();
		}
		return unreferenced2.stream().findFirst();
	}

	public ActivityPubObject create(IRI provide) {
		return new ActivityPubObjectDefault(rdf, provide, null, graphToStringConverter, subjectProvider, vocabularies, instanceProperties);
	}
}