package hu.elte.txtuml.validation;

import java.io.IOException;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.BuildContext;
import org.eclipse.jdt.core.compiler.ReconcileContext;
import org.eclipse.jdt.core.dom.CompilationUnit;

import hu.elte.txtuml.utils.Logger;
import hu.elte.txtuml.utils.jdt.ElementTypeTeller;
import hu.elte.txtuml.utils.jdt.SharedUtils;
import hu.elte.txtuml.validation.visitors.ModelVisitor;

/**
 * Compilation participant for JtxtUML validation. Performs validation on
 * reconcile events (not typing for a few seconds) and build events
 */
public class JtxtUMLCompilationParticipant extends org.eclipse.jdt.core.compiler.CompilationParticipant {
	private static final String TXTUML_NATURE_ID = "hu.elte.txtuml.project.txtumlprojectNature"; //$NON-NLS-1$
	public static final String JTXTUML_MARKER_TYPE = "hu.elte.txtuml.validation.jtxtumlmarker"; //$NON-NLS-1$

	@Override
	public boolean isActive(IJavaProject project) {
		try {
			return project.getProject().getNature(TXTUML_NATURE_ID) != null;
		} catch (CoreException e) {
			Logger.sys.error("Error while checking txtuml project", e); //$NON-NLS-1$
			return false;
		}
	}

	@Override
	public int aboutToBuild(IJavaProject project) {
		return READY_FOR_BUILD;
	}

	@Override
	public void reconcile(ReconcileContext context) {
		try {
			CompilationUnit unit = context.getAST8();
			ProblemCollector collector = new ProblemCollector(context);
			if (ElementTypeTeller.isModelElement(unit)) {
				unit.accept(new ModelVisitor(collector));
			}
			collector.refreshProblems();
		} catch (Exception e) {
			Logger.sys.error("Error while checking for problems", e); //$NON-NLS-1$
		}
	}

	@Override
	public void buildStarting(BuildContext[] files, boolean isBatch) {
		for (BuildContext file : files) {
			validateFile(file);
		}
	}

	private void validateFile(BuildContext file) {
		java.io.File systemFile = null;
		IPath location = file.getFile().getLocation();
		if (location != null) {
			systemFile = location.toFile();
		}
		if (systemFile == null) {
			return;
		}

		IProject project = file.getFile().getProject();
		IJavaProject javaProject = JavaCore.create(project);
		CompilationUnit unit = null;
		try {
			unit = SharedUtils.parseJavaSource(systemFile, javaProject);
		} catch (IOException | JavaModelException e) {
			// Validation is not possible, return.
			return;
		}
		if (unit == null || !ElementTypeTeller.isModelElement(unit)) {
			// Validation is not possible, return.
			return;
		}

		try {
			ProblemCollector collector = new ProblemCollector(unit, file.getFile());
			unit.accept(new ModelVisitor(collector));
			collector.refreshProblems();
		} catch (JavaModelException e) {
			Logger.sys.error("Error while creating problem collector", e); //$NON-NLS-1$
		}
	}

}

@@ -44,27 +44,144 @@
 java.io.
-IOException
+File;%0Aimport java.io.IOException;%0Aimport java.util.HashMap;%0Aimport java.util.HashSet;%0Aimport java.util.Map;%0Aimport java.util.Set
 ;%0A%0Aimpor
@@ -1034,16 +1034,17 @@
 ipant %7B%0A
+%0A
 %09private
@@ -1251,16 +1251,103 @@
 NLS-1$%0A%0A
+%09private Map%3CIJavaProject, Set%3CBuildContext%3E%3E javaProjectToFileSet = new HashMap%3C%3E();%0A%0A
 %09@Overri
@@ -2237,94 +2237,831 @@
 %0A%09%09%09
-validateFile(file);%0A%09%09%7D%0A%09%7D%0A%0A%09private void validateFile(BuildContext file) %7B%0A%09%09java.io.
+IProject project = file.getFile().getProject();%0A%09%09%09IJavaProject javaProject = JavaCore.create(project);%0A%0A%09%09%09Set%3CBuildContext%3E projectFileSet = javaProjectToFileSet.get(javaProject);%0A%09%09%09if (projectFileSet == null) %7B%0A%09%09%09%09projectFileSet = new HashSet%3C%3E();%0A%09%09%09%09javaProjectToFileSet.put(javaProject, projectFileSet);%0A%09%09%09%7D%0A%0A%09%09%09projectFileSet.add(file);%0A%09%09%7D%0A%09%7D%0A%0A%09@Override%0A%09public void buildFinished(IJavaProject javaProject) %7B%0A%09%09Set%3CBuildContext%3E projectFileSet = javaProjectToFileSet.get(javaProject);%0A%09%09if (projectFileSet == null) %7B // buildFinished might be called without%0A%09%09%09%09%09%09%09%09%09%09// buildStarting%0A%09%09%09return;%0A%09%09%7D%0A%0A%09%09for (BuildContext file : projectFileSet) %7B%0A%09%09%09validateFile(file, javaProject);%0A%09%09%7D%0A%0A%09%09javaProjectToFileSet.remove(javaProject);%0A%09%7D%0A%0A%09private void validateFile(BuildContext file, IJavaProject javaProject) %7B%0A%09%09
 File
@@ -3242,113 +3242,8 @@
 %09%7D%0A%0A
-%09%09IProject project = file.getFile().getProject();%0A%09%09IJavaProject javaProject = JavaCore.create(project);%0A
 %09%09Co

Reschedule JtxtUML validation to the end of the build