/*
 * 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.
 *
 * Contributions from 2013-2017 where performed either by US government
 * employees, or under US Veterans Health Administration contracts.
 *
 * US Veterans Health Administration contributions by government employees
 * are work of the U.S. Government and are not subject to copyright
 * protection in the United States. Portions contributed by government
 * employees are USGovWork (17USC §105). Not subject to copyright.
 * 
 * Contribution by contractors to the US Veterans Health Administration
 * during this period are contractually contributed under the
 * Apache License, Version 2.0.
 *
 * See: https://www.usa.gov/government-works
 * 
 * Contributions prior to 2013:
 *
 * Copyright (C) International Health Terminology Standards Development Organisation.
 * Licensed under the Apache License, Version 2.0.
 *
 */

package sh.isaac.mojo;

import java.util.ArrayList;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import sh.isaac.api.AssemblageService;
import sh.isaac.api.Get;
import sh.isaac.api.IdentifiedObjectService;
import sh.isaac.api.IdentifierService;

/**
 * @author darmbrust
 *         Simply utility mojo to warn about semantics that reference a missing component.
 */
@Mojo(name = "scan-refs", defaultPhase = LifecyclePhase.PROCESS_RESOURCES)
public class ScanForMissingConcepts extends AbstractMojo
{
	/**
	 * Execute.
	 *
	 * @throws MojoExecutionException the mojo execution exception
	 */
	@Override
	public void execute() throws MojoExecutionException
	{
		Headless.setHeadless();

		IdentifierService is = Get.identifierService();
		IdentifiedObjectService ios = Get.identifiedObjectService();
		AssemblageService as = Get.assemblageService();

		{
			ArrayList<UUID> missingComponents = new ArrayList<>();
			AtomicInteger semanticScanCount = new AtomicInteger();
			Get.assemblageService().getSemanticChronologyStream(true).forEach(sc -> {
				semanticScanCount.getAndIncrement();
				if (ios.getChronology(sc.getReferencedComponentNid()).isEmpty())
				{
					UUID temp = is.getUuidPrimordialForNid(sc.getReferencedComponentNid());
					synchronized(missingComponents) {
						missingComponents.add(temp);
					}
				}
			});
			if (missingComponents.size() > 0)
			{
				getLog().error("There are " + missingComponents.size() + " referenced components which are not present in the database");
				int breaker = 0;
				for (UUID uuid : missingComponents)
				{
					getLog().error("Missing: " + uuid);
					breaker++;
					if (breaker > 100)
					{
						break;
					}
				}
			}
			else
			{
				getLog().info("No missing components found.  Scanned " + semanticScanCount.get() + " semantics");
			}
		}

		{
			AtomicInteger conceptScanCount = new AtomicInteger();
			ArrayList<UUID> missingDescriptions = new ArrayList<>();
			Get.conceptService().getConceptChronologyStream(true).forEach(c -> {
				conceptScanCount.getAndIncrement();
				if (as.getDescriptionsForComponent(c.getNid()).size() == 0)
				{
					UUID temp = is.getUuidPrimordialForNid(c.getNid());
					synchronized(missingDescriptions) {
						missingDescriptions.add(temp);
					}
				}
			});
			if (missingDescriptions.size() > 0)
			{
				getLog().error("There are " + missingDescriptions.size() + " concepts which have 0 descriptions");
				int breaker = 0;
				for (UUID uuid : missingDescriptions)
				{
					getLog().error("Missing Description: " + uuid);
					breaker++;
					if (breaker > 100)
					{
						break;
					}
				}
			}
			else
			{
				getLog().info("No missing descriptions found.  Scanned " + conceptScanCount.get() + " concepts");
			}
		}
	}
}

@@ -2530,24 +2530,77 @@
 ayList%3C%3E();%0A
+%09%09%09AtomicInteger missingCount = new AtomicInteger();%0A
 %09%09%09AtomicInt
@@ -2830,32 +2830,110 @@
 sEmpty())%0A%09%09%09%09%7B%0A
+%09%09%09%09%09int newSize = missingCount.incrementAndGet();%0A%09%09%09%09%09if (newSize %3C 100) %7B%0A%09
 %09%09%09%09%09UUID temp =
@@ -2985,32 +2985,33 @@
 omponentNid());%0A
+%09
 %09%09%09%09%09synchronize
@@ -3035,24 +3035,25 @@
 ts) %7B%0A%09%09%09%09%09%09
+%09
 missingCompo
@@ -3061,32 +3061,40 @@
 ents.add(temp);%0A
+%09%09%09%09%09%09%7D%0A
 %09%09%09%09%09%7D%0A%09%09%09%09%7D%0A%09%09%09
@@ -3113,29 +3113,23 @@
 issingCo
-mponents.size
+unt.get
 () %3E 0)%0A
@@ -3180,21 +3180,15 @@
 ngCo
-mponents.size
+unt.get
 () +
@@ -3249,39 +3249,30 @@
 database
-%22);%0A%09%09%09%09int breaker = 0
+.  Examples:%22)
 ;%0A%09%09%09%09fo
@@ -3356,75 +3356,8 @@
 d);%0A
-%09%09%09%09%09breaker++;%0A%09%09%09%09%09if (breaker %3E 100)%0A%09%09%09%09%09%7B%0A%09%09%09%09%09%09break;%0A%09%09%09%09%09%7D%0A
 %09%09%09%09

improve performance of missing components scan