ActorsStoreRepositoryDefault.java

package org.linkedopenactors.rdfpub.store.rdf4j;

import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import org.apache.commons.rdf.api.IRI;
import org.apache.commons.rdf.api.RDF;
import org.linkedopenactors.rdfpub.domain.commonsrdf.Activity;
import org.linkedopenactors.rdfpub.domain.commonsrdf.ActivityPubObject;
import org.linkedopenactors.rdfpub.domain.commonsrdf.ActivityPubObjectConvertable;
import org.linkedopenactors.rdfpub.domain.commonsrdf.ActivityPubStore;
import org.linkedopenactors.rdfpub.domain.commonsrdf.Actor;
import org.linkedopenactors.rdfpub.domain.commonsrdf.ActorsStore;
import org.linkedopenactors.rdfpub.domain.commonsrdf.ActorsStoreRepository;
import org.linkedopenactors.rdfpub.domain.commonsrdf.SubjectProvider;
import org.linkedopenactors.rdfpub.domain.commonsrdf.vocab.Vocabularies;
import org.linkedopenactors.rdfpub.store.ActivityPubStoreRepository;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class ActorsStoreRepositoryDefault implements ActorsStoreRepository {

	private RDF rdf;
	private List<ActivityHandler> activityHandlers;
	private ActivityPubStoreRepository activityPubStoreRepository;
	private Vocabularies vocabularies;
	private SubjectProvider subjectProvider;
	private org.linkedopenactors.rdfpub.domain.commonsrdf.ActivityPubObjectFactory activityPubObjectFactory;

	public ActorsStoreRepositoryDefault(RDF rdf, ActivityPubStoreRepository activityPubStoreRepository,
			List<ActivityHandler> activityHandlers,SubjectProvider subjectProvider, Vocabularies vocabularies, org.linkedopenactors.rdfpub.domain.commonsrdf.ActivityPubObjectFactory activityPubObjectFactory) {
		this.rdf = rdf;
		this.activityPubStoreRepository = activityPubStoreRepository;
		this.activityHandlers = activityHandlers;
		this.vocabularies = vocabularies;
		this.subjectProvider = subjectProvider;
		this.activityPubObjectFactory = activityPubObjectFactory;
	}
	
	@Override
	public Optional<ActorsStore> find(IRI actorSubject) {
		if(vocabularies.getActivityStreams().Public().equals(actorSubject)) {
			return find4PublicActor();
		} else {
			return find4Actor(actorSubject);
		}
	}

	private Optional<ActorsStore> find4PublicActor() {
		ActivityPubStore publicStore = activityPubStoreRepository.findActivityPubStore(vocabularies.getActivityStreams().Public())
			.orElse(activityPubStoreRepository.createActivityPubStore(vocabularies.getActivityStreams().Public()));
			
		Optional<ActivityPubObject> aoOpt = publicStore.find(vocabularies.getActivityStreams().Public());
		if(aoOpt.isEmpty()) {
			createPublicActor(publicStore);
			aoOpt = publicStore.find(vocabularies.getActivityStreams().Public());
		}
		return aoOpt
				.map(ActivityPubObject::asConvertable)
				.map(ActivityPubObjectConvertable::asActor)
				.flatMap(actor->{
					return activityPubStoreRepository.findActivityPubStore(vocabularies.getActivityStreams().Public())
							.map(activityPubStore->new ActorsStoreDefault(rdf, actor, activityPubStore, activityHandlers));
					});
	}

	private Optional<ActorsStore> find4Actor(IRI actorSubject) {
		ActivityPubStore publicStore = activityPubStoreRepository.findActivityPubStore(vocabularies.getActivityStreams().Public())
					.orElse(activityPubStoreRepository.createActivityPubStore(actorSubject));
		
		Optional<ActorsStore> s = publicStore.find(actorSubject)
				.map(ActivityPubObject::asConvertable)
				.map(ActivityPubObjectConvertable::asActor)
				.flatMap(actor->{
					return activityPubStoreRepository.findActivityPubStore(actorSubject)
							.map(activityPubStore->new ActorsStoreDefault(rdf, actor, activityPubStore, activityHandlers));
					});
		return s;
	}

	private Actor createPublicActor(ActivityPubStore publicStore) {
		org.apache.commons.rdf.api.IRI inboxCollection = getActorIriExtendedWith(vocabularies.getActivityStreams().Public(), "inbox");
		org.apache.commons.rdf.api.IRI outboxCollection =  getActorIriExtendedWith(vocabularies.getActivityStreams().Public(), "outbox");
		
		Actor actor = activityPubObjectFactory.create(vocabularies.getActivityStreams().Public()).asConvertable().asActor();
		
		actor.setType(Set.of(vocabularies.getActivityStreams().Application()));
		actor.setInbox(inboxCollection);
		actor.setOutbox(outboxCollection);		
		actor.setPublished(Instant.now());
		
		Activity activity = activityPubObjectFactory.create(subjectProvider.provide(actor)).asConvertable().asActivity();
		activity.addType(vocabularies.getActivityStreams().Create());		
		activity.addActor(actor.getSubject());
		activity.addObject(actor);

		publicStore.add(/**vocabularies.getActivityStreams().Public(),**/ activity, "createPublicActor");
		
		Actor createdActor = findPublicActor()
				.orElseThrow();
		log.debug("Public Actor created: " + createdActor);
		return createdActor;
	}

	private org.apache.commons.rdf.api.IRI getActorIriExtendedWith(org.apache.commons.rdf.api.IRI actorId, String extension) {
		String actorIdAsString = actorId.toString();
		return rdf.createIRI(actorIdAsString + "/" + extension);
	}

	private Optional<Actor> findPublicActor() {
		ActorsStore actorsStore = find(vocabularies.getActivityStreams().Public()).orElseThrow();
		return actorsStore
				.find(vocabularies.getActivityStreams().Public())
				.map(ActivityPubObject::asConvertable)
				.map(ActivityPubObjectConvertable::asActor);
	}

}