package es.tid.cosmos.base.data;

import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Message;
import com.google.protobuf.Message.Builder;

import es.tid.cosmos.base.data.generated.CdrProtocol.Uler;
import es.tid.cosmos.base.data.generated.WebLogProtocol.WebLog;

/**
 * 
 * @author dmicol
 */
public abstract class MessageGenerator {
    private static final String ULER_TYPE_NAME = "uler";
    private static final String WEBLOG_TYPE_NAME = "weblog";
    
    private MessageGenerator() {
    }
    
    public static Message generate(MessageDescriptor messageDescriptor,
                                   String line) {
        final String type = messageDescriptor.getMetaFieldValue(
                MessageDescriptor.MetaFields.TYPE);
        final String delimiter = messageDescriptor.getMetaFieldValue(
                MessageDescriptor.MetaFields.DELIMITER);
        String[] fields = line.split(delimiter);
        Builder builder;
        Descriptor descriptor;
        if (type.equals(ULER_TYPE_NAME)) {
            builder = Uler.newBuilder();
            descriptor = Uler.getDescriptor();
        } else if (type.equals(WEBLOG_TYPE_NAME)) {
            builder = WebLog.newBuilder();
            descriptor = WebLog.getDescriptor();
        } else {
            throw new IllegalArgumentException("Invalid type: " + type);
        }
        return setFields(builder, descriptor, messageDescriptor, fields);
    }
    
    private static Message setFields(Builder builder, Descriptor descriptor,
                                     MessageDescriptor messageDescriptor,
                                     String[] fields) {
        for (String fieldName : messageDescriptor.getFieldNames()) {
            FieldDescriptor fieldDesc = descriptor.findFieldByName(fieldName);
            if (fieldDesc == null) {
                throw new IllegalArgumentException("Invalid field name: "
                        + fieldName);
            }
            String fieldValue;
            try {
                fieldValue = fields[messageDescriptor.getFieldColumnIndex(
                        fieldName)];
            } catch (IndexOutOfBoundsException ex) {
                throw new IllegalArgumentException("Invalid column index for "
                        + "field " + fieldName);
            }
            builder.setField(fieldDesc, cast(fieldDesc, fieldValue));
        }
        return builder.build();
    }
    
    private static Object cast(FieldDescriptor fieldDesc, String value) {
        switch (fieldDesc.getType()) {
            case BOOL:
                return Boolean.parseBoolean(value);
            case DOUBLE:
                return Double.parseDouble(value);
            case FIXED32:
            case INT32:
            case SINT32:
            case UINT32:
                return Integer.parseInt(value);
            case FIXED64:
            case INT64:
            case SINT64:
            case UINT64:
                return Long.parseLong(value);
            case FLOAT:
                return Float.parseFloat(value);
            case STRING:
                return value;
            default:
                throw new IllegalArgumentException("Invalid type for field "
                        + fieldDesc.getName());
        }
    }
}

@@ -2425,24 +2425,8 @@
 esc,
- cast(fieldDesc,
  fie
@@ -2433,17 +2433,16 @@
 ldValue)
-)
 ;%0A      
@@ -2487,857 +2487,6 @@
   %7D%0A
-    %0A    private static Object cast(FieldDescriptor fieldDesc, String value) %7B%0A        switch (fieldDesc.getType()) %7B%0A            case BOOL:%0A                return Boolean.parseBoolean(value);%0A            case DOUBLE:%0A                return Double.parseDouble(value);%0A            case FIXED32:%0A            case INT32:%0A            case SINT32:%0A            case UINT32:%0A                return Integer.parseInt(value);%0A            case FIXED64:%0A            case INT64:%0A            case SINT64:%0A            case UINT64:%0A                return Long.parseLong(value);%0A            case FLOAT:%0A                return Float.parseFloat(value);%0A            case STRING:%0A                return value;%0A            default:%0A                throw new IllegalArgumentException(%22Invalid type for field %22%0A                        + fieldDesc.getName());%0A        %7D%0A    %7D%0A
 %7D%0A

Remove cast operation.