[teiid-commits] teiid SVN: r4069 - in trunk: build/assembly/jboss-as7 and 29 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Mon May 7 14:40:55 EDT 2012


Author: rareddy
Date: 2012-05-07 14:40:54 -0400 (Mon, 07 May 2012)
New Revision: 4069

Added:
   trunk/build/kits/jboss-as7/modules/org/jboss/teiid/translator/jpa/
   trunk/build/kits/jboss-as7/modules/org/jboss/teiid/translator/jpa/main/
   trunk/connectors/translator-jpa/
   trunk/connectors/translator-jpa/pom.xml
   trunk/connectors/translator-jpa/src/
   trunk/connectors/translator-jpa/src/main/
   trunk/connectors/translator-jpa/src/main/java/
   trunk/connectors/translator-jpa/src/main/java/org/
   trunk/connectors/translator-jpa/src/main/java/org/teiid/
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java
   trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java
   trunk/connectors/translator-jpa/src/main/resources/
   trunk/connectors/translator-jpa/src/main/resources/META-INF/
   trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF
   trunk/connectors/translator-jpa/src/main/resources/META-INF/services/
   trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory
   trunk/connectors/translator-jpa/src/main/resources/org/
   trunk/connectors/translator-jpa/src/main/resources/org/teiid/
   trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/
   trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/
   trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties
   trunk/connectors/translator-jpa/src/test/
   trunk/connectors/translator-jpa/src/test/java/
   trunk/connectors/translator-jpa/src/test/java/org/
   trunk/connectors/translator-jpa/src/test/java/org/teiid/
   trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/
   trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/
   trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java
   trunk/connectors/translator-jpa/src/test/resources/
   trunk/connectors/translator-jpa/src/test/resources/sakila.ddl
   trunk/connectors/translator-jpa/target/
   trunk/connectors/translator-jpa/target/classes/
   trunk/connectors/translator-jpa/target/classes/META-INF/
   trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF
Modified:
   trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java
   trunk/api/src/main/java/org/teiid/metadata/Table.java
   trunk/build/assembly/jboss-as7/dist.xml
   trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml
   trunk/connectors/pom.xml
Log:
TEIID-2011: Adding initial code for supporting the JPA based translator

Modified: trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java	2012-05-07 18:28:19 UTC (rev 4068)
+++ trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -56,4 +56,12 @@
 		this.parent = parent;
 	}
 
+    public Column getColumn(String name) {
+    	for (Column c:columns) {
+    		if (c.getCanonicalName().equals(name.toUpperCase())) {
+    			return c;
+    		}
+    	}
+    	return null;
+    }
 }
\ No newline at end of file

Modified: trunk/api/src/main/java/org/teiid/metadata/Table.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/Table.java	2012-05-07 18:28:19 UTC (rev 4068)
+++ trunk/api/src/main/java/org/teiid/metadata/Table.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -209,6 +209,15 @@
 		this.foriegnKeys = foriegnKeys;
 	}
     
+    public ForeignKey getForeignKey(String name) {
+    	for (ForeignKey fk:this.foriegnKeys) {
+    		if (fk.getName().equals(name)) {
+    			return fk;
+    		}
+    	}
+    	return null;
+    }
+    
     public List<KeyRecord> getIndexes() {
     	return this.indexes;
     }

Modified: trunk/build/assembly/jboss-as7/dist.xml
===================================================================
--- trunk/build/assembly/jboss-as7/dist.xml	2012-05-07 18:28:19 UTC (rev 4068)
+++ trunk/build/assembly/jboss-as7/dist.xml	2012-05-07 18:40:54 UTC (rev 4069)
@@ -388,6 +388,28 @@
           <outputDirectory>modules/org/jboss/teiid/translator/hive/main</outputDirectory>
           <fileMode>0644</fileMode>
         </binaries>
+    </moduleSet>      
+    
+    <moduleSet>
+        <includeSubModules>true</includeSubModules>
+        <useAllReactorProjects>true</useAllReactorProjects>
+        <includes>
+            <include>org.jboss.teiid.connectors:translator-jpa</include>
+        </includes>
+        <binaries>        
+          <includeDependencies>true</includeDependencies>
+          <unpack>false</unpack>
+            <dependencySets>
+                <dependencySet>
+                    <useProjectArtifact>true</useProjectArtifact>
+                    <unpack>false</unpack>
+                    <useTransitiveDependencies>false</useTransitiveDependencies>
+                    <useDefaultExcludes>true</useDefaultExcludes>
+                </dependencySet>
+            </dependencySets>          
+          <outputDirectory>modules/org/jboss/teiid/translator/jpa/main</outputDirectory>
+          <fileMode>0644</fileMode>
+        </binaries>
     </moduleSet>        
      
     <!-- Include the JOPR plugin     

Modified: trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml
===================================================================
--- trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml	2012-05-07 18:28:19 UTC (rev 4068)
+++ trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml	2012-05-07 18:40:54 UTC (rev 4069)
@@ -308,6 +308,7 @@
             <translator name="ws" module="org.jboss.teiid.translator.ws"/>
             <translator name="salesforce" module="org.jboss.teiid.translator.salesforce"/>
             <translator name="hive" module="org.jboss.teiid.translator.hive"/>
+            <translator name="jpa2" module="org.jboss.teiid.translator.jpa"/>
             
         </subsystem>         
         <subsystem xmlns="urn:jboss:domain:threads:1.1">

Modified: trunk/connectors/pom.xml
===================================================================
--- trunk/connectors/pom.xml	2012-05-07 18:28:19 UTC (rev 4068)
+++ trunk/connectors/pom.xml	2012-05-07 18:40:54 UTC (rev 4069)
@@ -105,5 +105,6 @@
     <module>translator-ws</module>
     <module>translator-olap</module>
     <module>translator-hive</module>
+    <module>translator-jpa</module>
   </modules>
 </project>

Added: trunk/connectors/translator-jpa/pom.xml
===================================================================
--- trunk/connectors/translator-jpa/pom.xml	                        (rev 0)
+++ trunk/connectors/translator-jpa/pom.xml	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>connectors</artifactId>
+        <groupId>org.jboss.teiid</groupId>
+        <version>8.1.0.Alpha1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>translator-jpa</artifactId>
+    <groupId>org.jboss.teiid.connectors</groupId>
+    <name>JPA2 Translator</name>
+    <description>This translator provides access to any JPA based entities</description>
+    <properties>
+        <version.org.hibernate.javax.persistence.hibernate-jpa-2.0-api>1.0.1.Final</version.org.hibernate.javax.persistence.hibernate-jpa-2.0-api>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.teiid</groupId>
+            <artifactId>teiid-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.teiid</groupId>
+            <artifactId>teiid-common-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.teiid.connectors</groupId>
+            <artifactId>translator-jdbc</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>   
+        <dependency>
+            <groupId>org.jboss.teiid.connectors</groupId>
+            <artifactId>translator-jdbc</artifactId>
+            <version>${project.version}</version>        
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.resource</groupId>
+            <artifactId>connector-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+            <version>${version.org.hibernate.javax.persistence.hibernate-jpa-2.0-api}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-jar-plugin</artifactId>
+            <configuration>
+              <archive>
+                <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
+              </archive>
+            </configuration>
+          </plugin>
+        </plugins>
+
+        <outputDirectory>target/classes</outputDirectory>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.xml</include>
+                    <include>**/*.properties</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>false</filtering>
+                <excludes>
+                    <exclude>**/*.xml</exclude>
+                    <exclude>**/*.properties</exclude>
+                </excludes>
+            </resource>
+        </resources>
+    </build>
+</project>

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,278 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.teiid.core.util.PropertiesUtils;
+import org.teiid.language.Call;
+import org.teiid.language.Command;
+import org.teiid.language.QueryExpression;
+import org.teiid.metadata.MetadataFactory;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ExecutionFactory;
+import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.ResultSetExecution;
+import org.teiid.translator.SourceSystemFunctions;
+import org.teiid.translator.Translator;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.UpdateExecution;
+import org.teiid.translator.jdbc.AliasModifier;
+import org.teiid.translator.jdbc.FunctionModifier;
+
+ at Translator(name="jpa2", description="A translator for JPA2 based entities")
+public class JPA2ExecutionFactory extends ExecutionFactory<EntityManagerFactory, EntityManager> {
+	private Map<String, FunctionModifier> functionModifiers = new TreeMap<String, FunctionModifier>(String.CASE_INSENSITIVE_ORDER);
+	
+	@Override
+	public void start() throws TranslatorException {
+		super.start();
+		setSupportsInnerJoins(true);
+		setSupportsOrderBy(true);
+		setSupportsSelectDistinct(true);
+		setSupportedJoinCriteria(SupportedJoinCriteria.KEY);
+		setSupportsOuterJoins(true);
+		
+		registerFunctionModifier(SourceSystemFunctions.LCASE, new AliasModifier("lower")); //$NON-NLS-1$
+		registerFunctionModifier(SourceSystemFunctions.UCASE, new AliasModifier("upper")); //$NON-NLS-1$
+		registerFunctionModifier(SourceSystemFunctions.CURDATE, new AliasModifier("current_date")); //$NON-NLS-1$
+		registerFunctionModifier(SourceSystemFunctions.CURTIME, new AliasModifier("current_time")); //$NON-NLS-1$
+	}
+	
+	@Override
+	public EntityManager getConnection(EntityManagerFactory factory, ExecutionContext executionContext) throws TranslatorException {
+		if (factory == null) {
+			return null;
+		}
+		return factory.createEntityManager();
+	}
+
+	@Override
+	public void closeConnection(EntityManager connection, EntityManagerFactory factory) {
+		connection.close();
+	}
+
+	@Override
+	public ResultSetExecution createResultSetExecution(QueryExpression command, ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager connection) throws TranslatorException {
+		return new JPQLQueryExecution(this, command, executionContext, metadata, connection);
+	}
+
+	@Override
+	public ProcedureExecution createProcedureExecution(Call command, ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager connection) throws TranslatorException {
+		return super.createProcedureExecution(command, executionContext, metadata, connection);
+	}
+
+	@Override
+	public UpdateExecution createUpdateExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager connection) throws TranslatorException {
+		return new JPQLUpdateExecution(command, executionContext, metadata, connection);
+	}
+	
+	@Override
+	public void getMetadata(MetadataFactory mf, EntityManager em) throws TranslatorException {
+		JPAMetadataProcessor metadataProcessor = new JPAMetadataProcessor();
+		PropertiesUtils.setBeanProperties(metadataProcessor, mf.getImportProperties(), "importer"); //$NON-NLS-1$
+		metadataProcessor.getMetadata(mf, em);
+	}
+
+
+	@Override
+	public boolean supportsSelectExpression() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAliasedTable() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsInlineViews() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsCompareCriteriaEquals() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsCompareCriteriaOrdered() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsLikeCriteria() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsInCriteria() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsInCriteriaSubquery() {
+		return false;
+	}
+
+	@Override
+	public boolean supportsIsNullCriteria() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsOrCriteria() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsNotCriteria() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsExistsCriteria() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsGroupBy() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsHaving() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAggregatesSum() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAggregatesAvg() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAggregatesMin() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAggregatesMax() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAggregatesCount() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAggregatesCountStar() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsAggregatesDistinct() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsScalarSubqueries() {
+		return true;
+	}
+	
+	@Override
+	public boolean useAnsiJoin() {
+		return true;
+	}
+
+	@Override
+	public boolean supportsDependentJoins() {
+		return true;
+	}
+
+	@Override
+    public boolean supportsSelfJoins() {
+    	return true;
+    }	
+
+	@Override
+	public List<String> getSupportedFunctions() {
+        List<String> supportedFunctions = new ArrayList<String>();
+        supportedFunctions.addAll(getDefaultSupportedFunctions());
+
+        // String functions
+        supportedFunctions.add(SourceSystemFunctions.CONCAT); 
+        supportedFunctions.add(SourceSystemFunctions.SUBSTRING); 
+        supportedFunctions.add(SourceSystemFunctions.TRIM);
+        supportedFunctions.add(SourceSystemFunctions.LCASE); 
+        supportedFunctions.add(SourceSystemFunctions.UCASE); 
+        supportedFunctions.add(SourceSystemFunctions.LENGTH);
+        supportedFunctions.add(SourceSystemFunctions.LOCATE);
+
+        // airthamatic functions
+        supportedFunctions.add(SourceSystemFunctions.ABS); 
+        supportedFunctions.add(SourceSystemFunctions.SQRT); 
+        supportedFunctions.add(SourceSystemFunctions.MOD);
+        supportedFunctions.add(SourceSystemFunctions.CURDATE);
+        supportedFunctions.add(SourceSystemFunctions.CURTIME);
+        
+        supportedFunctions.add(SourceSystemFunctions.COALESCE);
+        supportedFunctions.add(SourceSystemFunctions.NULLIF);
+        
+        return supportedFunctions;
+	}
+
+    /**
+     * Return a map of function name to FunctionModifier.
+     * @return Map of function name to FunctionModifier.
+     */
+    public Map<String, FunctionModifier> getFunctionModifiers() {
+    	return functionModifiers;
+    }
+    
+    /**
+     * Add the {@link FunctionModifier} to the set of known modifiers.
+     * @param name
+     * @param modifier
+     */
+    public void registerFunctionModifier(String name, FunctionModifier modifier) {
+    	this.functionModifiers.put(name, modifier);
+    }	
+	
+	
+	public List<String> getDefaultSupportedFunctions(){
+		return Arrays.asList(new String[] { "+", "-", "*", "/" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+	}
+}

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,323 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.Metamodel;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type.PersistenceType;
+
+import org.teiid.core.types.BlobType;
+import org.teiid.core.types.ClobType;
+import org.teiid.language.SQLConstants.Tokens;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.ForeignKey;
+import org.teiid.metadata.KeyRecord;
+import org.teiid.metadata.MetadataFactory;
+import org.teiid.metadata.Table;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+
+/**
+ * TODO: 
+ *  - support of abstract entities is an issue, should we represent base and extended types, just extended types?
+ * 
+ */
+ at SuppressWarnings("nls")
+public class JPAMetadataProcessor {
+	public static final String KEY_ASSOSIATED_WITH_FOREIGN_TABLE = "assosiated_with_table";
+	public static final String ENTITYCLASS= "entity_class";
+	
+	final static Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
+	static {
+	    map.put(boolean.class, Boolean.class);
+	    map.put(byte.class, Byte.class);
+	    map.put(short.class, Short.class);
+	    map.put(char.class, Character.class);
+	    map.put(int.class, Integer.class);
+	    map.put(long.class, Long.class);
+	    map.put(float.class, Float.class);
+	    map.put(double.class, Double.class);
+	    map.put(byte[].class, BlobType.class);
+	    map.put(char[].class, ClobType.class);
+	    map.put(Byte[].class, BlobType.class);
+	    map.put(Character[].class, ClobType.class);
+	    
+	    map.put(Boolean.class, Boolean.class);
+	    map.put(Byte.class, Byte.class);
+	    map.put(Short.class, Short.class);
+	    map.put(Character.class, Character.class);
+	    map.put(Integer.class, Integer.class);
+	    map.put(Long.class, Long.class);
+	    map.put(Float.class, Float.class);
+	    map.put(Double.class, Double.class);
+	    map.put(Calendar.class, java.sql.Timestamp.class);
+	}
+
+	public void getMetadata(MetadataFactory mf, EntityManager entityManager) throws TranslatorException {
+		Metamodel model = entityManager.getMetamodel();
+		
+		Set<EntityType<?>> entities = model.getEntities();
+		for (EntityType<?> entity:entities) {
+			addEntity(mf, model, entity);
+		}
+		
+		// take a second swipe and add Foreign Keys
+		for (EntityType<?> entity:entities) {
+			Table t = mf.getTable(entity.getName());
+			addForeignKeys(mf, model, entity, t);
+		}		
+	}
+
+	private Table addEntity(MetadataFactory mf, Metamodel model, EntityType<?> entity) throws TranslatorException {
+		Table table = mf.getTable(entity.getName());
+		if (table == null) {			
+			table = mf.addTable(entity.getName());
+			table.setSupportsUpdate(true);
+			table.setProperty(ENTITYCLASS, entity.getJavaType().getCanonicalName());
+			addPrimaryKey(mf, model, entity, table);
+			addSingularAttributes(mf, model, entity, table);
+		}
+		return table;
+	}
+	
+	private boolean columnExists(String name, Table table) {
+		if (table.getColumns() == null) {
+			return false;
+		}
+		for (Column existingColumn: table.getColumns()) {
+			if (existingColumn.getName().equals(name)) {
+				return true;
+			}
+		}		
+		return false;
+	}
+	
+	private Column addColumn(MetadataFactory mf, String name, String type, Table entityTable) throws TranslatorException {
+		if (!columnExists(name, entityTable)) {
+			Column c = mf.addColumn(name, type, entityTable);
+			c.setUpdatable(true);
+			return c;
+		}
+		return entityTable.getColumn(name);
+	}
+	
+	private void addForiegnKey(MetadataFactory mf, String name, List<String> columnNames, String referenceTable, Table table) throws TranslatorException {
+		ForeignKey fk = mf.addForiegnKey("FK_"+name, columnNames, referenceTable, table);
+		for (String column:columnNames) {
+			Column c = table.getColumn(column);
+			c.setProperty(KEY_ASSOSIATED_WITH_FOREIGN_TABLE, mf.getName()+Tokens.DOT+referenceTable);
+		}
+		fk.setNameInSource(name);
+	}
+
+	private void addSingularAttributes(MetadataFactory mf, Metamodel model, ManagedType<?> entity, Table entityTable) throws TranslatorException {
+		for (Attribute<?, ?> attr:entity.getAttributes()) {
+			if (!attr.isCollection()) {
+				boolean simpleType = isSimpleType(attr.getJavaType());
+				if (simpleType) {
+					Column column = addColumn(mf, attr.getName(), TypeFacility.getDataTypeName(getJavaDataType(attr.getJavaType())), entityTable);
+					if (((SingularAttribute)attr).isOptional()) {
+						column.setDefaultValue(null);
+					}
+				} 
+				else {
+					boolean classFound = false;
+					// If this attribute is a @Embeddable then add its columns as
+					// this tables columns
+					for (EmbeddableType<?> embeddable:model.getEmbeddables()) {
+						if (embeddable.getJavaType().equals(attr.getJavaType())) {
+							addSingularAttributes(mf, model, embeddable, entityTable);
+							classFound = true;
+							break;
+						}
+					}
+					
+					if (!classFound) {
+						// if the attribute is @Entity then add entity's PK as column on this
+						// table, then add that column as FK 
+						for (EntityType et:model.getEntities()) {
+							if (et.getJavaType().equals(attr.getJavaType())) {
+								Table attributeTable = addEntity(mf, model, et);
+								KeyRecord pk = attributeTable.getPrimaryKey();
+								if (pk != null) { // TODO: entities must have PK, so this check is not needed.
+									ArrayList<String> keys = new ArrayList<String>();
+									for (Column column:pk.getColumns()) {
+										addColumn(mf, column.getName(), column.getDatatype().getRuntimeTypeName(), entityTable);
+										keys.add(column.getName());
+									}
+									if (!foreignKeyExists(keys, entityTable)) {
+										addForiegnKey(mf, attr.getName(), keys, attributeTable.getName(), entityTable);
+									}
+								}
+								else {
+									throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14001, attributeTable.getName()));
+								}
+								classFound = true;
+								break;
+							}
+						}
+					}
+					
+					if (!classFound) {
+						throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14002, attr.getName()));
+					}
+				}
+			}
+		}
+	}
+	
+	private boolean isSimpleType(Class type) {
+		return type.isPrimitive() || type.equals(String.class)
+				|| type.equals(BigDecimal.class) || type.equals(Date.class)
+				|| type.equals(BigInteger.class)
+				|| map.containsKey(type);
+	}
+	
+	private void addForeignKeys(MetadataFactory mf, Metamodel model, ManagedType<?> entity, Table entityTable) throws TranslatorException {
+		for (Attribute<?, ?> attr:entity.getAttributes()) {
+			if (attr.isCollection()) {
+				
+				PluralAttribute pa = (PluralAttribute)attr;
+				Table forignTable = null;
+				
+				for (EntityType et:model.getEntities()) {
+					if (et.getJavaType().equals(pa.getElementType().getJavaType())) {
+						forignTable = mf.getTable(et.getName());
+						break;
+					}
+				}
+				
+				if (forignTable == null) {
+					continue;
+				}
+				
+				// add foreign keys as columns in table first; check if they exist first
+				ArrayList<String> keys = new ArrayList<String>();
+				KeyRecord pk = entityTable.getPrimaryKey();
+				for (Column entityColumn:pk.getColumns()) {
+					addColumn(mf, entityColumn.getName(), entityColumn.getDatatype().getRuntimeTypeName(), forignTable);
+					keys.add(entityColumn.getName());
+				}
+
+				if (!foreignKeyExists(keys, forignTable)) {
+					addForiegnKey(mf, attr.getName(), keys, entityTable.getName(), forignTable);
+				}
+			}
+		}
+	}
+	
+	private boolean foreignKeyExists(List<String> keys, Table forignTable) {
+		boolean fkExists = false;
+		for (ForeignKey fk:forignTable.getForeignKeys()) {
+			boolean allKeysFound = true;
+			for (String key:keys) {
+				boolean keyfound = false;
+				for (Column col:fk.getColumns()) {
+					if (col.getName().equals(key)) {
+						keyfound = true;
+						break;
+					}
+				}
+				if (!keyfound) {
+					allKeysFound = false;
+					break;
+				}
+			}
+			
+			if (allKeysFound) {
+				fkExists = true;
+				break;
+			}
+		}
+		return fkExists;
+	}	
+
+	private void addPrimaryKey(MetadataFactory mf, Metamodel model, EntityType<?> entity, Table entityTable) throws TranslatorException {
+		// figure out the PK
+		if (entity.hasSingleIdAttribute()) {
+			if (entity.getIdType().getPersistenceType().equals(PersistenceType.BASIC)) {
+				SingularAttribute<?, ?> pkattr = entity.getId(entity.getIdType().getJavaType());
+				addColumn(mf, pkattr.getName(), TypeFacility.getDataTypeName(getJavaDataType(pkattr.getJavaType())), entityTable);
+				mf.addPrimaryKey("PK_"+entity.getName(), Arrays.asList(pkattr.getName()), entityTable); //$NON-NLS-1$
+			}
+			else if (entity.getIdType().getPersistenceType().equals(PersistenceType.EMBEDDABLE)) {
+				SingularAttribute<?, ?> pkattr = entity.getId(entity.getIdType().getJavaType());
+				for (EmbeddableType<?> embeddable:model.getEmbeddables()) {
+					if (embeddable.getJavaType().equals(pkattr.getJavaType())) {
+						addSingularAttributes(mf, model, embeddable, entityTable);
+						ArrayList<String> keys = new ArrayList<String>();
+						for (Attribute<?, ?> attr:embeddable.getAttributes()) {
+							if (isSimpleType(attr.getJavaType())) {
+								keys.add(attr.getName());
+							}
+							else {
+								throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14003, entityTable.getName()));
+							}
+						}
+						mf.addPrimaryKey("PK_"+pkattr.getName(), keys, entityTable);
+						break;
+					}
+				}			
+			}
+		}
+		else {
+			// Composite PK. If the PK is specified with @IdClass then read its attributes,
+			// if those attributes are not found, add them as columns then as composite PK
+			ArrayList<String> keys = new ArrayList<String>();
+			for (Object obj:entity.getIdClassAttributes()) {
+				SingularAttribute<?, ?> attr = (SingularAttribute)obj;
+				addColumn(mf, attr.getName(), TypeFacility.getDataTypeName(getJavaDataType(attr.getJavaType())), entityTable);
+				keys.add(attr.getName());
+			}
+			mf.addPrimaryKey("PK_"+entity.getName(), keys, entityTable);
+		}
+	}
+	
+	private Class getJavaDataType(Class type) {
+		if (type.equals(Date.class)) {
+			return java.sql.Timestamp.class;
+		}
+		
+		if (type.isPrimitive()) {
+			return map.get(type);  // usage			
+		}
+		return type;
+	}
+	
+}

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import java.util.ResourceBundle;
+
+import org.teiid.core.BundleUtil;
+
+
+public class JPAPlugin { 
+
+    public static final String PLUGIN_ID = "org.teiid.translator.jpa" ; //$NON-NLS-1$
+
+    private static final String BUNDLE_NAME = PLUGIN_ID + ".i18n"; //$NON-NLS-1$
+    public static final BundleUtil Util = new BundleUtil(PLUGIN_ID,BUNDLE_NAME,ResourceBundle.getBundle(BUNDLE_NAME));
+
+    public static enum Event implements BundleUtil.Event{
+    	TEIID14001,
+    	TEIID14002,
+    	TEIID14003,
+    	TEIID14004,
+    	TEIID14005,
+    	TEIID14006,
+    	TEIID14007
+    }
+}

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import javax.persistence.EntityManager;
+
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.ExecutionContext;
+
+public class JPQLBaseExecution {
+	
+	protected ExecutionContext executionContext;
+	protected RuntimeMetadata metadata; 
+	protected EntityManager enityManager;
+
+	protected JPQLBaseExecution(ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager em) {
+		this.executionContext = executionContext;
+		this.metadata = metadata;
+		this.enityManager = em;
+	}
+
+}

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.teiid.language.QueryExpression;
+import org.teiid.language.Select;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ResultSetExecution;
+import org.teiid.translator.TranslatorException;
+
+public class JPQLQueryExecution extends JPQLBaseExecution implements ResultSetExecution {
+	private QueryExpression command;
+	private Iterator resultsIterator;
+	private JPA2ExecutionFactory executionFactory;
+
+	public JPQLQueryExecution(JPA2ExecutionFactory executionFactory, QueryExpression command, ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager em) {
+		super(executionContext, metadata, em);
+		this.command = command;
+		this.executionFactory = executionFactory;
+	}
+
+	@Override
+	public void execute() throws TranslatorException {
+		String jpql = JPQLSelectVisitor.getJPQLString((Select)this.command, this.executionFactory, this.metadata);
+		
+		LogManager.logTrace(LogConstants.CTX_CONNECTOR, "JPA Source-Query:", jpql); //$NON-NLS-1$
+		
+		Query query = this.enityManager.createQuery(jpql);
+		List results = query.getResultList();
+		this.resultsIterator = results.iterator();
+	}
+
+	@Override
+	public List<?> next() throws TranslatorException, DataNotAvailableException {
+		if (this.resultsIterator != null && this.resultsIterator.hasNext()) {
+			Object obj = this.resultsIterator.next();
+			if (obj instanceof Object[]) {
+				return Arrays.asList((Object[])obj);
+			}
+			return Arrays.asList(obj);
+		}
+		return null;
+	}
+	
+	@Override
+	public void close() {
+		// no close
+		this.resultsIterator = null;
+
+	}
+
+	@Override
+	public void cancel() throws TranslatorException {
+		// no cancel
+	}
+}

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,448 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import static org.teiid.language.SQLConstants.Reserved.*;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.language.*;
+import org.teiid.language.Join.JoinType;
+import org.teiid.language.SQLConstants.Tokens;
+import org.teiid.language.visitor.HierarchyVisitor;
+import org.teiid.language.visitor.SQLStringVisitor;
+import org.teiid.metadata.AbstractMetadataRecord;
+import org.teiid.metadata.ForeignKey;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.metadata.Table;
+import org.teiid.translator.TranslatorException;
+/**
+ * This visitor converts the Teiid command into JPQL string 
+ */
+public class JPQLSelectVisitor extends HierarchyVisitor {
+	protected JPA2ExecutionFactory executionFactory;
+	protected static final String UNDEFINED = "<undefined>"; //$NON-NLS-1$
+    private LinkedList<JoinTable> joins = new LinkedList<JoinTable>();
+    protected ArrayList<TranslatorException> exceptions = new ArrayList<TranslatorException>();
+    protected LinkedHashMap<String, NamedTable> implicitGroups = new LinkedHashMap<String, NamedTable>();
+    protected AtomicInteger aliasCounter = new AtomicInteger(0);
+	protected RuntimeMetadata metadata;
+    
+    public JPQLSelectVisitor(JPA2ExecutionFactory executionFactory, RuntimeMetadata metadata) {
+    	super(false);
+    	this.executionFactory = executionFactory;
+    	this.metadata = metadata;
+    }
+    	
+    public static String getJPQLString(Select obj, JPA2ExecutionFactory executionFactory, RuntimeMetadata metadata)  throws TranslatorException {
+    	JPQLSelectVisitor visitor = new JPQLSelectVisitor(executionFactory, metadata);
+        
+    	visitor.visitNode(obj);
+    	
+    	if (!visitor.exceptions.isEmpty()) {
+    		throw visitor.exceptions.get(0);
+    	}  
+    	
+        return visitor.convertToQuery(obj);
+    }
+    
+    private String convertToQuery(Select obj) {
+    	JPQLSelectStringVisitor visitor = new JPQLSelectStringVisitor(this);
+    	visitor.visitNode(obj);
+    	return visitor.toString();
+    }
+    
+    @Override
+    public void visit(Select obj) {
+    	visitNodes(obj.getDerivedColumns());
+    	visitNodes(obj.getFrom());
+        visitNode(obj.getWhere());
+        visitNode(obj.getGroupBy());
+        visitNode(obj.getHaving());
+        visitNode(obj.getOrderBy());
+    }    
+    
+    @Override
+    public void visit(ColumnReference obj) {
+		AbstractMetadataRecord record = obj.getMetadataObject();
+		if (record != null) {
+			String name = record.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false); 
+			if (name != null) {
+				try {
+					Table t = this.metadata.getTable(name);
+					if (this.implicitGroups.get(name) == null) {
+						this.implicitGroups.put(name, new NamedTable(t.getName(), "J_"+this.aliasCounter.getAndIncrement(), t)); //$NON-NLS-1$
+					}
+				} catch (TranslatorException e) {
+					exceptions.add(e);
+				}
+			}
+		}
+    }
+    
+    private boolean alreadyInJoin(String tableName) {
+    	for(JoinTable joinTable:this.joins) {
+			if ((joinTable.left != null && joinTable.left.getMetadataObject().getFullName().equals(tableName))
+					|| (joinTable.right != null && joinTable.right.getMetadataObject().getFullName().equals(tableName))) {
+    			return true;
+    		}
+    	}
+    	return false;
+    }
+
+    @Override
+    public void visit(NamedTable obj) {
+    	if (implicitGroups.isEmpty()) {
+    		this.joins.add(new JoinTable(obj, null, JoinType.INNER_JOIN));
+    	}
+    	else {
+	    	for (NamedTable table:this.implicitGroups.values()) {
+    			this.joins.add(new JoinTable(obj, table, JoinType.INNER_JOIN));
+	    	}
+    	}
+    }
+    
+    @Override
+    public void visit(Join obj) {
+    	try {
+			handleJoin(obj);
+	    	for (NamedTable table:this.implicitGroups.values()) {
+	    		NamedTable parent = findParent(table);
+	    		if (parent != null) {
+	    			if (!alreadyInJoin(table.getMetadataObject().getFullName())) {
+	    				this.joins.add(new JoinTable(parent, table, JoinType.INNER_JOIN));
+	    			}
+	    		}
+	    		else {
+	    			exceptions.add(new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14004, table.getName())));
+	    		}
+	    	}			
+		} catch (TranslatorException e) {
+			exceptions.add(e);
+		}
+    }
+
+    private NamedTable findParent(NamedTable child) {
+    	for (JoinTable jt:this.joins) {
+    		if (jt.getParent() != null) {
+    			if (isParentOf(jt.getParent(), child)) {
+    				return jt.getParent();
+    			}
+    		}
+    		
+    		if (jt.getChild() != null) {
+    			if (isParentOf(jt.getChild(), child)) {
+    				return jt.getChild();
+    			}    			
+    		}
+    	}
+    	return null;
+    }
+    
+	private JoinTable handleJoin(Join obj)  throws TranslatorException {
+		TableReference left = obj.getLeftItem();
+    	TableReference right = obj.getRightItem();
+    	
+    	if ((left instanceof NamedTable) && (right instanceof NamedTable)) {
+    		JoinTable join = handleJoin(obj.getJoinType(), left, right, true);
+    		this.joins.add(join);
+    		return join;
+    	}    	
+    	
+    	JoinTable leftJoin = null;
+    	if (left instanceof Join) {
+    		leftJoin = handleJoin((Join)left);
+    		if (right instanceof NamedTable) {
+    			JoinTable join =  handleJoin(obj.getJoinType(), leftJoin, (NamedTable)right);
+        		this.joins.add(join);
+        		return join;    			
+    		}
+    	}
+    	
+    	JoinTable rightJoin = null;
+    	if (right instanceof Join) {
+    		rightJoin = handleJoin((Join)right);
+    		if (left instanceof NamedTable) {
+    			JoinTable join = handleJoin(obj.getJoinType(), (NamedTable)left, rightJoin);
+        		this.joins.add(join);
+        		return join;      			
+    		}
+    	}
+    	throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14005));
+	}
+	
+	private JoinTable handleJoin(Join.JoinType joinType, JoinTable left, NamedTable right) throws TranslatorException {
+		// first we need to find correct parent for the right 
+		JoinTable withParent = handleJoin(joinType, left.getParent(), right, false);
+		JoinTable withChild = handleJoin(joinType, left.getChild(), right, false);
+		
+		NamedTable parent = (withParent.getParent() != null)?withParent.getParent():withChild.getParent();
+		if (parent != null) {
+			return handleJoin(joinType, parent, right, true);
+		}
+		throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14006)); 
+	}
+	
+	private JoinTable handleJoin(Join.JoinType joinType, NamedTable left, JoinTable right) throws TranslatorException {
+		// first we need to find correct parent for the left 
+		JoinTable withParent = handleJoin(joinType, left, right.getParent(), false);
+		JoinTable withChild = handleJoin(joinType, left, right.getChild(), false);
+		
+		NamedTable parent = (withParent.getParent() != null)?withParent.getParent():withChild.getParent();
+		if (parent != null) {
+			return handleJoin(joinType, left, parent, true);
+		}
+		throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14006));
+	}	
+
+	private JoinTable handleJoin(Join.JoinType joinType, TableReference left, TableReference right, boolean fixCorrelatedNames) {
+		// both sides are named tables
+		NamedTable leftTable = (NamedTable)left;
+		NamedTable rightTable = (NamedTable)right;
+		JoinTable joinTable = new JoinTable(leftTable, rightTable, joinType);
+		
+		if (fixCorrelatedNames) {
+			// fix left table's correleated name
+			NamedTable table = this.implicitGroups.get(leftTable.getMetadataObject().getFullName());
+			if (table != null) {
+				table.setCorrelationName(leftTable.getCorrelationName());
+			}
+			
+			// fix right table's correleated name
+			table = this.implicitGroups.get(rightTable.getMetadataObject().getFullName());
+			if (table != null) {
+				table.setCorrelationName(rightTable.getCorrelationName());
+			}   
+		}
+		return joinTable;
+	}    
+    
+	private boolean isParentOf(NamedTable parent, NamedTable child) {
+		for (ForeignKey fk:parent.getMetadataObject().getForeignKeys()){
+			if (fk.getReferenceTableName().equals(child.getMetadataObject().getName())) {
+				return true;
+			}
+		}
+		return false;
+	}
+    
+    static class JoinTable {
+    	NamedTable parent;
+    	NamedTable child;
+    	NamedTable left;
+    	NamedTable right;
+    	String childAttributeName;
+    	String parentAttributeName;
+    	JoinType joinType;
+    	
+    	JoinTable(NamedTable customer, NamedTable address, JoinType type) {
+    		this.left = customer;
+    		this.right = address;
+    		this.joinType = type;
+    		if (address == null) {
+    			this.parent = customer;
+    			this.parentAttributeName = customer.getName();
+    		}
+    		else {
+	    		for (ForeignKey fk:customer.getMetadataObject().getForeignKeys()){
+	    			if (fk.getReferenceTableName().equals(address.getMetadataObject().getName())) {
+	    				this.parent = customer;
+	    				this.child = address;
+	    				this.childAttributeName = fk.getNameInSource();
+	    				this.parentAttributeName = customer.getName();
+	    			}
+	    		}
+	    		if (this.parent == null) {
+	        		for (ForeignKey fk:address.getMetadataObject().getForeignKeys()){
+	        			if (fk.getReferenceTableName().equals(customer.getMetadataObject().getName())) {
+	            			this.parent = address;
+	            			this.child = customer;
+	        				this.childAttributeName = fk.getNameInSource();
+	        				this.parentAttributeName = customer.getName();
+	        			}
+	        		}    			
+	    		}
+    		}
+    	}
+    	
+    	NamedTable getParent() {
+    		return this.parent;
+    	}
+    	
+    	NamedTable getChild() {
+    		return this.child;
+    	}
+    	
+    	NamedTable getLeft() {
+    		return this.left;
+    	}
+    	
+    	NamedTable getRight() {
+    		return this.right;
+    	}    	
+    	
+    	String childAttributeName() {
+    		return this.childAttributeName;
+    	}
+    	
+    	String parentAttributeName() {
+    		return this.parentAttributeName;
+    	}
+    	
+    	public boolean isLeftParent() {
+    		return this.left == this.parent;
+    	}
+    }
+    
+    
+    static class JPQLSelectStringVisitor extends SQLStringVisitor {
+    	private JPQLSelectVisitor visitor;
+    	
+    	public JPQLSelectStringVisitor(JPQLSelectVisitor visitor) {
+    		this.visitor = visitor;
+    	}
+    	
+    	@Override
+    	public void visit(Select obj) {
+    		
+    		buffer.append(SELECT).append(Tokens.SPACE);
+    		
+            if (obj.isDistinct()) {
+                buffer.append(DISTINCT).append(Tokens.SPACE);
+            }
+                   
+            append(obj.getDerivedColumns());
+            
+            if (obj.getFrom() != null && !obj.getFrom().isEmpty()) {
+            	buffer.append(Tokens.SPACE).append(FROM).append(Tokens.SPACE);
+            	append(obj.getFrom());
+            }
+            
+            if (obj.getWhere() != null) {
+                buffer.append(Tokens.SPACE)
+                      .append(WHERE)
+                      .append(Tokens.SPACE);
+                append(obj.getWhere());
+            }
+            if (obj.getGroupBy() != null) {
+                buffer.append(Tokens.SPACE);
+                append(obj.getGroupBy());
+            }
+            if (obj.getHaving() != null) {
+                buffer.append(Tokens.SPACE)
+                      .append(HAVING)
+                      .append(Tokens.SPACE);
+                append(obj.getHaving());
+            }
+            if (obj.getOrderBy() != null) {
+                buffer.append(Tokens.SPACE);
+                append(obj.getOrderBy());
+            }
+        }    	
+    	
+    	@Override
+        public void visit(ColumnReference column) {
+    		AbstractMetadataRecord record = column.getMetadataObject();
+    		if (record != null) {
+    			String name = record.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false); 
+    			if (name == null) {
+					buffer.append(column.getTable().getCorrelationName()).append(Tokens.DOT).append(column.getMetadataObject().getName());
+    			}
+    			else {
+    				buffer.append(this.visitor.implicitGroups.get(name).getCorrelationName()).append(Tokens.DOT).append(column.getMetadataObject().getName());
+    			}
+    		}   
+    		else {
+    			buffer.append(column.getName());
+    		}
+    	}
+    	
+    	@Override
+        public void visit(Join obj) {
+    		addFromClause();
+        }
+    	
+    	@Override
+        public void visit(Function func) {
+        	if (visitor.executionFactory.getFunctionModifiers().containsKey(func.getName())) {
+                visitor.executionFactory.getFunctionModifiers().get(func.getName()).translate(func);
+        	}
+        	super.visit(func);
+        }    
+    	
+    	@Override
+        public void visit(NamedTable obj) {
+    		addFromClause();
+    	}
+    	
+    	private void addFromClause() {
+    		boolean first = true;
+    		for (JoinTable joinTable:this.visitor.joins) {
+    			if (!joinTable.isLeftParent() && joinTable.joinType == JoinType.LEFT_OUTER_JOIN) {
+    				joinTable.joinType = JoinType.RIGHT_OUTER_JOIN;
+    			}
+    			if (first) {
+    				buffer.append(joinTable.getParent().getName());
+    		        buffer.append(Tokens.SPACE);
+    		        buffer.append(AS).append(Tokens.SPACE);
+    		    	buffer.append(joinTable.getParent().getCorrelationName());    		    	
+    		    	first = false;
+    			}
+    			if (joinTable.getChild() != null) {
+    				buffer.append(Tokens.SPACE);
+    		        switch(joinTable.joinType) {
+    		        case CROSS_JOIN:
+    		            buffer.append(CROSS);
+    		            break;
+    		        case FULL_OUTER_JOIN:
+    		            buffer.append(FULL)
+    		                  .append(Tokens.SPACE)
+    		                  .append(OUTER);
+    		            break;
+    		        case INNER_JOIN:
+    		            buffer.append(INNER);
+    		            break;
+    		        case LEFT_OUTER_JOIN:
+    		            buffer.append(LEFT)
+    		                  .append(Tokens.SPACE)
+    		                  .append(OUTER);
+    		            break;
+    		        case RIGHT_OUTER_JOIN:
+    		            buffer.append(RIGHT)
+    		                  .append(Tokens.SPACE)
+    		                  .append(OUTER);
+    		            break;
+    		        default: buffer.append(UNDEFINED);
+    		        } 
+    		        buffer.append(Tokens.SPACE).append(JOIN).append(Tokens.SPACE);
+    				buffer.append(joinTable.getParent().getCorrelationName()).append(Tokens.DOT).append(joinTable.childAttributeName());
+    		        buffer.append(Tokens.SPACE);
+    		        buffer.append(AS).append(Tokens.SPACE);
+    		    	buffer.append(joinTable.getChild().getCorrelationName());
+    			}
+    		}
+    	}    	
+    }
+}

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,124 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.teiid.core.TeiidException;
+import org.teiid.core.util.PropertiesUtils;
+import org.teiid.core.util.ReflectionHelper;
+import org.teiid.language.*;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.UpdateExecution;
+
+public class JPQLUpdateExecution extends JPQLBaseExecution implements UpdateExecution {
+	private Command command;
+	private int[] results;
+	
+	public JPQLUpdateExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager em) {
+		super(executionContext, metadata, em);
+		this.command = command;
+	}
+	
+	@Override
+	public void execute() throws TranslatorException {
+		if (command instanceof BatchedUpdates) {
+			BatchedUpdates updates = (BatchedUpdates)this.command;
+			this.results = new int[updates.getUpdateCommands().size()];
+			int index = 0;
+			for (Command cmd:updates.getUpdateCommands()) {
+				this.results[index++] = executeUpdate(cmd);
+			}
+		}
+		else if (this.command instanceof Insert) {
+			this.results = new int[1];
+			Object entity = handleInsert((Insert)this.command);
+			this.enityManager.merge(entity);
+			this.results[0] = 1;
+		}
+		else {
+			// update or delete
+			this.results = new int[1];
+			this.results[0] = executeUpdate(this.command);			
+		}
+	}
+
+	private int executeUpdate(Command cmd) throws TranslatorException {
+		String jpql = JPQLUpdateQueryVisitor.getJPQLString(cmd);
+		LogManager.logTrace(LogConstants.CTX_CONNECTOR, "JPA Source-Query:", jpql); //$NON-NLS-1$
+		Query query = this.enityManager.createQuery(jpql);
+		return query.executeUpdate();
+	}
+
+	@Override
+	public int[] getUpdateCounts() throws DataNotAvailableException, TranslatorException {
+		return this.results;
+	}
+
+	@Override
+	public void close() {
+	}
+
+	@Override
+	public void cancel() throws TranslatorException {
+	}
+	
+	private Object handleInsert(Insert insert) throws TranslatorException {
+		try {
+			String entityClassName = insert.getTable().getMetadataObject().getProperty(JPAMetadataProcessor.ENTITYCLASS, false);
+			Object entity = ReflectionHelper.create(entityClassName, null, this.executionContext.getCommandContext().getVDBClassLoader());
+			
+			List<ColumnReference> columns = insert.getColumns();
+			List<Expression> values = ((ExpressionValueSource)insert.getValueSource()).getValues();
+			if(columns.size() != values.size()) {
+				throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14007));
+			}
+			for(int i = 0; i < columns.size(); i++) {
+				Column column = columns.get(i).getMetadataObject();
+				Object value = values.get(i);
+				
+				// do not add the derived columns
+				String name = column.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false); 				
+				if (name == null) {
+					if(value instanceof Literal) {
+						Literal literalValue = (Literal)value;
+						PropertiesUtils.setBeanProperty(entity, column.getName(), literalValue.getValue());
+					} else {
+						PropertiesUtils.setBeanProperty(entity, column.getName(), value);
+					}
+				}
+			}			
+			return entity;
+		} catch (TeiidException e) {
+			throw new TranslatorException(e);
+		}
+	}
+}

Added: trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,100 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.language.ColumnReference;
+import org.teiid.language.Command;
+import org.teiid.language.NamedTable;
+import org.teiid.language.SQLConstants.Tokens;
+import org.teiid.language.visitor.HierarchyVisitor;
+import org.teiid.language.visitor.SQLStringVisitor;
+import org.teiid.metadata.AbstractMetadataRecord;
+import org.teiid.translator.TranslatorException;
+
+public class JPQLUpdateQueryVisitor extends HierarchyVisitor {
+	protected ArrayList<TranslatorException> exceptions = new ArrayList<TranslatorException>();
+	protected AtomicInteger aliasCounter = new AtomicInteger(0);
+	protected HashMap<String, String> correlatedName = new HashMap<String, String>();
+	
+	public JPQLUpdateQueryVisitor() {
+		super(false);
+	}
+
+    public static String getJPQLString(Command obj)  throws TranslatorException {
+    	JPQLUpdateQueryVisitor visitor = new JPQLUpdateQueryVisitor();
+        
+    	visitor.visitNode(obj);
+    	
+    	if (!visitor.exceptions.isEmpty()) {
+    		throw visitor.exceptions.get(0);
+    	}  
+    	
+        return visitor.convertToQuery(obj);
+    }
+    
+    private String convertToQuery(Command obj) {
+    	JPQLUpdateStringVisitor visitor = new JPQLUpdateStringVisitor(this);
+    	visitor.visitNode(obj);
+    	return visitor.toString();
+    }
+    
+    @Override
+    public void visit(NamedTable obj) {
+    	if (obj.getCorrelationName() == null) {
+    		String aliasName = "ql_"+this.aliasCounter.getAndIncrement(); //$NON-NLS-1$
+    		this.correlatedName.put(obj.getMetadataObject().getName(), aliasName);
+    		obj.setCorrelationName(aliasName);
+    	}
+    	else {
+    		this.correlatedName.put(obj.getMetadataObject().getName(), obj.getCorrelationName());
+    	}
+    }
+    
+    static class JPQLUpdateStringVisitor extends SQLStringVisitor {
+    	private JPQLUpdateQueryVisitor visitor;
+    	
+    	public JPQLUpdateStringVisitor(JPQLUpdateQueryVisitor visitor) {
+    		this.visitor = visitor;
+    	}
+    	
+    	@Override
+        public void visit(ColumnReference column) {
+    		AbstractMetadataRecord record = column.getMetadataObject();
+    		if (record != null) {
+    			String name = record.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false); 
+    			if (name == null) {
+					buffer.append(this.visitor.correlatedName.get(column.getTable().getMetadataObject().getName())).append(Tokens.DOT).append(column.getMetadataObject().getName());
+    			}
+    			else {
+    				buffer.append(this.visitor.correlatedName.get(name)).append(Tokens.DOT).append(column.getMetadataObject().getName());
+    			}
+    		}   
+    		else {
+    			buffer.append(column.getName());
+    		}
+    	}    	
+    }
+}

Added: trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF
===================================================================
--- trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1 @@
+Dependencies: org.hibernate,org.jboss.teiid.translator.jdbc

Added: trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory
===================================================================
--- trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1 @@
+org.teiid.translator.jpa.JPA2ExecutionFactory
\ No newline at end of file

Added: trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties
===================================================================
--- trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,7 @@
+TEIID14001=PK on table {0} not found
+TEIID14002=Attribute can not be resolved:{0}
+TEIID14003=Embedded class has entity type based pk, not allowed on {0}
+TEIID14004=No parent table found for {0}
+TEIID14005=Bushy joins are not supported.
+TEIID14006=Unsupported join semantics, join can only be done where relationship exists
+TEIID14007=Columns.size and values.size are not the same
\ No newline at end of file

Added: trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java
===================================================================
--- trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,91 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+package org.teiid.translator.jpa;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.teiid.cdk.api.TranslationUtility;
+import org.teiid.core.util.UnitTestUtil;
+import org.teiid.language.Select;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.unittest.RealMetadataFactory;
+
+ at SuppressWarnings("nls")
+public class TestJSelectJPQLVisitor {
+    private JPA2ExecutionFactory jpaTranslator;
+    private TranslationUtility utility;
+
+    @Before
+    public void setUp() throws Exception {
+    	jpaTranslator = new JPA2ExecutionFactory();
+    	jpaTranslator.start();
+    	
+    	TransformationMetadata metadata = RealMetadataFactory.fromDDL(UnitTestUtil.getTestDataFile("sakila.ddl"), "sakila", "sakila");
+    	utility = new TranslationUtility(metadata);
+    	
+    }
+    
+    private void helpExecute(String query, String expected) throws Exception {
+    	Select cmd = (Select)this.utility.parseCommand(query);
+    	String jpaCommand = JPQLSelectVisitor.getJPQLString(cmd, jpaTranslator, utility.createRuntimeMetadata());
+    	assertEquals(expected, jpaCommand);
+    }
+    
+    @Test
+    public void testProjectionBasedJoin() throws Exception {
+    	helpExecute("select * from customer as c", "SELECT c.customer_id, J_0.store_id, c.first_name, c.last_name, c.email, J_1.address_id, c.active, c.create_date, c.last_update FROM customer AS c INNER JOIN c.store AS J_0 INNER JOIN c.address AS J_1");
+    }
+    
+    @Test
+    public void testExplicitJoinJoin() throws Exception {
+    	helpExecute("select c.first_name, c.last_name, a.address_id FROM customer c join address a on c.address_id=a.address_id", 
+    			"SELECT c.first_name, c.last_name, a.address_id FROM customer AS c INNER JOIN c.address AS a");
+    }
+    
+    @Test
+    public void testSimpleSelect() throws Exception {
+    	helpExecute("select c.first_name, c.last_name FROM customer c order by last_name", 
+    			"SELECT c.first_name, c.last_name FROM customer AS c ORDER BY c.last_name");
+    }
+    
+    @Test
+    public void testFunctionsSelect() throws Exception {
+    	helpExecute("select concat(lcase(first_name), last_Name) from customer as c", 
+    			"SELECT concat(lower(c.first_name), c.last_name) FROM customer AS c");
+    }
+    
+    @Test
+    public void testRightJoinRewriteSelect() throws Exception {
+    	helpExecute("select c.first_name, c.last_name, c.address_id, a.phone from customer c right join address a on c.address_Id=a.address_Id", 
+    			"SELECT c.first_name, c.last_name, a.address_id, a.phone FROM customer AS c RIGHT OUTER JOIN c.address AS a");
+    }
+    
+    @Test
+    public void testRightandinnerJoinRewriteSelect() throws Exception {
+    	helpExecute("select c.first_name, c.last_name, a.address_id, a.phone, ci.city from customer c join address a on c.address_Id=a.address_Id right join city ci on ci.city_id = a.city_id where c.last_Name='MYERS' OR c.last_Name='TALBERT' order by c.first_Name", 
+    			"SELECT c.first_name, c.last_name, a.address_id, a.phone, ci.city FROM customer AS c INNER JOIN c.address AS a RIGHT OUTER JOIN a.city AS ci WHERE c.last_name IN ('TALBERT', 'MYERS') ORDER BY c.first_name");
+    }
+    
+	// needs one with composite PK
+}

Added: trunk/connectors/translator-jpa/src/test/resources/sakila.ddl
===================================================================
--- trunk/connectors/translator-jpa/src/test/resources/sakila.ddl	                        (rev 0)
+++ trunk/connectors/translator-jpa/src/test/resources/sakila.ddl	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,69 @@
+CREATE FOREIGN TABLE country (
+  country_id integer  NOT NULL AUTO_INCREMENT,
+  country varchar(50) NOT NULL,
+  last_update timestamp NOT NULL
+  CONSTRAINT PRIMARY KEY  (country_id)
+);
+
+CREATE FOREIGN TABLE city (
+  city_id integer  NOT NULL AUTO_INCREMENT,
+  city varchar(50) NOT NULL,
+  country_id integer  NOT NULL OPTIONS (assosiated_with_table 'sakila.country'),
+  last_update timestamp NOT NULL
+  CONSTRAINT PRIMARY KEY  (city_id),
+  FOREIGN KEY (country_id) REFERENCES country (country_id) OPTIONS(NAMEINSOURCE 'country')
+);
+
+CREATE FOREIGN TABLE address (
+  address_id integer NOT NULL AUTO_INCREMENT,
+  address varchar(50) NOT NULL,
+  address2 varchar(50),
+  district varchar(20) NOT NULL,
+  city_id integer  NOT NULL OPTIONS (assosiated_with_table 'sakila.city'),
+  postal_code varchar(10),
+  phone varchar(20) NOT NULL,
+  last_update timestamp NOT NULL
+  CONSTRAINT PRIMARY KEY  (address_id),
+  FOREIGN KEY (city_id) REFERENCES city (city_id) OPTIONS(NAMEINSOURCE 'city')
+);
+
+CREATE FOREIGN TABLE staff (
+  staff_id byte NOT NULL AUTO_INCREMENT,
+  first_name varchar(45) NOT NULL,
+  last_name varchar(45) NOT NULL,
+  address_id integer NOT NULL OPTIONS (assosiated_with_table 'sakila.address'),
+  email varchar(50),
+  store_id byte NOT NULL OPTIONS (assosiated_with_table 'sakila.store'),
+  active boolean NOT NULL,
+  username varchar(16) NOT NULL,
+  password varchar(40),
+  last_update timestamp
+  CONSTRAINT PRIMARY KEY  (staff_id),
+  FOREIGN KEY (store_id) REFERENCES store (store_id) OPTIONS(NAMEINSOURCE 'store'),
+  FOREIGN KEY (address_id) REFERENCES address (address_id) OPTIONS(NAMEINSOURCE 'address')
+);
+
+CREATE FOREIGN TABLE store (
+  store_id byte  NOT NULL AUTO_INCREMENT,
+  manager_staff_id byte NOT NULL OPTIONS (assosiated_with_table 'sakila.staff'),
+  address_id integer NOT NULL OPTIONS (assosiated_with_table 'sakila.store'),
+  last_update timestamp NOT NULL
+  CONSTRAINT PRIMARY KEY  (store_id),
+  FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) OPTIONS(NAMEINSOURCE 'staff'),
+  FOREIGN KEY (address_id) REFERENCES address (address_id) OPTIONS(NAMEINSOURCE 'address')
+);
+
+CREATE FOREIGN TABLE customer (
+  customer_id integer NOT NULL AUTO_INCREMENT,
+  store_id byte NOT NULL OPTIONS (assosiated_with_table 'sakila.store'),
+  first_name varchar(45) NOT NULL,
+  last_name varchar(45) NOT NULL,
+  email varchar(50),
+  address_id integer  NOT NULL OPTIONS (assosiated_with_table 'sakila.address'),
+  active boolean NOT NULL,
+  create_date timestamp NOT NULL,
+  last_update timestamp
+  constraint PRIMARY KEY  (customer_id),
+  FOREIGN KEY (address_id) REFERENCES address (address_id) OPTIONS(NAMEINSOURCE 'address'),
+  FOREIGN KEY (store_id) REFERENCES store (store_id) OPTIONS(NAMEINSOURCE 'store')
+);
\ No newline at end of file

Added: trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF
===================================================================
--- trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF	                        (rev 0)
+++ trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF	2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1 @@
+Dependencies: org.hibernate,org.jboss.teiid.translator.jdbc


Property changes on: trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF
___________________________________________________________________
Added: svn:mime-type
   + text/plain



More information about the teiid-commits mailing list