//electValue chooses the best value for the variable in hand.
//The preferences goes as
//	1.	The value read from the environment
//	2.	The default value
//	3.	Corresponding zero value if 1 & 2 fails and the variable
//		is set as optional
//Returns error if the value is missing(both in environment
//and as default) and the variable is set to mandatory.
func (f *fieldMeta) electValue() (string, *models.EnvError) {
	if f.valueHolder != "" {
		return f.valueHolder, nil
	} else if f.defVal != "" {
		return f.defVal, nil
	} else if f.mandatory {
		return "", models.MandatoryValueMissing()
	}
	return "", models.OptionalValueMissing()
}
//Map performs the mapping of the environment value
//to the struct.
//source is the structure to which environment values
//are to be mapped.
func (e EnvToStruct) Map(source interface{}) error {
	completeError = EnvError{}
	if source == nil {
		return errors.New("invalid source;")
	}

	rType := reflect.TypeOf(source)
	if rType.Kind() != reflect.Ptr {
		return errors.New("Expects pointer to target object")
	}
	rType = rType.Elem()
	if rType.Kind() != reflect.Struct {
		return errors.New("Expects pointer to struct")
	}
	rFieldNum := rType.NumField()
	metaHolder := make(map[int]fieldMeta, rFieldNum)

	for i := 0; i < rFieldNum; i++ {
		rTFi := rType.Field(i)
		thisMeta := fieldMeta{}
		thisMeta.position = i
		rFTag := rTFi.Tag.Get(APP_TAG)
		tagInfo, tagEr := tagParser(rFTag)
		if tagEr != nil {
			return *tagEr
		}
		thisMeta.envName = tagInfo.name
		thisMeta.mandatory = tagInfo.mandatory
		thisMeta.defVal = tagInfo.deftVal
		metaHolder[i] = thisMeta
	}
	metaHolder = e.envToHolder(e.appName+e.separator, metaHolder)

	rValue := reflect.ValueOf(source)
	if rValue.IsNil() {
		return errors.New("pointer to nil obtained.")
	}

	if rValue.Kind() == reflect.Ptr {
		rValue = rValue.Elem()
	}
	for i := 0; i < rFieldNum; i++ {
		rVFi := rValue.Field(i)
		rTFi := rType.Field(i)
		if rVFi.Kind() == reflect.Ptr {
			rVFi = rVFi.Elem()
		}
		if rVFi.CanSet() {
			thisMeta := metaHolder[i]
			electedVal, electionError := thisMeta.electValue()
			if electionError != nil {
				if *electionError == *models.OptionalValueMissing() {
					continue
				}
				comepleteErorr = completeError.Append("optional valuen missing " + rTFi.Name)
			}
			switch rTFi.Type.Kind() {
			case reflect.Int:
				intVal, convErr := strconv.Atoi(electedVal)
				if convErr != nil {
					completeError.Append("conversion error " + rTFi.Name)
				}
				rVFi.Set(reflect.ValueOf(intVal))
			case reflect.String:
				rVFi.Set(reflect.ValueOf(electedVal))
			}
		}
	}
	return *completeError
}