/**
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.jboss.jca.adapters.sap.cci.impl;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_BYTE_LENGTH_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_CLASS_NAME_OF_FIELD_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_DECIMALS_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_DEFAULT_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_DESCRIPTION_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_ABAP_OBJECT_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_CHANGING_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_EXPORT_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_IMPORT_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_NESTED_TYPE1_STRUCTURE_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_OPTIONAL_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_STRUCTURE_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_IS_TABLE_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_LENGTH_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_RECORD_FIELD_NAME_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_RECORD_TYPE_NAME_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_TYPE_AS_STRING_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_TYPE_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_UNICODE_BYTE_LENGTH_KEY;
import static org.jboss.jca.adapters.sap.cci.CciPackage.CciNS_URI;
import static org.jboss.jca.adapters.sap.cci.CciPackage.JBOSS_SAP_URI_PREFIX;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EGenericType;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.jboss.jca.adapters.sap.cci.IndexedRecord;
import org.jboss.jca.adapters.sap.cci.MappedRecord;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunctionTemplate;
import com.sap.conn.jco.JCoListMetaData;
import com.sap.conn.jco.JCoMetaData;
import com.sap.conn.jco.JCoRecordMetaData;
import com.sap.conn.jco.JCoRepository;
import com.sap.conn.jco.JCoTable;
/**
* Package Registry for JBoss SAP JCA Connector
*
* This class dynamically creates Ecore package definitions on demand which
* describes the data structures required to invoke a specific remote function
* module. An Ecore package is created on demand for each remote function module
* defined in a connected SAP instance.
*
* @author William Collins
*
*/
public class CciPackageRegistryImpl implements Registry {
private static final String GenNS_URI = "http://www.eclipse.org/emf/2002/GenModel";
private static final String GenNS_DOCUMENTATION_KEY = "documentation";
/**
* The {@link JCoRepository} providing the source of package meta-data.
*/
private JCoRepository repository;
/**
* Construct a {@link Registry} using the given {@link JCoRepository} to create required packages on demand.
*
* @param repository - the {@link JCoRepository} used to provide package meta-data.
*/
public CciPackageRegistryImpl(JCoRepository repository) {
this.repository = repository;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return EPackage.Registry.INSTANCE.size();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEmpty() {
return EPackage.Registry.INSTANCE.isEmpty();
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsKey(Object key) {
return EPackage.Registry.INSTANCE.containsKey(key);
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsValue(Object value) {
return EPackage.Registry.INSTANCE.containsValue(value);
}
/**
* {@inheritDoc}
*/
@Override
public Object get(Object key) {
return EPackage.Registry.INSTANCE.get(key);
}
/**
* {@inheritDoc}
*/
@Override
public Object put(String key, Object value) {
return EPackage.Registry.INSTANCE.put(key, value);
}
/**
* {@inheritDoc}
*/
@Override
public Object remove(Object key) {
return EPackage.Registry.INSTANCE.remove(key);
}
/**
* {@inheritDoc}
*/
@Override
public void putAll(Map<? extends String, ? extends Object> m) {
EPackage.Registry.INSTANCE.putAll(m);
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
EPackage.Registry.INSTANCE.clear();
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> keySet() {
return EPackage.Registry.INSTANCE.keySet();
}
/**
* {@inheritDoc}
*/
@Override
public Collection<Object> values() {
return EPackage.Registry.INSTANCE.values();
}
/**
* {@inheritDoc}
*/
@Override
public Set<java.util.Map.Entry<String, Object>> entrySet() {
return EPackage.Registry.INSTANCE.entrySet();
}
@Override
public EPackage getEPackage(String nsURI) {
EPackage ePackage = (EPackage) EPackage.Registry.INSTANCE.get(nsURI);
if (ePackage == null && nsURI.startsWith(JBOSS_SAP_URI_PREFIX + repository.getName())) {
int prefixLength = JBOSS_SAP_URI_PREFIX.length() + repository.getName().length() + 1; // Length of "http://sap.adapters.jca.jboss.org/<repo-name>/" prefix.
String functionModuleName = nsURI.substring(prefixLength);
EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
JCoFunctionTemplate functionTemplate;
try {
functionTemplate = repository.getFunctionTemplate(functionModuleName);
} catch (JCoException e) {
return null;
}
JCoListMetaData importParameterListMetaData = functionTemplate.getImportParameterList();
JCoListMetaData changingParameterListMetaData = functionTemplate.getChangingParameterList();
JCoListMetaData tableParameterListMetaData = functionTemplate.getTableParameterList();
JCoListMetaData exportParameterListMetaData = functionTemplate.getExportParameterList();
// Create and initialize package
ePackage = ecoreFactory.createEPackage();
ePackage.setName(functionModuleName);
ePackage.setNsPrefix(functionModuleName);
ePackage.setNsURI(nsURI);
// Create Input Record Class
EClass inputRecordClass = ecoreFactory.createEClass();
ePackage.getEClassifiers().add(inputRecordClass);
inputRecordClass.setName("INPUT_RECORD");
inputRecordClass.getESuperTypes().add(CciPackageImpl.eINSTANCE.getMappedRecord());
addListMetaData(inputRecordClass, importParameterListMetaData);
addListMetaData(inputRecordClass, changingParameterListMetaData);
addListMetaData(inputRecordClass, tableParameterListMetaData);
addAnnotation(inputRecordClass, GenNS_URI, GenNS_DOCUMENTATION_KEY, "Input Record for "
+ functionModuleName);
// Create Output Record
EClass outputRecordClass = ecoreFactory.createEClass();
ePackage.getEClassifiers().add(outputRecordClass);
outputRecordClass.setName("OUTPUT_RECORD");
outputRecordClass.getESuperTypes().add(CciPackageImpl.eINSTANCE.getMappedRecord());
addListMetaData(outputRecordClass, exportParameterListMetaData);
addListMetaData(outputRecordClass, changingParameterListMetaData);
addListMetaData(outputRecordClass, tableParameterListMetaData);
addAnnotation(outputRecordClass, GenNS_URI, GenNS_DOCUMENTATION_KEY, "Output Record for "
+ functionModuleName);
// Register Package
EPackage.Registry.INSTANCE.put(nsURI, ePackage);
}
return ePackage;
}
@Override
public EFactory getEFactory(String nsURI) {
EPackage ePackage = getEPackage(nsURI);
if (ePackage != null)
return ePackage.getEFactoryInstance();
return null;
}
/**
* @param clazz
* @param jcoListMetaData
* @generated NOT
*/
private void addAnnotation(EModelElement modelElement, String source, String key, String value) {
EAnnotation annotation = modelElement.getEAnnotation(source);
if (annotation == null) {
annotation = EcoreFactory.eINSTANCE.createEAnnotation();
annotation.setSource(source);
annotation.setEModelElement(modelElement);
}
annotation.getDetails().put(key, value);
}
/**
* Populate the given {@link EClass} with structural features and annotations derived from the meta-data of the given {@link JCoListMetaData}.
*
* @param eClass - the {@link EClass} populated with meta-data.
* @param jcoListMetaData - the {@link JCoListMetaData} from which the meta-data is derived.
*/
private void addListMetaData(EClass eClass, JCoListMetaData jcoListMetaData) {
if (jcoListMetaData == null)
return;
EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
EPackage ePackage = eClass.getEPackage();
for (int i = 0; i < jcoListMetaData.getFieldCount(); i++) {
EStructuralFeature structuralFeature;
if (jcoListMetaData.isStructure(i)) {
JCoRecordMetaData jcoRecordMetaData = jcoListMetaData.getRecordMetaData(i);
EClass mappedRecordClass = getMappedRecordClass(ePackage, jcoRecordMetaData);
EReference reference = ecoreFactory.createEReference();
reference.setEType(mappedRecordClass);
reference.setContainment(true);
structuralFeature = reference;
addAnnotation(structuralFeature, CciNS_URI, CciNS_CLASS_NAME_OF_FIELD_KEY,
MappedRecord.class.getName());
} else if (jcoListMetaData.isTable(i)) {
JCoRecordMetaData jcoRecordMetaData = jcoListMetaData.getRecordMetaData(i);
EClass indexedRecordClass = getIndexedRecordClass(ePackage, jcoRecordMetaData);
EReference reference = ecoreFactory.createEReference();
reference.setEType(indexedRecordClass);
reference.setContainment(true);
structuralFeature = reference;
addAnnotation(structuralFeature, CciNS_URI, CciNS_CLASS_NAME_OF_FIELD_KEY,
IndexedRecord.class.getName());
} else {
EAttribute attribute = ecoreFactory.createEAttribute();
attribute.setEType(getEDataType(jcoListMetaData.getType(i)));
structuralFeature = attribute;
addAnnotation(structuralFeature, CciNS_URI, CciNS_CLASS_NAME_OF_FIELD_KEY,
jcoListMetaData.getClassNameOfField(i));
}
structuralFeature.setName(jcoListMetaData.getName(i));
if (!jcoListMetaData.isOptional(i))
structuralFeature.setLowerBound(1);
if (jcoListMetaData.getDefault(i) != null)
structuralFeature.setDefaultValueLiteral(jcoListMetaData.getDefault(i));
addAnnotation(structuralFeature, GenNS_URI, GenNS_DOCUMENTATION_KEY, jcoListMetaData.getDescription(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_DESCRIPTION_KEY,
jcoListMetaData.getDescription(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_TYPE_KEY,
Integer.toString(jcoListMetaData.getType(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_TYPE_AS_STRING_KEY,
jcoListMetaData.getTypeAsString(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_RECORD_TYPE_NAME_KEY,
jcoListMetaData.getRecordTypeName(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_LENGTH_KEY,
Integer.toString(jcoListMetaData.getLength(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_BYTE_LENGTH_KEY,
Integer.toString(jcoListMetaData.getByteLength(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_UNICODE_BYTE_LENGTH_KEY,
Integer.toString(jcoListMetaData.getUnicodeByteLength(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_DECIMALS_KEY,
Integer.toString(jcoListMetaData.getDecimals(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_DEFAULT_KEY, jcoListMetaData.getDefault(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_RECORD_FIELD_NAME_KEY,
jcoListMetaData.getRecordFieldName(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_ABAP_OBJECT_KEY,
Boolean.toString(jcoListMetaData.isAbapObject(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_NESTED_TYPE1_STRUCTURE_KEY,
Boolean.toString(jcoListMetaData.isNestedType1Structure(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_STRUCTURE_KEY,
Boolean.toString(jcoListMetaData.isStructure(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_TABLE_KEY,
Boolean.toString(jcoListMetaData.isTable(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_IMPORT_KEY,
Boolean.toString(jcoListMetaData.isImport(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_EXPORT_KEY,
Boolean.toString(jcoListMetaData.isExport(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_CHANGING_KEY,
Boolean.toString(jcoListMetaData.isChanging(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_OPTIONAL_KEY,
Boolean.toString(jcoListMetaData.isOptional(i)));
eClass.getEStructuralFeatures().add(structuralFeature);
}
}
/**
* @generated NOT
*/
private EClass getMappedRecordClass(EPackage ePackage, JCoRecordMetaData jcoRecordMetaData) {
EClassifier eClassifier = ePackage.getEClassifier(jcoRecordMetaData.getName());
if (!(eClassifier instanceof EClass)) {
// Create Mapped Record Subclass
eClassifier = EcoreFactory.eINSTANCE.createEClass();
ePackage.getEClassifiers().add(eClassifier);
eClassifier.setName(jcoRecordMetaData.getName());
((EClass)eClassifier).getESuperTypes().add(CciPackageImpl.eINSTANCE.getMappedRecord());
addRecordMetaData(((EClass)eClassifier), jcoRecordMetaData);
}
return (EClass) eClassifier;
}
/**
* Create and return an {@link EClass} deriving from {@link IndexedRecord} and representing the {@link JCoTable}
* @param ePackage
* @param jcoRecordMetaData
* @return
*/
private EClass getIndexedRecordClass(EPackage ePackage, JCoRecordMetaData jcoRecordMetaData) {
EClassifier eClassifier = ePackage.getEClassifier(jcoRecordMetaData.getName() + "_TABLE");
if (!(eClassifier instanceof EClass)) {
// Create super type for indexed record subclass: IndexeRecord<R extends MappedRecord>
EGenericType indexedRecordGenericType = EcoreFactory.eINSTANCE.createEGenericType();
indexedRecordGenericType.setEClassifier(CciPackageImpl.eINSTANCE.getIndexedRecord());
// Create type parameter for record type: R extends MappedRecord
EGenericType recordEntryGenericType = EcoreFactory.eINSTANCE.createEGenericType();
EClass recordType = getMappedRecordClass(ePackage, jcoRecordMetaData);
recordEntryGenericType.setEClassifier(recordType);
// Add type parameter to super type.
indexedRecordGenericType.getETypeArguments().add(recordEntryGenericType);
// Create indexed record subclass and add to package
eClassifier = EcoreFactory.eINSTANCE.createEClass();
ePackage.getEClassifiers().add(eClassifier);
eClassifier.setName(jcoRecordMetaData.getName() + "_TABLE");
((EClass)eClassifier).getEGenericSuperTypes().add(indexedRecordGenericType);
}
return (EClass) eClassifier;
}
/**
* Populate the given {@link EClass} with structural features and annotations derived from the meta-data of the given {@link JCoRecordMetaData}.
*
* @param eClass - the {@link EClass} populated with meta-data.
* @param jcoRecordMetaData - the {@link JCoRecordMetaData} from which the meta-data is derived.
*/
private void addRecordMetaData(EClass eClass, JCoRecordMetaData jcoRecordMetaData) {
EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
EPackage ePackage = eClass.getEPackage();
for (int i = 0; i < jcoRecordMetaData.getFieldCount(); i++) {
EStructuralFeature structuralFeature;
if (jcoRecordMetaData.isStructure(i)) {
JCoRecordMetaData jcoSubRecordMetaData = jcoRecordMetaData.getRecordMetaData(i);
EClass structureClass = getMappedRecordClass(ePackage, jcoSubRecordMetaData);
EReference reference = ecoreFactory.createEReference();
structuralFeature = reference;
reference.setEType(structureClass);
reference.setContainment(true);
addAnnotation(structuralFeature, CciNS_URI, CciNS_CLASS_NAME_OF_FIELD_KEY, MappedRecord.class.getName());
} else if (jcoRecordMetaData.isTable(i)) {
JCoRecordMetaData jcoSubRecordMetaData = jcoRecordMetaData.getRecordMetaData(i);
EClass tableClass = getIndexedRecordClass(ePackage, jcoSubRecordMetaData);
EReference reference = ecoreFactory.createEReference();
structuralFeature = reference;
reference.setEType(tableClass);
reference.setContainment(true);
addAnnotation(structuralFeature, CciNS_URI, CciNS_CLASS_NAME_OF_FIELD_KEY, IndexedRecord.class.getName());
} else {
EAttribute attribute = ecoreFactory.createEAttribute();
structuralFeature = attribute;
attribute.setEType(getEDataType(jcoRecordMetaData.getType(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_CLASS_NAME_OF_FIELD_KEY, jcoRecordMetaData.getClassNameOfField(i));
}
structuralFeature.setName(jcoRecordMetaData.getName(i));
addAnnotation(structuralFeature, GenNS_URI, GenNS_DOCUMENTATION_KEY, jcoRecordMetaData.getDescription(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_DESCRIPTION_KEY, jcoRecordMetaData.getDescription(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_TYPE_KEY, Integer.toString(jcoRecordMetaData.getType(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_TYPE_AS_STRING_KEY, jcoRecordMetaData.getTypeAsString(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_RECORD_TYPE_NAME_KEY, jcoRecordMetaData.getRecordTypeName(i));
addAnnotation(structuralFeature, CciNS_URI, CciNS_LENGTH_KEY, Integer.toString(jcoRecordMetaData.getLength(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_BYTE_LENGTH_KEY, Integer.toString(jcoRecordMetaData.getByteLength(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_UNICODE_BYTE_LENGTH_KEY, Integer.toString(jcoRecordMetaData.getUnicodeByteLength(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_DECIMALS_KEY, Integer.toString(jcoRecordMetaData.getDecimals(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_ABAP_OBJECT_KEY, Boolean.toString(jcoRecordMetaData.isAbapObject(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_NESTED_TYPE1_STRUCTURE_KEY, Boolean.toString(jcoRecordMetaData.isNestedType1Structure(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_STRUCTURE_KEY, Boolean.toString(jcoRecordMetaData.isStructure(i)));
addAnnotation(structuralFeature, CciNS_URI, CciNS_IS_TABLE_KEY, Boolean.toString(jcoRecordMetaData.isTable(i)));
eClass.getEStructuralFeatures().add(structuralFeature);
}
}
/**
* Return the {@link EClassifier} corresponding to the given JCo data type.
*
* @param jcoDataType - the JCo data type.
* @return the {@link EClassifier} corresponding to the given JCo data type.
*/
private EClassifier getEDataType(int jcoDataType) {
switch (jcoDataType) {
case JCoMetaData.TYPE_INT:
case JCoMetaData.TYPE_INT1:
case JCoMetaData.TYPE_INT2:
return EcorePackage.Literals.EINT;
case JCoMetaData.TYPE_CHAR:
return EcorePackage.Literals.ESTRING;
case JCoMetaData.TYPE_NUM:
return EcorePackage.Literals.ESTRING;
case JCoMetaData.TYPE_BCD:
return EcorePackage.Literals.EBIG_DECIMAL;
case JCoMetaData.TYPE_DATE:
return EcorePackage.Literals.EDATE;
case JCoMetaData.TYPE_TIME:
return EcorePackage.Literals.EDATE;
case JCoMetaData.TYPE_FLOAT:
return EcorePackage.Literals.EDOUBLE;
case JCoMetaData.TYPE_BYTE:
return EcorePackage.Literals.EBYTE_ARRAY;
case JCoMetaData.TYPE_STRING:
return EcorePackage.Literals.ESTRING;
case JCoMetaData.TYPE_XSTRING:
return EcorePackage.Literals.EBYTE_ARRAY;
case JCoMetaData.TYPE_DECF16:
return EcorePackage.Literals.EBIG_DECIMAL;
case JCoMetaData.TYPE_DECF34:
return EcorePackage.Literals.EBIG_DECIMAL;
case JCoMetaData.TYPE_STRUCTURE:
return CciPackageImpl.Literals.MAPPED_RECORD;
case JCoMetaData.TYPE_TABLE:
return CciPackageImpl.Literals.INDEXED_RECORD;
default:
return EcorePackage.Literals.EBYTE_ARRAY;
}
}
}