<commit_before>/**
 * 
 */
package gov.va.isaac.util;

import gov.va.isaac.AppContext;
import gov.va.isaac.ExtendedAppContext;
import gov.va.isaac.config.profiles.UserProfile;
import gov.va.isaac.config.profiles.UserProfileBindings;
import gov.va.isaac.config.profiles.UserProfileManager;
import gov.va.isaac.config.users.InvalidUserException;
import gov.vha.isaac.cradle.sememe.SememeProvider;
import gov.vha.isaac.metadata.coordinates.StampCoordinates;
import gov.vha.isaac.metadata.source.IsaacMetadataAuxiliaryBinding;
import gov.vha.isaac.ochre.api.Get;
import gov.vha.isaac.ochre.api.IdentifierService;
import gov.vha.isaac.ochre.api.LookupService;
import gov.vha.isaac.ochre.api.chronicle.LatestVersion;
import gov.vha.isaac.ochre.api.component.concept.ConceptChronology;
import gov.vha.isaac.ochre.api.component.concept.ConceptService;
import gov.vha.isaac.ochre.api.component.concept.ConceptSnapshot;
import gov.vha.isaac.ochre.api.component.concept.ConceptSnapshotService;
import gov.vha.isaac.ochre.api.component.concept.ConceptVersion;
import gov.vha.isaac.ochre.api.component.sememe.SememeChronology;
import gov.vha.isaac.ochre.api.component.sememe.SememeSnapshotService;
import gov.vha.isaac.ochre.api.component.sememe.version.DescriptionSememe;
import gov.vha.isaac.ochre.api.component.sememe.version.SememeVersion;
import gov.vha.isaac.ochre.api.coordinate.LanguageCoordinate;
import gov.vha.isaac.ochre.api.coordinate.PremiseType;
import gov.vha.isaac.ochre.api.coordinate.StampCoordinate;
import gov.vha.isaac.ochre.api.coordinate.TaxonomyCoordinate;
import gov.vha.isaac.ochre.api.relationship.RelationshipVersionAdaptor;
import gov.vha.isaac.ochre.api.tree.Tree;
import gov.vha.isaac.ochre.collections.ConceptSequenceSet;
import gov.vha.isaac.ochre.model.sememe.version.StringSememeImpl;
import gov.vha.isaac.ochre.util.UuidFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author joel
 *
 */
public final class OchreUtility {
	private static final Logger LOG = LoggerFactory.getLogger(OchreUtility.class);

	private OchreUtility() {}

	
	@SuppressWarnings("unchecked")
	public static List<? extends SememeChronology<? extends DescriptionSememe<?>>> getConceptDescriptionList(ConceptChronology<?> cc) {
		@SuppressWarnings("rawtypes")
		List<? extends SememeChronology<? extends DescriptionSememe>> rawList = cc.getConceptDescriptionList();
		
		return (List<? extends SememeChronology<? extends DescriptionSememe<?>>>)rawList;
	}

    @SuppressWarnings("unchecked")
	public static Optional<LatestVersion<? extends ConceptVersion<?>>> getLatestConceptVersion(ConceptChronology<? extends ConceptVersion<?>> cc, StampCoordinate<? extends StampCoordinate<?>> sc) {
		@SuppressWarnings("rawtypes")
		ConceptChronology raw = (ConceptChronology)cc;
    	
    	return raw.getLatestVersion(ConceptVersion.class, sc);
    }
    
	@SuppressWarnings("unchecked")
	public static Optional<LatestVersion<? extends RelationshipVersionAdaptor<?>>> getLatestRelationshipVersionAdaptor(SememeChronology<? extends RelationshipVersionAdaptor<?>> sc, StampCoordinate<? extends StampCoordinate<?>> stampCoordinate) {
		@SuppressWarnings("rawtypes")
		SememeChronology rawSememChronology = (SememeChronology)sc;
		
		return rawSememChronology.getLatestVersion(RelationshipVersionAdaptor.class, stampCoordinate);
	}

	/**
	 * @param nid concept nid
	 * @param stampCoordinate StampCoordinate for retrieving latest LogicGraphSememeImpl
	 * @param premiseType PremiseTypes by which to filter. Passing null disables filtering by PremiseType (returns both STATED and INFERRED)
	 * @return List of RelationshipVersionAdaptor
	 * 
	 * 
	 */
	public static List<RelationshipVersionAdaptor<?>> getRelationshipListOriginatingFromConcept(int nid, StampCoordinate<? extends StampCoordinate<?>> stampCoordinate, boolean historical, PremiseType premiseType, Integer relTypeSequence) {
		List<RelationshipVersionAdaptor<?>> allRelationships = new ArrayList<>();
		
		// Code for examining LogicGraphs only
//		LogicGraphSememeImpl latestStatedGraph = null;
//		LogicGraphSememeImpl latestInferredGraph = null;
//
//		if (premiseType == null || premiseType == PremiseType.STATED)
//		{
//			Optional<SememeChronology<? extends SememeVersion<?>>> defChronologyOptional = Get.statedDefinitionChronology(nid);
//
//			SememeChronology rawDefChronology = defChronologyOptional.get();
//			Optional<LatestVersion<LogicGraphSememeImpl>> latestGraphLatestVersionOptional = rawDefChronology.getLatestVersion(LogicGraphSememeImpl.class, stampCoordinate);
//			latestStatedGraph = latestGraphLatestVersionOptional.get().value();
//		}	
//		
//		if (premiseType == null || premiseType == PremiseType.INFERRED)
//		{
//			Optional<SememeChronology<? extends SememeVersion<?>>> defChronologyOptional = Get.inferredDefinitionChronology(nid);
//
//			SememeChronology rawDefChronology = defChronologyOptional.get();
//			Optional<LatestVersion<LogicGraphSememeImpl>> latestGraphLatestVersionOptional = rawDefChronology.getLatestVersion(LogicGraphSememeImpl.class, stampCoordinate);
//			latestInferredGraph = latestGraphLatestVersionOptional.get().value();
//		}
		
		List<? extends SememeChronology<? extends RelationshipVersionAdaptor<?>>> outgoingRelChronicles = Get.conceptService().getConcept(nid).getRelationshipListOriginatingFromConcept();
		for (SememeChronology<? extends RelationshipVersionAdaptor<?>> chronicle : outgoingRelChronicles)
		{
			if (historical) {
				for (RelationshipVersionAdaptor<?> rv : chronicle.getVersionList())
				{
					// Ensure that RelationshipVersionAdaptor corresponds to latest LogicGraph
					if (premiseType == null || premiseType == rv.getPremiseType()) {
						allRelationships.add(rv);
						LOG.debug("getLatestRelationshipListOriginatingFromConcept(" + Get.conceptDescriptionText(nid) + ", stampCoord, (PremiseType)" + (premiseType != null ? premiseType.name() : null) + ") adding " + OchreUtility.toString(rv));
					}
				}
			} else {
				Optional<LatestVersion<? extends RelationshipVersionAdaptor<?>>> latest = getLatestRelationshipVersionAdaptor(chronicle, stampCoordinate);
				if (latest.isPresent() && latest.get().value() != null
						&& (premiseType == null || premiseType == latest.get().value().getPremiseType())
						&& (relTypeSequence == null || relTypeSequence == latest.get().value().getTypeSequence())) {
					allRelationships.add(latest.get().value());
				}
			}
		}
		return allRelationships;
	}
	
	public static Set<ConceptVersion<?>> getPathConcepts() {
		Stream<SememeChronology<? extends SememeVersion<?>>> sememes = Get.sememeService().getSememesFromAssemblage(IsaacMetadataAuxiliaryBinding.PATHS_ASSEMBLAGE.getConceptSequence());
		//LOG.debug("Loaded {} sememes from assemblage {}", sememes.count(), Get.conceptDescriptionText(IsaacMetadataAuxiliaryBinding.PATHS_ASSEMBLAGE.getNid()));

		final Set<ConceptVersion<?>> pathConcepts = new HashSet<>();
		Consumer<? super SememeChronology<? extends SememeVersion<?>>> action = new Consumer<SememeChronology<? extends SememeVersion<?>>>() {
			@Override
			public void accept(SememeChronology<? extends SememeVersion<?>> t) {
				ConceptChronology<? extends ConceptVersion<?>> pathCC = Get.conceptService().getConcept(t.getReferencedComponentNid());
				
				Optional<LatestVersion<? extends ConceptVersion<?>>> latestPathConceptVersion = getLatestConceptVersion(pathCC, StampCoordinates.getDevelopmentLatest());
				if (latestPathConceptVersion.isPresent()) {
					pathConcepts.add(latestPathConceptVersion.get().value());
				}
			}
		};
		sememes.distinct().forEach(action);

		if (pathConcepts.isEmpty()) {
			LOG.error("No paths loaded based on membership in {}", IsaacMetadataAuxiliaryBinding.PATHS_ASSEMBLAGE);
		} else {
			LOG.debug("Loaded {} paths: {}", pathConcepts.size(), pathConcepts);
		}
			
		return Collections.unmodifiableSet(pathConcepts);
	}

	public static ConceptSnapshotService conceptSnapshotService(TaxonomyCoordinate<?> vc) {
		return conceptSnapshotService(vc.getStampCoordinate(), vc.getLanguageCoordinate());
	}
	public static ConceptSnapshotService conceptSnapshotService(StampCoordinate<? extends StampCoordinate<?>> stampCoordinate, LanguageCoordinate languageCoordinate) {
		return LookupService.getService(ConceptService.class).getSnapshot(stampCoordinate, languageCoordinate);
	}

	@Deprecated
	public static String conceptDescriptionText(int conceptId, TaxonomyCoordinate<?> vc) {
		return conceptDescriptionText(conceptId, conceptSnapshotService(vc));
	}
	public static String conceptDescriptionText(int conceptId, ConceptSnapshotService snapshot) {
		Optional<LatestVersion<DescriptionSememe<?>>> descriptionOptional = snapshot.getDescriptionOptional(conceptId);
		if (descriptionOptional.isPresent()) {
			return descriptionOptional.get().value().getText();
		}

		return null;<commit_msg>get rid of deprecated method<commit_after>/**
 * 
 */
package gov.va.isaac.util;

import gov.va.isaac.AppContext;
import gov.va.isaac.ExtendedAppContext;
import gov.va.isaac.config.profiles.UserProfile;
import gov.va.isaac.config.profiles.UserProfileBindings;
import gov.va.isaac.config.profiles.UserProfileManager;
import gov.va.isaac.config.users.InvalidUserException;
import gov.vha.isaac.cradle.sememe.SememeProvider;
import gov.vha.isaac.metadata.coordinates.StampCoordinates;
import gov.vha.isaac.metadata.source.IsaacMetadataAuxiliaryBinding;
import gov.vha.isaac.ochre.api.Get;
import gov.vha.isaac.ochre.api.IdentifierService;
import gov.vha.isaac.ochre.api.LookupService;
import gov.vha.isaac.ochre.api.chronicle.LatestVersion;
import gov.vha.isaac.ochre.api.component.concept.ConceptChronology;
import gov.vha.isaac.ochre.api.component.concept.ConceptService;
import gov.vha.isaac.ochre.api.component.concept.ConceptSnapshot;
import gov.vha.isaac.ochre.api.component.concept.ConceptSnapshotService;
import gov.vha.isaac.ochre.api.component.concept.ConceptVersion;
import gov.vha.isaac.ochre.api.component.sememe.SememeChronology;
import gov.vha.isaac.ochre.api.component.sememe.SememeSnapshotService;
import gov.vha.isaac.ochre.api.component.sememe.version.DescriptionSememe;
import gov.vha.isaac.ochre.api.component.sememe.version.SememeVersion;
import gov.vha.isaac.ochre.api.coordinate.LanguageCoordinate;
import gov.vha.isaac.ochre.api.coordinate.PremiseType;
import gov.vha.isaac.ochre.api.coordinate.StampCoordinate;
import gov.vha.isaac.ochre.api.coordinate.TaxonomyCoordinate;
import gov.vha.isaac.ochre.api.relationship.RelationshipVersionAdaptor;
import gov.vha.isaac.ochre.api.tree.Tree;
import gov.vha.isaac.ochre.collections.ConceptSequenceSet;
import gov.vha.isaac.ochre.model.sememe.version.StringSememeImpl;
import gov.vha.isaac.ochre.util.UuidFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author joel
 *
 */
public final class OchreUtility {
	private static final Logger LOG = LoggerFactory.getLogger(OchreUtility.class);

	private OchreUtility() {}

	
	@SuppressWarnings("unchecked")
	public static List<? extends SememeChronology<? extends DescriptionSememe<?>>> getConceptDescriptionList(ConceptChronology<?> cc) {
		@SuppressWarnings("rawtypes")
		List<? extends SememeChronology<? extends DescriptionSememe>> rawList = cc.getConceptDescriptionList();
		
		return (List<? extends SememeChronology<? extends DescriptionSememe<?>>>)rawList;
	}

    @SuppressWarnings("unchecked")
	public static Optional<LatestVersion<? extends ConceptVersion<?>>> getLatestConceptVersion(ConceptChronology<? extends ConceptVersion<?>> cc, StampCoordinate<? extends StampCoordinate<?>> sc) {
		@SuppressWarnings("rawtypes")
		ConceptChronology raw = (ConceptChronology)cc;
    	
    	return raw.getLatestVersion(ConceptVersion.class, sc);
    }
    
	@SuppressWarnings("unchecked")
	public static Optional<LatestVersion<? extends RelationshipVersionAdaptor<?>>> getLatestRelationshipVersionAdaptor(SememeChronology<? extends RelationshipVersionAdaptor<?>> sc, StampCoordinate<? extends StampCoordinate<?>> stampCoordinate) {
		@SuppressWarnings("rawtypes")
		SememeChronology rawSememChronology = (SememeChronology)sc;
		
		return rawSememChronology.getLatestVersion(RelationshipVersionAdaptor.class, stampCoordinate);
	}

	/**
	 * @param nid concept nid
	 * @param stampCoordinate StampCoordinate for retrieving latest LogicGraphSememeImpl
	 * @param premiseType PremiseTypes by which to filter. Passing null disables filtering by PremiseType (returns both STATED and INFERRED)
	 * @return List of RelationshipVersionAdaptor
	 * 
	 * 
	 */
	public static List<RelationshipVersionAdaptor<?>> getRelationshipListOriginatingFromConcept(int nid, StampCoordinate<? extends StampCoordinate<?>> stampCoordinate, boolean historical, PremiseType premiseType, Integer relTypeSequence) {
		List<RelationshipVersionAdaptor<?>> allRelationships = new ArrayList<>();
		
		// Code for examining LogicGraphs only
//		LogicGraphSememeImpl latestStatedGraph = null;
//		LogicGraphSememeImpl latestInferredGraph = null;
//
//		if (premiseType == null || premiseType == PremiseType.STATED)
//		{
//			Optional<SememeChronology<? extends SememeVersion<?>>> defChronologyOptional = Get.statedDefinitionChronology(nid);
//
//			SememeChronology rawDefChronology = defChronologyOptional.get();
//			Optional<LatestVersion<LogicGraphSememeImpl>> latestGraphLatestVersionOptional = rawDefChronology.getLatestVersion(LogicGraphSememeImpl.class, stampCoordinate);
//			latestStatedGraph = latestGraphLatestVersionOptional.get().value();
//		}	
//		
//		if (premiseType == null || premiseType == PremiseType.INFERRED)
//		{
//			Optional<SememeChronology<? extends SememeVersion<?>>> defChronologyOptional = Get.inferredDefinitionChronology(nid);
//
//			SememeChronology rawDefChronology = defChronologyOptional.get();
//			Optional<LatestVersion<LogicGraphSememeImpl>> latestGraphLatestVersionOptional = rawDefChronology.getLatestVersion(LogicGraphSememeImpl.class, stampCoordinate);
//			latestInferredGraph = latestGraphLatestVersionOptional.get().value();
//		}
		
		List<? extends SememeChronology<? extends RelationshipVersionAdaptor<?>>> outgoingRelChronicles = Get.conceptService().getConcept(nid).getRelationshipListOriginatingFromConcept();
		for (SememeChronology<? extends RelationshipVersionAdaptor<?>> chronicle : outgoingRelChronicles)
		{
			if (historical) {
				for (RelationshipVersionAdaptor<?> rv : chronicle.getVersionList())
				{
					// Ensure that RelationshipVersionAdaptor corresponds to latest LogicGraph
					if (premiseType == null || premiseType == rv.getPremiseType()) {
						allRelationships.add(rv);
						LOG.debug("getLatestRelationshipListOriginatingFromConcept(" + Get.conceptDescriptionText(nid) + ", stampCoord, (PremiseType)" + (premiseType != null ? premiseType.name() : null) + ") adding " + OchreUtility.toString(rv));
					}
				}
			} else {
				Optional<LatestVersion<? extends RelationshipVersionAdaptor<?>>> latest = getLatestRelationshipVersionAdaptor(chronicle, stampCoordinate);
				if (latest.isPresent() && latest.get().value() != null
						&& (premiseType == null || premiseType == latest.get().value().getPremiseType())
						&& (relTypeSequence == null || relTypeSequence == latest.get().value().getTypeSequence())) {
					allRelationships.add(latest.get().value());
				}
			}
		}
		return allRelationships;
	}
	
	public static Set<ConceptVersion<?>> getPathConcepts() {
		Stream<SememeChronology<? extends SememeVersion<?>>> sememes = Get.sememeService().getSememesFromAssemblage(IsaacMetadataAuxiliaryBinding.PATHS_ASSEMBLAGE.getConceptSequence());
		//LOG.debug("Loaded {} sememes from assemblage {}", sememes.count(), Get.conceptDescriptionText(IsaacMetadataAuxiliaryBinding.PATHS_ASSEMBLAGE.getNid()));

		final Set<ConceptVersion<?>> pathConcepts = new HashSet<>();
		Consumer<? super SememeChronology<? extends SememeVersion<?>>> action = new Consumer<SememeChronology<? extends SememeVersion<?>>>() {
			@Override
			public void accept(SememeChronology<? extends SememeVersion<?>> t) {
				ConceptChronology<? extends ConceptVersion<?>> pathCC = Get.conceptService().getConcept(t.getReferencedComponentNid());
				
				Optional<LatestVersion<? extends ConceptVersion<?>>> latestPathConceptVersion = getLatestConceptVersion(pathCC, StampCoordinates.getDevelopmentLatest());
				if (latestPathConceptVersion.isPresent()) {
					pathConcepts.add(latestPathConceptVersion.get().value());
				}
			}
		};
		sememes.distinct().forEach(action);

		if (pathConcepts.isEmpty()) {
			LOG.error("No paths loaded based on membership in {}", IsaacMetadataAuxiliaryBinding.PATHS_ASSEMBLAGE);
		} else {
			LOG.debug("Loaded {} paths: {}", pathConcepts.size(), pathConcepts);
		}
			
		return Collections.unmodifiableSet(pathConcepts);
	}

	public static ConceptSnapshotService conceptSnapshotService(TaxonomyCoordinate<?> vc) {
		return conceptSnapshotService(vc.getStampCoordinate(), vc.getLanguageCoordinate());
	}
	public static ConceptSnapshotService conceptSnapshotService(StampCoordinate<? extends StampCoordinate<?>> stampCoordinate, LanguageCoordinate languageCoordinate) {
		return LookupService.getService(ConceptService.class).getSnapshot(stampCoordinate, languageCoordinate);
	}

	public static String conceptDescriptionText(int conceptId, ConceptSnapshotService snapshot) {
		Optional<LatestVersion<DescriptionSememe<?>>> descriptionOptional = snapshot.getDescriptionOptional(conceptId);
		if (descriptionOptional.isPresent()) {
			return descriptionOptional.get().value().getText();
		}

		return null;
{'fraction_non_alphanumeric': 0.1176115471159651, 'fraction_numerical': 0.0003292903792327534, 'mean_word_length': 6.309265944645006, 'pattern_counts': {'":': 0, '<': 156, '<?xml version=': 0, '>': 156, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5104916', 'n_tokens_mistral': 6046, 'n_tokens_neox': 5607, 'n_words': 896}