<commit_before>/************************************************************************
 * Copyright © 2007-2016 - General Electric Company, All Rights Reserved
 *
 * Project: SADL
 *
 * Description: The Semantic Application Design Language (SADL) is a
 * language for building semantic models and expressing rules that
 * capture additional domain knowledge. The SADL-IDE (integrated
 * development environment) is a set of Eclipse plug-ins that
 * support the editing and testing of semantic models using the
 * SADL language.
 *
 * This software is distributed "AS-IS" without ANY WARRANTIES
 * and licensed under the Eclipse Public License - v 1.0
 * which is available at http://www.eclipse.org/org/documents/epl-v10.php
 *
 ***********************************************************************/
/*
 * generated by Xtext 2.9.0-SNAPSHOT
 */
package com.ge.research.sadl.ui.contentassist

import com.ge.research.sadl.jena.JenaBasedSadlModelProcessor
import com.ge.research.sadl.jena.JenaBasedSadlModelValidator
import com.ge.research.sadl.jena.OntModelProvider
import com.ge.research.sadl.model.DeclarationExtensions
import com.ge.research.sadl.model.OntConceptType
import com.ge.research.sadl.processing.IModelProcessorProvider
import com.ge.research.sadl.processing.SadlConstants
import com.ge.research.sadl.processing.ValidationAcceptor
import com.ge.research.sadl.sADL.BinaryOperation
import com.ge.research.sadl.sADL.Declaration
import com.ge.research.sadl.sADL.Name
import com.ge.research.sadl.sADL.PropOfSubject
import com.ge.research.sadl.sADL.SadlModel
import com.ge.research.sadl.sADL.SadlProperty
import com.ge.research.sadl.sADL.SadlPropertyInitializer
import com.ge.research.sadl.sADL.SadlResource
import com.ge.research.sadl.sADL.SadlSimpleTypeReference
import com.ge.research.sadl.sADL.SubjHasProp
import com.google.common.base.Predicate
import com.google.common.base.Predicates
import com.google.common.collect.Maps
import com.google.inject.Inject
import com.google.inject.Provider
import com.hp.hpl.jena.ontology.OntResource
import java.util.ArrayList
import java.util.HashMap
import java.util.List
import java.util.Map
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.Assignment
import org.eclipse.xtext.CrossReference
import org.eclipse.xtext.EcoreUtil2
import org.eclipse.xtext.GrammarUtil
import org.eclipse.xtext.Keyword
import org.eclipse.xtext.RuleCall
import org.eclipse.xtext.diagnostics.Severity
import org.eclipse.xtext.naming.QualifiedName
import org.eclipse.xtext.resource.EObjectAtOffsetHelper
import org.eclipse.xtext.resource.IEObjectDescription
import org.eclipse.xtext.scoping.impl.FilteringScope
import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext
import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor
import org.eclipse.xtext.util.IAcceptor
import org.eclipse.xtext.validation.Issue
import org.eclipse.xtext.AbstractRule
import org.eclipse.xtext.ui.editor.contentassist.CompletionProposalComputer
import org.eclipse.xtext.ui.editor.contentassist.AbstractContentProposalProvider.NullSafeCompletionProposalAcceptor
import org.eclipse.xtext.AbstractElement
import org.eclipse.xtext.ui.editor.contentassist.IFollowElementAcceptor

/**
 * See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#content-assist
 * on how to customize the content assistant.
 */
class SADLProposalProvider extends AbstractSADLProposalProvider {
	
	@Inject protected DeclarationExtensions declarationExtensions;
	@Inject protected IModelProcessorProvider processorProvider;
	@Inject protected Provider<DeclarationExtensions> extensionProvider;
    @Inject extension ProposalProviderFilterProvider;
	
	protected List<OntConceptType> typeRestrictions
	protected List<String> excludedNamespaces
	
	override void completeSadlModel_BaseUri(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		var rsrcNm = context.resource.URI.lastSegment
		var proposal = "\"http://sadl.org/" + rsrcNm + "\""
		acceptor.accept(createCompletionProposal(proposal, context))
	}
	
	override void completeSadlModel_Alias(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		var rsrcNm = context.resource.URI.trimFileExtension.lastSegment
		var proposal = rsrcNm
		acceptor.accept(createCompletionProposal(proposal, context))
		
	}
	
	override def void completeSadlImport_ImportedResource(EObject model,  Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		val term = assignment.terminal
		val container = EcoreUtil2.getContainerOfType(model, SadlModel)
		
// When there is a partial statement of the form "import ", cursor at end, the call on the next line results in a NullPointerException and no proposals are generated.		
//		val imports = container.imports.map[importedResource.baseUri].toSet
		
// An alternative for the above is the code below, up to the call to lookupCrossReference, which has sufficient not null checks to work
		val imports = new ArrayList<String>()
		val importsList = container.imports
		if (importsList !== null) {
			for (imp:importsList) {
				if (imp !== null) {
					val import = imp.importedResource
					if (import !== null) {
						val impUri = import.baseUri
						if (impUri !== null) {
							imports.add(impUri)
						}
					}
				}
			}
		}

		lookupCrossReference(term as CrossReference, context, acceptor, new Predicate<IEObjectDescription>() {
					override apply(IEObjectDescription input) {
						val fnm = input.EObjectURI.lastSegment
						if (fnm !== null && (fnm.toLowerCase().endsWith(".sadl") || 
							fnm.toLowerCase().endsWith(".owl") ||
							 fnm.toLowerCase().endsWith(".n3") || 
							 fnm.toLowerCase().endsWith(".ntriple") ||
							 fnm.toLowerCase().endsWith(".nt")) && 
							!fnm.equals("SadlImplicitModel.sadl") &&
							!imports.contains(input.name.toString)
						) {
							return true;
						}
						return false
					}
					
				})
	}

	// Creates a proposal for an EOS terminal.  Xtext can't guess (at
    // the moment) what the valid values for a terminal rule are, so
    // that's why there is no automatic content assist for EOS.
	override void complete_EOS(EObject model, RuleCall ruleCall, 
	        ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		var proposalText = ".\n";
		var displayText = ". - End of Sentence";
		var image = getImage(model);
		var proposal = createCompletionProposal(proposalText, displayText, image, context);
		acceptor.accept(proposal);
	}

	override void completeKeyword(Keyword keyword, ContentAssistContext context,
			ICompletionProposalAcceptor acceptor) {
		if (!includeKeyword(keyword, context)) {
			return
		}
		var proposalText = keyword.getValue();
		if (isInvokedDirectlyAfterKeyword(context) && requireSpaceBefore(keyword, context) && !hasSpaceBefore(context)) {
			proposalText = " " + proposalText;
		}
		if (requireSpaceAfter(keyword, context) && !hasSpaceAfter(context)) {
			proposalText = proposalText + " ";
		}
	
		var proposal = createCompletionProposal(proposalText, getKeywordDisplayString(keyword),
				getImage(keyword), context);
		getPriorityHelper().adjustKeywordPriority(proposal, context.getPrefix());
		acceptor.accept(proposal);
	}
	

	@Override
	override completeRuleCall(RuleCall ruleCall, ContentAssistContext contentAssistContext,
			ICompletionProposalAcceptor acceptor) {
		val calledRule = ruleCall.getRule();
		val methodName = "complete_" + calledRule.getName();
		invokeMethod(methodName, acceptor, contentAssistContext.getCurrentModel(), ruleCall, contentAssistContext);
		
		val a = acceptor as org.eclipse.xtext.ui.editor.contentassist.AbstractContentProposalProvider.NullSafeCompletionProposalAcceptor;
		val c = a.delegate as CompletionProposalComputer
		val field = c.class.getDeclaredField('proposals')
		field.accessible = true;
		println(field.get(c))
		println();
		
	}

	override void createProposals(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		if (excludedNamespaces !== null) excludedNamespaces.clear
		if (typeRestrictions !== null) typeRestrictions.clear
		super.createProposals(context, acceptor)
	}
	
	override void completeSadlPropertyInitializer_Value(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		System.out.println("completeSadlPropertyInitializer_Value called")
	}
	
//	// this is without filtering out duplicates
//	override void lookupCrossReference(CrossReference crossReference, ContentAssistContext context,
//			ICompletionProposalAcceptor acceptor) {
//		lookupCrossReference(crossReference, context, acceptor,
//				Predicates.<IEObjectDescription> alwaysTrue());
//	}

	private def createValidator(Resource resource) {
		val issues = <Issue>newArrayList();
		val acceptor = new ValidationAcceptor([issues.add(it)] as IAcceptor<Issue>);
		val model = OntModelProvider.find(resource);
		val ^extension = extensionProvider.get;<commit_msg>Added data type support for property assignments.<commit_after>/************************************************************************
 * Copyright © 2007-2016 - General Electric Company, All Rights Reserved
 *
 * Project: SADL
 *
 * Description: The Semantic Application Design Language (SADL) is a
 * language for building semantic models and expressing rules that
 * capture additional domain knowledge. The SADL-IDE (integrated
 * development environment) is a set of Eclipse plug-ins that
 * support the editing and testing of semantic models using the
 * SADL language.
 *
 * This software is distributed "AS-IS" without ANY WARRANTIES
 * and licensed under the Eclipse Public License - v 1.0
 * which is available at http://www.eclipse.org/org/documents/epl-v10.php
 *
 ***********************************************************************/
/*
 * generated by Xtext 2.9.0-SNAPSHOT
 */
package com.ge.research.sadl.ui.contentassist

import com.ge.research.sadl.jena.JenaBasedSadlModelProcessor
import com.ge.research.sadl.jena.JenaBasedSadlModelValidator
import com.ge.research.sadl.jena.OntModelProvider
import com.ge.research.sadl.model.DeclarationExtensions
import com.ge.research.sadl.model.OntConceptType
import com.ge.research.sadl.processing.IModelProcessorProvider
import com.ge.research.sadl.processing.SadlConstants
import com.ge.research.sadl.processing.ValidationAcceptor
import com.ge.research.sadl.sADL.BinaryOperation
import com.ge.research.sadl.sADL.Declaration
import com.ge.research.sadl.sADL.Name
import com.ge.research.sadl.sADL.PropOfSubject
import com.ge.research.sadl.sADL.SadlModel
import com.ge.research.sadl.sADL.SadlProperty
import com.ge.research.sadl.sADL.SadlPropertyInitializer
import com.ge.research.sadl.sADL.SadlResource
import com.ge.research.sadl.sADL.SadlSimpleTypeReference
import com.ge.research.sadl.sADL.SubjHasProp
import com.google.common.base.Predicate
import com.google.common.base.Predicates
import com.google.common.collect.Maps
import com.google.inject.Inject
import com.google.inject.Provider
import com.hp.hpl.jena.ontology.OntResource
import java.util.ArrayList
import java.util.HashMap
import java.util.List
import java.util.Map
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.Assignment
import org.eclipse.xtext.CompoundElement
import org.eclipse.xtext.CrossReference
import org.eclipse.xtext.EcoreUtil2
import org.eclipse.xtext.EnumLiteralDeclaration
import org.eclipse.xtext.EnumRule
import org.eclipse.xtext.GrammarUtil
import org.eclipse.xtext.Keyword
import org.eclipse.xtext.RuleCall
import org.eclipse.xtext.diagnostics.Severity
import org.eclipse.xtext.naming.QualifiedName
import org.eclipse.xtext.resource.IEObjectDescription
import org.eclipse.xtext.scoping.impl.FilteringScope
import org.eclipse.xtext.ui.editor.contentassist.AbstractContentProposalProvider
import org.eclipse.xtext.ui.editor.contentassist.CompletionProposalComputer
import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext
import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor
import org.eclipse.xtext.util.IAcceptor
import org.eclipse.xtext.validation.Issue

/**
 * See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#content-assist
 * on how to customize the content assistant.
 */
class SADLProposalProvider extends AbstractSADLProposalProvider {
	
	@Inject protected DeclarationExtensions declarationExtensions;
	@Inject protected IModelProcessorProvider processorProvider;
	@Inject protected Provider<DeclarationExtensions> extensionProvider;
    @Inject extension ProposalProviderFilterProvider;
	
	protected List<OntConceptType> typeRestrictions
	protected List<String> excludedNamespaces
	
	override void completeSadlModel_BaseUri(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		var rsrcNm = context.resource.URI.lastSegment
		var proposal = "\"http://sadl.org/" + rsrcNm + "\""
		acceptor.accept(createCompletionProposal(proposal, context))
	}
	
	override void completeSadlModel_Alias(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		var rsrcNm = context.resource.URI.trimFileExtension.lastSegment
		var proposal = rsrcNm
		acceptor.accept(createCompletionProposal(proposal, context))
		
	}
	
	override def void completeSadlImport_ImportedResource(EObject model,  Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		val term = assignment.terminal
		val container = EcoreUtil2.getContainerOfType(model, SadlModel)
		
// When there is a partial statement of the form "import ", cursor at end, the call on the next line results in a NullPointerException and no proposals are generated.		
//		val imports = container.imports.map[importedResource.baseUri].toSet
		
// An alternative for the above is the code below, up to the call to lookupCrossReference, which has sufficient not null checks to work
		val imports = new ArrayList<String>()
		val importsList = container.imports
		if (importsList !== null) {
			for (imp:importsList) {
				if (imp !== null) {
					val import = imp.importedResource
					if (import !== null) {
						val impUri = import.baseUri
						if (impUri !== null) {
							imports.add(impUri)
						}
					}
				}
			}
		}

		lookupCrossReference(term as CrossReference, context, acceptor, new Predicate<IEObjectDescription>() {
					override apply(IEObjectDescription input) {
						val fnm = input.EObjectURI.lastSegment
						if (fnm !== null && (fnm.toLowerCase().endsWith(".sadl") || 
							fnm.toLowerCase().endsWith(".owl") ||
							 fnm.toLowerCase().endsWith(".n3") || 
							 fnm.toLowerCase().endsWith(".ntriple") ||
							 fnm.toLowerCase().endsWith(".nt")) && 
							!fnm.equals("SadlImplicitModel.sadl") &&
							!imports.contains(input.name.toString)
						) {
							return true;
						}
						return false
					}
					
				})
	}

	// Creates a proposal for an EOS terminal.  Xtext can't guess (at
    // the moment) what the valid values for a terminal rule are, so
    // that's why there is no automatic content assist for EOS.
	override void complete_EOS(EObject model, RuleCall ruleCall, 
	        ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		var proposalText = ".\n";
		var displayText = ". - End of Sentence";
		var image = getImage(model);
		var proposal = createCompletionProposal(proposalText, displayText, image, context);
		acceptor.accept(proposal);
	}

	override void completeKeyword(Keyword keyword, ContentAssistContext context,
			ICompletionProposalAcceptor acceptor) {
		if (!includeKeyword(keyword, context)) {
			return
		}
		var proposalText = keyword.getValue();
		if (isInvokedDirectlyAfterKeyword(context) && requireSpaceBefore(keyword, context) && !hasSpaceBefore(context)) {
			proposalText = " " + proposalText;
		}
		if (requireSpaceAfter(keyword, context) && !hasSpaceAfter(context)) {
			proposalText = proposalText + " ";
		}
	
		var proposal = createCompletionProposal(proposalText, getKeywordDisplayString(keyword),
				getImage(keyword), context);
		getPriorityHelper().adjustKeywordPriority(proposal, context.getPrefix());
		acceptor.accept(proposal);
	}
	

	@Override
	override completeRuleCall(RuleCall ruleCall, ContentAssistContext contentAssistContext,
			ICompletionProposalAcceptor acceptor) {
		val calledRule = ruleCall.getRule();
		val methodName = "complete_" + calledRule.getName();
		invokeMethod(methodName, acceptor, contentAssistContext.getCurrentModel(), ruleCall, contentAssistContext);
		
		val a = acceptor as org.eclipse.xtext.ui.editor.contentassist.AbstractContentProposalProvider.NullSafeCompletionProposalAcceptor;
		val c = a.delegate as CompletionProposalComputer
		val field = c.class.getDeclaredField('proposals')
		field.accessible = true;
		println(field.get(c))
		println();
		
	}
	
	override void complete_SadlDataType(EObject model, RuleCall ruleCall, ContentAssistContext context,
		ICompletionProposalAcceptor acceptor) {

		// This is required to make sure data types are available for properties.
		if (model?.eContainer instanceof SadlProperty) {
			val rule = ruleCall.rule;
			if (rule instanceof EnumRule) {
				val alternatives = rule.alternatives;
				if (alternatives instanceof CompoundElement) {
					alternatives.elements.filter(EnumLiteralDeclaration).forEach [
						val proposal = literal?.value;
						if (!proposal.nullOrEmpty) {
							acceptor.accept(createCompletionProposal(proposal, proposal, image, context));
						}
					];
				}
			}
		}
	}

	override void createProposals(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		if (excludedNamespaces !== null) excludedNamespaces.clear
		if (typeRestrictions !== null) typeRestrictions.clear
		super.createProposals(context, acceptor)
	}
	
	override void completeSadlPropertyInitializer_Value(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		System.out.println("completeSadlPropertyInitializer_Value called")
	}
	
//	// this is without filtering out duplicates
//	override void lookupCrossReference(CrossReference crossReference, ContentAssistContext context,
//			ICompletionProposalAcceptor acceptor) {
//		lookupCrossReference(crossReference, context, acceptor,
//				Predicates.<IEObjectDescription> alwaysTrue());
//	}

	private def createValidator(Resource resource) {
		val issues = <Issue>newArrayList();
		val acceptor = new ValidationAcceptor([issues.add(it)] as IAcceptor<Issue>);
		val model = OntModelProvider.find(resource);
		val ^extension = extensionProvider.get;
{'fraction_non_alphanumeric': 0.10559897910352528, 'fraction_numerical': 0.002233211038443133, 'mean_word_length': 5.069054533720555, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1925496', 'n_tokens_mistral': 5998, 'n_tokens_neox': 5360, 'n_words': 1223}