<commit_before>package com.temenos.interaction.sdk;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.odata4j.edm.EdmAssociation;
import org.odata4j.edm.EdmAssociationEnd;
import org.odata4j.edm.EdmDataServices;
import org.odata4j.edm.EdmEntityType;
import org.odata4j.edm.EdmMultiplicity;
import org.odata4j.edm.EdmNavigationProperty;
import org.odata4j.edm.EdmProperty;
import org.odata4j.edm.EdmSimpleType;
import org.odata4j.edm.EdmType;
import org.odata4j.format.xml.EdmxFormatParser;
import org.odata4j.internal.InternalUtil;
import org.odata4j.stax2.XMLEventReader2;

/**
 * This class is the main entry point to the IRIS SDK. It is a simple front end
 * for generating JPA classes, and associated configuration files. With these
 * classes and config files in place we can then fill a mock database with
 * appropriate values and enable IRIS to respond to resource requests from User
 * Agents.
 * 
 */
public class JPAResponderGen {

	private final static String JPA_CONFIG_FILE = "persistence.xml";
	private final static String SPRING_CONFIG_FILE = "spring-beans.xml";
	private final static String RESPONDER_INSERT_FILE = "responder_insert.sql";

	/*
	 *  create a new instance of the engine
	 */
	VelocityEngine ve = new VelocityEngine();

	public JPAResponderGen() {
		// load .vm templates using classloader
		ve.setProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
		ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".class", ClasspathResourceLoader.class.getName());
		ve.init();
	}

	/**
	 * @precondition File edmxFile exists on the file system
	 * @postcondition JPA Entity classes written to file system as valid Java source
	 * @postcondition JPA persistence.xml written to file system, configured to inmemory database
	 * @postcondition a boolean flag indicating a successful result will be returned
	 * @invariant enough free space on the file system
	 * @param edmxFile
	 * @param srcOutputPath
	 * @param configOutputPath
	 */
	public boolean generateArtifacts(File edmxFile, File sourceOutputPath, File configOutputPath) {
		try {
			InputStream is = new FileInputStream(edmxFile);
			return generateArtifacts(is, sourceOutputPath, configOutputPath);
		} catch (FileNotFoundException e) {
			return false;
		}
	}
	
	/**
	 * Generate JPA responder artifacts.  Including JPA classes, persistence.xml, and DML bootstrapping.
	 * @param is
	 * @param srcOutputPath
	 * @param configOutputPath
	 * @return
	 */
	public boolean generateArtifacts(InputStream is, File srcOutputPath, File configOutputPath) {
		XMLEventReader2 reader =  InternalUtil.newXMLEventReader(new BufferedReader(new InputStreamReader(is)));
		EdmDataServices ds = new EdmxFormatParser().parseMetadata(reader);
		
		boolean ok = true;
		List<ResourceInfo> resourcesInfo = new ArrayList<ResourceInfo>();
		
		// generate JPA classes
		for (EdmEntityType t : ds.getEntityTypes()) {
			JPAEntityInfo entityInfo = createJPAEntityInfoFromEdmEntityType(t);
			String fqOutputDir = srcOutputPath.getPath() + "/" + entityInfo.getPackageAsPath();
			new File(fqOutputDir).mkdirs();
			if (writeClass(formClassFilename(srcOutputPath.getPath(), entityInfo), generateJPAEntityClass(entityInfo))) {
				String resourcePath = "/" + entityInfo.getClazz() + "/{id}";
				String commandType = "com.temenos.interaction.commands.odata.GETEntityCommand"; 
				resourcesInfo.add(new ResourceInfo(resourcePath, entityInfo, commandType));
				
				//Navigation properties linking to itself with multiplicity are considered to relate a resource with a collection resource
				if(t.getNavigationProperties() != null) {
					for (EdmNavigationProperty np : t.getNavigationProperties()) {
						EdmAssociation ea = np.getRelationship();
						EdmAssociationEnd end1 = ea.getEnd1();
						EdmAssociationEnd end2 = ea.getEnd2();
						if(end1.getType().equals(end2.getType()) && (
								end1.getMultiplicity().equals(EdmMultiplicity.MANY) ||
								end2.getMultiplicity().equals(EdmMultiplicity.MANY))) {
							JPAEntityInfo entityFeedInfo = createJPAEntityInfoFromEdmEntityType(t);
							entityFeedInfo.setFeedEntity();		//This is a feed of OEntities and should not exist as a JPA entity 
							resourcePath = "/" + entityFeedInfo.getClazz();
							commandType = "com.temenos.interaction.commands.odata.GETEntitiesCommand"; 
							resourcesInfo.add(new ResourceInfo(resourcePath, entityFeedInfo, commandType));
						}					
					}
				}
					
			} else {<commit_msg>Change the Interaction SDK to generate responders with resource paths which comply with the ODATA URI template, i.e. from myCollection/{id} to myCollection({id}).<commit_after>package com.temenos.interaction.sdk;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.odata4j.edm.EdmAssociation;
import org.odata4j.edm.EdmAssociationEnd;
import org.odata4j.edm.EdmDataServices;
import org.odata4j.edm.EdmEntityType;
import org.odata4j.edm.EdmMultiplicity;
import org.odata4j.edm.EdmNavigationProperty;
import org.odata4j.edm.EdmProperty;
import org.odata4j.edm.EdmSimpleType;
import org.odata4j.edm.EdmType;
import org.odata4j.format.xml.EdmxFormatParser;
import org.odata4j.internal.InternalUtil;
import org.odata4j.stax2.XMLEventReader2;

/**
 * This class is the main entry point to the IRIS SDK. It is a simple front end
 * for generating JPA classes, and associated configuration files. With these
 * classes and config files in place we can then fill a mock database with
 * appropriate values and enable IRIS to respond to resource requests from User
 * Agents.
 * 
 */
public class JPAResponderGen {

	private final static String JPA_CONFIG_FILE = "persistence.xml";
	private final static String SPRING_CONFIG_FILE = "spring-beans.xml";
	private final static String RESPONDER_INSERT_FILE = "responder_insert.sql";

	/*
	 *  create a new instance of the engine
	 */
	VelocityEngine ve = new VelocityEngine();

	public JPAResponderGen() {
		// load .vm templates using classloader
		ve.setProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
		ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".class", ClasspathResourceLoader.class.getName());
		ve.init();
	}

	/**
	 * @precondition File edmxFile exists on the file system
	 * @postcondition JPA Entity classes written to file system as valid Java source
	 * @postcondition JPA persistence.xml written to file system, configured to inmemory database
	 * @postcondition a boolean flag indicating a successful result will be returned
	 * @invariant enough free space on the file system
	 * @param edmxFile
	 * @param srcOutputPath
	 * @param configOutputPath
	 */
	public boolean generateArtifacts(File edmxFile, File sourceOutputPath, File configOutputPath) {
		try {
			InputStream is = new FileInputStream(edmxFile);
			return generateArtifacts(is, sourceOutputPath, configOutputPath);
		} catch (FileNotFoundException e) {
			return false;
		}
	}
	
	/**
	 * Generate JPA responder artifacts.  Including JPA classes, persistence.xml, and DML bootstrapping.
	 * @param is
	 * @param srcOutputPath
	 * @param configOutputPath
	 * @return
	 */
	public boolean generateArtifacts(InputStream is, File srcOutputPath, File configOutputPath) {
		XMLEventReader2 reader =  InternalUtil.newXMLEventReader(new BufferedReader(new InputStreamReader(is)));
		EdmDataServices ds = new EdmxFormatParser().parseMetadata(reader);
		
		boolean ok = true;
		List<ResourceInfo> resourcesInfo = new ArrayList<ResourceInfo>();
		
		// generate JPA classes
		for (EdmEntityType t : ds.getEntityTypes()) {
			JPAEntityInfo entityInfo = createJPAEntityInfoFromEdmEntityType(t);
			String fqOutputDir = srcOutputPath.getPath() + "/" + entityInfo.getPackageAsPath();
			new File(fqOutputDir).mkdirs();
			if (writeClass(formClassFilename(srcOutputPath.getPath(), entityInfo), generateJPAEntityClass(entityInfo))) {
				String resourcePath = "/" + entityInfo.getClazz() + "({id})";
				String commandType = "com.temenos.interaction.commands.odata.GETEntityCommand"; 
				resourcesInfo.add(new ResourceInfo(resourcePath, entityInfo, commandType));
				
				//Navigation properties linking to itself with multiplicity are considered to relate a resource with a collection resource
				if(t.getNavigationProperties() != null) {
					for (EdmNavigationProperty np : t.getNavigationProperties()) {
						EdmAssociation ea = np.getRelationship();
						EdmAssociationEnd end1 = ea.getEnd1();
						EdmAssociationEnd end2 = ea.getEnd2();
						if(end1.getType().equals(end2.getType()) && (
								end1.getMultiplicity().equals(EdmMultiplicity.MANY) ||
								end2.getMultiplicity().equals(EdmMultiplicity.MANY))) {
							JPAEntityInfo entityFeedInfo = createJPAEntityInfoFromEdmEntityType(t);
							entityFeedInfo.setFeedEntity();		//This is a feed of OEntities and should not exist as a JPA entity 
							resourcePath = "/" + entityFeedInfo.getClazz();
							commandType = "com.temenos.interaction.commands.odata.GETEntitiesCommand"; 
							resourcesInfo.add(new ResourceInfo(resourcePath, entityFeedInfo, commandType));
						}					
					}
				}
					
			} else {
{'fraction_non_alphanumeric': 0.0937686641449333, 'fraction_numerical': 0.004578936890304599, 'mean_word_length': 4.724786324786325, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 10}, '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': '5046845', 'n_tokens_mistral': 3288, 'n_tokens_neox': 2912, 'n_words': 759}