/**
 * File:    PropertyAspectFactory.java
 * Created: 28.07.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2007-2009 Open Wide SA, France <www.openwide.fr>
 *
 * 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:
 *    Marc Dutoo, Open Wide SA 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.conf.property.model.aspects;

import java.math.BigDecimal;
import java.util.Date;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jwt.we.conf.model.Aspect;
import org.eclipse.jwt.we.conf.model.AspectInstance;
import org.eclipse.jwt.we.conf.model.ConfPackage;
import org.eclipse.jwt.we.conf.model.aspects.factory.RegistryAspectFactory;
import org.eclipse.jwt.we.conf.property.model.property.Property;
import org.eclipse.jwt.we.conf.property.model.property.PropertyPackage;


/**
 * Property aspect factory, meant to be default.
 * 
 * [#311818] 2010/05/06 Moved from org.eclipse.jwt.we.conf.aspects.factory to avoid package conflict at build time
 * 
 * @version $Id: PropertyAspectFactory.java,v 1.1 2010-05-10 10:04:27 chsaad Exp $
 * @author Marc Dutoo, Open Wide SA
 * @since 0.6
 */
public class PropertyAspectFactory implements RegistryAspectFactory {
	
	/** Created when registered */
	public static PropertyAspectFactory INSTANCE = null;

	public PropertyAspectFactory() {
		INSTANCE = this;
	}
	
	
	public boolean isFactoryFor(Aspect aspect) {
		// not null nor proxy, already checked
		EClassifier aspectInstanceETypeEClassifier = aspect.getAspectInstanceEType();
		return (aspectInstanceETypeEClassifier instanceof EDataType)
				|| ((aspectInstanceETypeEClassifier instanceof EClass)
						&& !ConfPackage.eINSTANCE.getAspectInstance().isSuperTypeOf((EClass) aspectInstanceETypeEClassifier));
	}
	

	public AspectInstance createAspectInstance(Aspect aspect, EObject modelElement) {
		// not null nor proxy, already checked
		EClassifier aspectInstanceETypeEClassifier = aspect.getAspectInstanceEType();
	  	  
        // Now handling various Property Aspect cases
        if (aspectInstanceETypeEClassifier instanceof EDataType) {
        	// Property with a primitive value type
      	  EDataType eDataType = (EDataType) aspectInstanceETypeEClassifier;
      	  return createAspectDataProperty(eDataType, aspect.getDefaultValue());
    			
        } else if (aspectInstanceETypeEClassifier instanceof EClass) { // custom Aspect
      	  EClass aspectInstanceEClass = (EClass) aspectInstanceETypeEClassifier;
      	  
      	  // only if !ConfPackage.eINSTANCE.getAspectInstance().isSuperTypeOf(aspectInstanceEClass) :
      	  // Property with an EObject value type
      	  return createAspectObjectProperty(aspectInstanceEClass);
      	  
        }
        return null;
	}
	

	/** 
	 * @param eDataType
	 * @return a new instance of Property of the given data type
	 */
	public Property createAspectDataProperty(EDataType eDataType, String defaultStringValue) {
	    // building Property
	    Property property = PropertyPackage.eINSTANCE.getPropertyFactory().createProperty();
		// creating Property default value
	    Object propertyValue = createDefaultValue(eDataType, defaultStringValue);
  	    if (propertyValue != null) {
	        property.setValue(propertyValue);
  	    }
		return property;
	}

	public Object createDefaultValue(EDataType eDataType, String defaultStringValue) {
		// getting an ok string value
  	    if (eDataType.getInstanceClass() == String.class) {
	    	defaultStringValue = (defaultStringValue == null) ? "" : defaultStringValue; //$NON-NLS-1$
	    	
	    } else if (defaultStringValue == null || defaultStringValue.length() == 0) {
	    	
	    	if (eDataType.getInstanceClass() == Boolean.class || eDataType.getInstanceClass() == Boolean.TYPE) {
	    		defaultStringValue = "true"; //$NON-NLS-1$
	    	} else if (eDataType.getInstanceClass() == Integer.class || eDataType.getInstanceClass() == Integer.TYPE
	    			|| eDataType.getInstanceClass() == Byte.class || eDataType.getInstanceClass() == Byte.TYPE
	  	    		|| eDataType.getInstanceClass() == Character.class || eDataType.getInstanceClass() == Character.TYPE
	  	    		|| eDataType.getInstanceClass() == Short.class || eDataType.getInstanceClass() == Short.TYPE
	  	    		|| eDataType.getInstanceClass() == Float.class || eDataType.getInstanceClass() == Float.TYPE
	  	    		|| eDataType.getInstanceClass() == Double.class || eDataType.getInstanceClass() == Double.TYPE
	  	    		|| eDataType.getInstanceClass() == BigDecimal.class) {
	  	    	defaultStringValue = "0"; //$NON-NLS-1$
	    	}
  	    }
  	    
  	    // building the property value
	  	Object propertyValue = null;
  	    if (defaultStringValue != null) {
  	  	    propertyValue = eDataType.getEPackage().getEFactoryInstance().createFromString(eDataType, defaultStringValue);   
  	    } else if (eDataType.getInstanceClass() == Date.class) {
  	    	propertyValue = new Date();
  	    }
		return propertyValue;
	}


	/**
	 * @param aspectInstanceEClass
	 * @return a new instance of Property with a new instance of the given type as its value
	 */
	public Property createAspectObjectProperty(
			EClass aspectInstanceEClass) {
		// creating Property default value
		EFactory propertyValueEFactory = aspectInstanceEClass.getEPackage().getEFactoryInstance();
		Object defaultValue = propertyValueEFactory.create(aspectInstanceEClass);
		// building Property
		Property property = PropertyPackage.eINSTANCE.getPropertyFactory().createProperty();
		property.setValue(defaultValue);
		return property;
	}
	
}
