/*
 * Copyright (c) 2008 Borland Software Corporation
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Artem Tikhomirov (Borland) - initial API and implementation
 */

import "http://www.eclipse.org/emf/2002/GenModel";
import "http://www.eclipse.org/emf/2002/Ecore";

extension xpt::GenModelUtils reexport;

/*
 * NOTE: Extensions from this file are supposed to be used 
 * ONLY from MetaModel.xpt. No other .xpt or .ext should import
 * this file. Common GenModel functionality, unrelated to meta-model 
 * access and access to generated model code should go into GenModelUtils.ext. 
 */


//
// GenPackageImpl#getQualifiedPackageInterfaceName()
//
String getQualifiedPackageInterfaceName(genmodel::GenPackage gp) :
	gp.genModel.suppressEMFMetaData ? getQualifiedPackageClassName(gp) : getReflectionPackageName(gp) + "." + getPackageInterfaceName(gp)
;

//
// GenPackageImpl#getQualifiedFactoryInterfaceName()
//
String getQualifiedFactoryInterfaceName(genmodel::GenPackage gp) :
	getReflectionPackageName(gp) + "." + getPrefixedName(gp, "Factory")
;

//
// GenPackage#getFactoryInstanceName
//
String getFactoryInstanceName(genmodel::GenPackage gp) :
	gp.genModel.suppressEMFMetaData ? "INSTANCE" : "eINSTANCE"
;

//
// GenPackageImpl#getQualifiedItemProviderAdapterFactoryClassName()
//
String getQualifiedItemProviderAdapterFactoryClassName(genmodel::GenPackage gp) :
	getQualifiedPackageName(gp, gp.providerPackageSuffix) + "." + getItemProviderAdapterFactoryClassName(gp)
;

//
// GenPackageImpl#getItemProviderAdapterFactoryClassName()
//
private String getItemProviderAdapterFactoryClassName(genmodel::GenPackage gp) :
	getPrefixedName(gp, "ItemProviderAdapterFactory")
;

//
// GenClass#getQualifiedInterfaceName
//
String getQualifiedInterfaceName(genmodel::GenClass gc) :
	null != gc.ecoreClass.instanceClassName 
		? gc.ecoreClass.instanceClassName.replaceAll('\\$', '\\.')
		: (getInterfacePackageName(gc.genPackage) + "." + gc.ecoreClass.name)
;

//
// GenPackageImpl#getInterfacePackageName()
//
private String getInterfacePackageName(GenPackage gp) :
	getQualifiedPackageName(gp, gp.interfacePackageSuffix)
;

String getQualifiedClassName(GenClassifier dt) : null ;
// NOTE GenDataType#getQualifiedInstanceClassName returns primitive types as is,
// while we return their java.lang wrappers
String getQualifiedClassName(GenDataType dt) : getObjectCompatibleClassName(dt.ecoreDataType) ; 
String getQualifiedClassName(GenEnum e) : getInterfacePackageName(e.genPackage) + "." + e.ecoreEnum.name
;

//
// GenClass#getClassifierAccessorName
//
String getClassifierAccessorName(genmodel::GenClassifier gc) :
	switch (gc.getEcoreClassifier().name) {
		case "Class" : "Class_"
		case "Name" : "Name_"
		default : gc.getEcoreClassifier().name
	}
;

//
// GenFeature#getFeatureAccessorName
//
String getFeatureAccessorName(genmodel::GenFeature gf) :
	gf.genClass.ecoreClass.name + "_" + gf.ecoreFeature.name.toFirstUpper()
;

// GenFeatureImpl#getAccessorName
String getAccessorName(genmodel::GenFeature gf) :
	isMapEntryFeature(gf) ? "Typed" + gf.ecoreFeature.name.toFirstUpper() : gf.ecoreFeature.name.toFirstUpper()
;

// GenFeature#getGetAccessor()
String getGetAccessor(genmodel::GenFeature gf) :
JAVA org.eclipse.gmf.internal.codegen.util.GenModelUtils.getGetAccessor(org.eclipse.emf.codegen.ecore.genmodel.GenFeature)
;

// GenClassImpl#isMapEntry
boolean isMapEntry(genmodel::GenClass gc) :
	("java.util.Map.Entry" == gc.ecoreClass.instanceClassName || "java.util.Map$Entry" == gc.ecoreClass.instanceClassName) 
		&& gc.ecoreClass.getEStructuralFeature("key") != null
		&& gc.ecoreClass.getEStructuralFeature("value") != null
;


/*
 * Casts the argument (which is assumed to be of the given source class) to the given target class. 
 * A null value may be used for both source and target class to specify the EObject class.
 * If the cast is required, it will be parenthesized as a whole, producing, e.g., ((EObject) o). 
 * If the parentheses are not required, use unparenthesizedCast() extension.
 */
String parenthesizedCast(String what, genmodel::GenClass source, genmodel::GenClass target) :
	needsCast(source, target) ? "(" + unparenthesizedCast(what, source, target) + ")" : what
;

/*
 * Casts the argument (which is assumed to be of the given source class) to the given target class. 
 * A null value may be used for both source and target class to specify the EObject class.
 * If the cast is required, it will NOT be parenthesized as a whole, producing, e.g., (EObject) o. 
 * If the parentheses are required, use parenthesizedCast() extension.
 */
String unparenthesizedCast(String what, genmodel::GenClass source, genmodel::GenClass target) :
	needsCast(source, target) ? 
		(target == null ? "(org.eclipse.emf.ecore.EObject)" + what : "(" + target.getQualifiedInterfaceName() + ")" + what)
		: what
;

//See cast()
private boolean needsCast(genmodel::GenClass source, genmodel::GenClass target) :
	source == target ? false :
		(target == null ? 
			(source != null && source.isExternalInterface()) : 
			source == null || target.isExternalInterface() || source.isExternalInterface() || !target.ecoreClass.isSuperTypeOf(source.ecoreClass))
;

private ecore::EClassifier getEcoreClassifier(genmodel::GenClassifier gc) : null ;
private ecore::EClassifier getEcoreClassifier(genmodel::GenClass gc) : gc.ecoreClass ;
private ecore::EClassifier getEcoreClassifier(genmodel::GenDataType gc) : gc.ecoreDataType ;

// GenPackageImpl#getReflectionPackageName()
private String getReflectionPackageName(genmodel::GenPackage gp) :
	getQualifiedPackageName(gp, gp.metaDataPackageSuffix)
;

// GenPackageImpl#getQualifiedPackageClassName()
private String getQualifiedPackageClassName(genmodel::GenPackage gp) :
	getReflectionClassPackageName(gp) + "." + getPackageClassName(gp)
;


// GenPackageImpl#getReflectionClassPackageName()
private String getReflectionClassPackageName(genmodel::GenPackage gp) :
	getQualifiedPackageName(gp, gp.genModel.suppressInterfaces ? gp.metaDataPackageSuffix : gp.classPackageSuffix)
;

// GenPackageImpl#getPackageClassName()
private string getPackageClassName(genmodel::GenPackage gp) :
	!gp.genModel.suppressEMFMetaData && !gp.genModel.suppressInterfaces ? getPackageInterfaceName(gp) + "Impl" : getPackageInterfaceName(gp)
;

// GenPackageImpl#getPackageInterfaceName()
private string getPackageInterfaceName(genmodel::GenPackage gp) :
	gp.genModel.suppressEMFMetaData && !gp.genModel.suppressInterfaces ? getPrefixedName(gp, "PackageImpl") : getPrefixedName(gp, "Package")
;

// GenPackageImpl#getPrefixedName()
private string getPrefixedName(genmodel::GenPackage gp, String name) :
	null != gp.prefix ? gp.prefix + name : name
;

// GenPackageImpl#getQualifiedPackageName(String)
private String getQualifiedPackageName(genmodel::GenPackage gp, String suffix) :
	isBlank(suffix) ? getQualifiedPackageName(gp) : getQualifiedPackageName(gp) + "." + suffix
;

// GenPackageImpl#getQualifiedPackageName()
private String getQualifiedPackageName(genmodel::GenPackage gp) :
	isBlank(gp.basePackage) ? safeName(gp.ecorePackage.name) : gp.basePackage + "." + safeName(gp.ecorePackage.name)
;

// GenFeatureImpl#isMapEntryFeature
private boolean isMapEntryFeature(genmodel::GenFeature gf) :
	gf.genClass.isMapEntry() && ("key" == gf.ecoreFeature.name || "value" == gf.ecoreFeature.name)
;

private boolean isBlank(String s) :
	null == s || s.length() == 0
;

private String safeName(String name) :
JAVA org.eclipse.emf.codegen.util.CodeGenUtil.safeName(java.lang.String)
;
