All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.smartdeveloperhub.harvesters.scm.testing.enhancer.GitLabEnhancer Maven / Gradle / Ivy

Go to download

Standalone GitLab Enhancer Testing implementation for carrying out integration tests

The newest version!
/**
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   This file is part of the Smart Developer Hub Project:
 *     http://www.smartdeveloperhub.org/
 *
 *   Center for Open Middleware
 *     http://www.centeropenmiddleware.com/
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Copyright (C) 2015-2016 Center for Open Middleware.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *             http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Artifact    : org.smartdeveloperhub.harvesters.scm:scm-harvester-testing:0.3.0
 *   Bundle      : scm-harvester-testing-0.3.0.jar
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 */
package org.smartdeveloperhub.harvesters.scm.testing.enhancer;

import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.smartdeveloperhub.harvesters.scm.backend.notification.CommitterCreatedEvent;
import org.smartdeveloperhub.harvesters.scm.backend.notification.CommitterDeletedEvent;
import org.smartdeveloperhub.harvesters.scm.backend.notification.Event;
import org.smartdeveloperhub.harvesters.scm.backend.notification.GitCollector;
import org.smartdeveloperhub.harvesters.scm.backend.notification.RepositoryCreatedEvent;
import org.smartdeveloperhub.harvesters.scm.backend.notification.RepositoryDeletedEvent;
import org.smartdeveloperhub.harvesters.scm.backend.notification.RepositoryUpdatedEvent;
import org.smartdeveloperhub.harvesters.scm.backend.pojos.Branch;
import org.smartdeveloperhub.harvesters.scm.backend.pojos.Commit;
import org.smartdeveloperhub.harvesters.scm.backend.pojos.Enhancer;
import org.smartdeveloperhub.harvesters.scm.backend.pojos.Repository;
import org.smartdeveloperhub.harvesters.scm.backend.pojos.User;
import org.smartdeveloperhub.harvesters.scm.testing.enhancer.ActivityTracker.ActivityContext;

import com.google.common.base.Joiner;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

public final class GitLabEnhancer {

	private final class InnerOwner implements ActivityContext {

		@Override
		public String resolve(final String path, final Object... args) {
			return GitLabEnhancer.this.base.resolve(String.format(path,args)).toString();
		}

		@Override
		public void onActivity(final Activity activity) {
			final ActivityListener current=GitLabEnhancer.this.listener;
			if(current!=null) {
				current.onActivity(activity);
			}
		}

	}

	public static class UpdateReport {

		private Event event;
		private final List warnings;
		private IOException failure;
		private String failureMessage;
		private final List sideEffects;

		UpdateReport() {
			this.warnings=Lists.newArrayList();
			this.sideEffects=Lists.newArrayList();
		}

		UpdateReport curatedEvent(final Event event) {
			this.event = event;
			return this;
		}

		UpdateReport sideEffect(final Event event) {
			this.sideEffects.add(event);
			return this;
		}

		UpdateReport updateFailed(final IOException failure, final String message, final Object...args) {
			this.failure = failure;
			this.failureMessage=String.format(message,args);
			return this;
		}

		UpdateReport updateFailed(final IOException failure) {
			this.failure = failure;
			this.failureMessage="";
			return this;
		}

		UpdateReport warn(final String message, final Object... args) {
			this.warnings.add(String.format(message,args));
			return this;
		}

		public boolean enhancerUpdated() {
			return this.event!=null;
		}

		public boolean notificationSent() {
			return enhancerUpdated() && this.failure==null;
		}

		public String updateFailure() {
			return
				this.failureMessage+
				(this.failureMessage.isEmpty()?"":"\n")+
				Throwables.getStackTraceAsString(this.failure);
		}

		public Event curatedEvent() {
			return this.event;
		}

		public List sideEffects() {
			return Collections.unmodifiableList(this.sideEffects);
		}

		public List warnings() {
			return Collections.unmodifiableList(this.warnings);
		}

	}

	private final Map committers;
	private final Map repositories;
	private final GitCollector collector;
	private final URI base;

	private ActivityListener listener;

	private GitLabEnhancer(final GitCollector collector, final URI base) {
		this.collector = collector;
		this.base = base;
		this.committers=Maps.newLinkedHashMap();
		this.repositories=Maps.newLinkedHashMap();
	}

	public GitLabEnhancer registerListener(final ActivityListener listener) {
		this.listener = listener;
		return this;
	}

	public Enhancer getEnhancer(final String instance) {
		final Enhancer en = new Enhancer();
		en.setId(instance);
		en.setName("Testing GitLab Enhancer Service");
		en.setStatus("OK");
		en.setVersion("0.1.0");
		en.getCollectors().add(this.collector.getConfig());
		return en;
	}

	public List getCommitters() {
		return ImmutableList.copyOf(this.committers.keySet());
	}

	public User getCommitter(final String committerId) {
		return findCommitter(committerId).getRepresentation();
	}

	public List getRepositories() {
		return ImmutableList.copyOf(this.repositories.keySet());
	}

	public Repository getRepository(final String repositoryId) {
		return findRepository(repositoryId).getRepresentation();
	}

	public List getRepositoryBranches(final String repositoryId) {
		return findRepository(repositoryId).branches();
	}

	public List getRepositoryCommits(final String repositoryId) {
		return findRepository(repositoryId).commits();
	}

	public Commit getRepositoryCommit(final String repositoryId, final String commitId) {
		return findRepository(repositoryId).commit(commitId).getRepresentation();
	}

	public Branch getRepositoryBranch(final String repositoryId, final String name) {
		return findRepository(repositoryId).branch(name).getRepresentation();
	}

	public List getRepositoryBranchCommits(final String repositoryId, final String name) {
		return findRepository(repositoryId).branch(name).commits();
	}

	public UpdateReport update(final Event event) {
		Reports.remove();
		ActivityTracker.useContext(new InnerOwner());
		try {
			updateEnhancer(event);
			notifyUpdate(Reports.currentReport().curatedEvent());
			for(final Event sideEffect:Reports.currentReport().sideEffects()) {
				notifyUpdate(sideEffect);
			}
			return Reports.currentReport();
		} finally {
			ActivityTracker.remove();
		}
	}

	private void notifyUpdate(final Event event) {
		if(event!=null) {
			event.setInstance(this.collector.getInstance());
			event.setTimestamp(System.currentTimeMillis());
			try {
				this.collector.notify(event);
			} catch (final IOException e) {
				Reports.currentReport().updateFailed(e);
			}
		}
	}

	private void updateEnhancer(final Event event) {
		if(event instanceof CommitterCreatedEvent) {
			createCommitters((CommitterCreatedEvent)event);
		} else if(event instanceof CommitterDeletedEvent) {
			deleteCommitters((CommitterDeletedEvent)event);
		} else if(event instanceof RepositoryCreatedEvent) {
			createRepositories((RepositoryCreatedEvent)event);
		} else if(event instanceof RepositoryDeletedEvent) {
			deleteRepositories((RepositoryDeletedEvent)event);
		} else if(event instanceof RepositoryUpdatedEvent) {
			updateRepository((RepositoryUpdatedEvent)event);
		} else {
			Reports.
				currentReport().
					updateFailed(
						new IOException("Unsupported event type "+event.getClass().getSimpleName()));
		}
	}

	private CommitterState findCommitter(final String committerId) {
		CommitterState state = this.committers.get(committerId);
		if(state==null) {
			Reports.currentReport().warn("Committer %s does not exist",committerId);
			state=new NullCommitterState(committerId);
		}
		return state;
	}

	private RepositoryState findRepository(final String repositoryId) {
		RepositoryState state = this.repositories.get(repositoryId);
		if(state==null) {
			Reports.currentReport().warn("Repository %s does not exist",repositoryId);
			state=new NullRepositoryState(repositoryId);
		}
		return state;
	}

	private void  updateRepository(final RepositoryUpdatedEvent event) {
		final UpdateReport report = Reports.currentReport();

		final RepositoryState state = this.repositories.get(event.getRepository());
		if(state==null) {
			Reports.currentReport().warn("Repository %s does not exist",event.getRepository());
			return;
		}

		final RepositoryUpdatedEvent curated=new RepositoryUpdatedEvent();
		curated.setRepository(event.getRepository());
		curated.getContributors().addAll(event.getContributors());
		curated.getContributors().retainAll(getCommitters());

		for(final String id:event.getDeletedBranches()) {
			if(state.deleteBranch(id)) {
				curated.getDeletedBranches().add(id);
			}
		}
		for(final String id:event.getDeletedCommits()) {
			if(state.deleteCommit(id)) {
				curated.getDeletedCommits().add(id);
			}
		}

		final List dismissed=Lists.newArrayList(event.getContributors());
		dismissed.removeAll(curated.getContributors());
		if(!dismissed.isEmpty()) {
			report.warn("Dismissing non-existing contributors (%s)",Joiner.on(", ").join(dismissed));
		}

		if(!curated.getContributors().isEmpty()) {
			final Set contributingContributors=Sets.newHashSet();
			final Iterator candidateContributors=Iterators.cycle(curated.getContributors());
			for(final String id:event.getNewBranches()) {
				final String contributor=candidateContributors.next();
				if(state.createBranch(id)) {
					curated.getNewBranches().add(id);
					contributingContributors.add(contributor);
				}
			}
			for(final String id:event.getNewCommits()) {
				final String contributor=candidateContributors.next();
				if(state.createCommit(id,this.committers.get(contributor))) {
					curated.getNewCommits().add(id);
					contributingContributors.add(contributor);
				}
			}
			curated.getContributors().retainAll(contributingContributors);
		} else {
			logDismissal(event.getNewBranches(), "branches");
			logDismissal(event.getNewCommits(), "commits");
		}
		if (!curated.getDeletedBranches().isEmpty() ||
			!curated.getDeletedCommits().isEmpty()  ||
			!curated.getNewBranches().isEmpty()     ||
			!curated.getNewCommits().isEmpty()) {
			report.curatedEvent(curated);
		}
	}

	private void logDismissal(final List members, final String memberType) {
		if(!members.isEmpty()) {
			Reports.
				currentReport().
					warn(
						"Dismissing new %s (%s) as no existing contributors were specified",
						memberType,
						Joiner.on(", ").join(members));
		}
	}

	/**
	 * NOTE: What happens to all the committers related to the repositories?
	 */
	private void deleteRepositories(final RepositoryDeletedEvent event) {
		final UpdateReport report = Reports.currentReport();
		final RepositoryDeletedEvent curated=new RepositoryDeletedEvent();
		for(final String repositoryId:event.getDeletedRepositories()) {
			final RepositoryState repository = this.repositories.remove(repositoryId);
			if(repository!=null) {
				curated.getDeletedRepositories().add(repositoryId);
				ActivityTracker.currentTracker().deleted(repository);
				ActivityTracker.currentTracker().log("Deleted repository %s (%s)",repository.getId(),repository.getName());
			} else {
				report.warn("Repository %s does not exist",repositoryId);
			}
		}
		if(!curated.getDeletedRepositories().isEmpty()) {
			report.curatedEvent(curated);
		}
	}

	private void createRepositories(final RepositoryCreatedEvent event) {
		final UpdateReport report = Reports.currentReport();
		if(!this.committers.isEmpty()) {
			final RepositoryCreatedEvent curated=new RepositoryCreatedEvent();
			final Iterator committerIds = Iterators.cycle(this.committers.keySet());
			for(final String repositoryId:event.getNewRepositories()) {
				if(!this.repositories.containsKey(repositoryId)) {
					final CommitterState owner = this.committers.get(committerIds.next());
					final RepositoryState repository =
						new ImmutableRepositoryState(
							repositoryId,
							owner);
					repository.createBranch("1");
					this.repositories.put(repositoryId, repository);
					curated.getNewRepositories().add(repositoryId);
					final RepositoryUpdatedEvent event2 = new RepositoryUpdatedEvent();
					event2.setRepository(repositoryId);
					event2.getNewBranches().add("1");
					event2.getContributors().add(owner.getId());
					report.sideEffect(event2);
				} else {
					report.warn("Repository %s already exists",repositoryId);
				}
			}
			if(!curated.getNewRepositories().isEmpty()) {
				report.curatedEvent(curated);
			}
		}
	}

	/**
	 * NOTE: What happens to all the artifacts associated to this committers?
	 */
	private void deleteCommitters(final CommitterDeletedEvent event) {
		final UpdateReport report = Reports.currentReport();
		final CommitterDeletedEvent curated=new CommitterDeletedEvent();
		for(final String committerId:event.getDeletedCommitters()) {
			final CommitterState committer = this.committers.remove(committerId);
			if(committer!=null) {
				curated.getDeletedCommitters().add(committerId);
				ActivityTracker.currentTracker().deleted(committer);
				ActivityTracker.currentTracker().log("Deleted committer %s (%s)",committerId,committer.getName());
			} else {
				report.warn("Committer %s does not exist",committerId);
			}
		}
		if(!curated.getDeletedCommitters().isEmpty()) {
			report.curatedEvent(curated);
		}
	}

	private void createCommitters(final CommitterCreatedEvent event) {
		final UpdateReport report = Reports.currentReport();
		final CommitterCreatedEvent curated=new CommitterCreatedEvent();
		for(final String committerId:event.getNewCommitters()) {
			if(!this.committers.containsKey(committerId)) {
				final CommitterState committer = new ImmutableCommitterState(committerId);
				this.committers.put(committerId, committer);
				curated.getNewCommitters().add(committerId);
			} else {
				report.warn("Committer %s already exists",committerId);
			}
		}
		if(!curated.getNewCommitters().isEmpty()) {
			report.curatedEvent(curated);
		}
	}

	public static GitLabEnhancer newInstance(final GitCollector collector, final URI base) {
		return new GitLabEnhancer(collector,base);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy