/** * */ package org.ebayopensource.turmeric.tools.codegen.proto; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.wsdl.Definition; import org.ebayopensource.turmeric.tools.codegen.CodeGenContext; import org.ebayopensource.turmeric.tools.codegen.InputOptions; import org.ebayopensource.turmeric.tools.codegen.ServiceCodeGenArgsParser; import org.ebayopensource.turmeric.tools.codegen.ServiceCodeGenArgsValidator; import org.ebayopensource.turmeric.tools.codegen.exception.BadInputOptionException; import org.ebayopensource.turmeric.tools.codegen.exception.BadInputValueException; import org.ebayopensource.turmeric.tools.codegen.exception.CodeGenFailedException; import org.ebayopensource.turmeric.tools.codegen.exception.MissingInputOptionException; import org.ebayopensource.turmeric.tools.codegen.external.WSDLUtil; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.dotproto.DotProtoGenerator; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufEnumEntry; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufEnumMessage; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufField; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufFieldModifier; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufFieldType; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufMessage; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufSchema; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.SchemaTypeName; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.tag.DefaultProtobufTagGenerator; import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.tag.ProtobufTagGenerator; import org.ebayopensource.turmeric.tools.codegen.handler.ConsoleResponseHandler; import org.ebayopensource.turmeric.tools.codegen.handler.DontPromptResponseHandler; import org.ebayopensource.turmeric.tools.codegen.handler.UserResponseHandler; import org.ebayopensource.turmeric.tools.codegen.util.CodeGenUtil; import org.ebayopensource.turmeric.tools.library.TypeLibraryInputOptions; import org.ebayopensource.turmeric.tools.library.codegen.TypeLibraryCodeGenArgsParser; import org.ebayopensource.turmeric.tools.library.codegen.TypeLibraryCodeGenArgsValidator; import org.ebayopensource.turmeric.tools.library.codegen.TypeLibraryCodeGenBuilder; import org.ebayopensource.turmeric.tools.library.codegen.TypeLibraryCodeGenContext; import edu.emory.mathcs.backport.java.util.Arrays; /** * @author rkulandaivel * */ @SuppressWarnings("unchecked") public class ProtobufSchemaMapperTestUtils { private static final String GEN_SRC_FOLDER ="gen-src"; private static final String GEN_META_SRC_FOLDER ="gen-meta-src"; private static final List<String> s_protobufTypes = Arrays.asList(new String[]{ "int32", "sint32", "string", "double", "bool", "bytes", "sint64", "float" }); private static InputOptions getInputOptions(String[] args) throws MissingInputOptionException, BadInputOptionException, BadInputValueException { // Parse & Validate input arguments InputOptions inputOptions = ServiceCodeGenArgsParser.getInstance() .parse(args); ServiceCodeGenArgsValidator.getInstance().validate(inputOptions); return inputOptions; } private static CodeGenContext createContext( InputOptions inputOptions, UserResponseHandler userResponseHandler) throws CodeGenFailedException { CodeGenContext codeGenCtx = new CodeGenContext(inputOptions, userResponseHandler); String javaSrcDestLoc = inputOptions.getJavaSrcDestLocation(); String metaSrcDestLoc = inputOptions.getMetaSrcDestLocation(); String destLocation = inputOptions.getDestLocation(); // Generated Java Source files will go here if (CodeGenUtil.isEmptyString(javaSrcDestLoc)) { // set it to default javaSrcDestLoc = CodeGenUtil.genDestFolderPath(destLocation, GEN_SRC_FOLDER); } // Generated XML/Config files will go here if (CodeGenUtil.isEmptyString(metaSrcDestLoc)) { // set it to default metaSrcDestLoc = CodeGenUtil.genDestFolderPath(destLocation, GEN_META_SRC_FOLDER); } // Compiled Java Classes will go here String binLocation = inputOptions.getBinLocation(); if (CodeGenUtil.isEmptyString(binLocation)) { binLocation = CodeGenUtil.genDestFolderPath(destLocation, "bin"); inputOptions.setBinLocation(binLocation); } // create directories if doesn't exists try { CodeGenUtil.createDir(javaSrcDestLoc); CodeGenUtil.createDir(metaSrcDestLoc); CodeGenUtil.createDir(binLocation); } catch (IOException ioEx) { throw new CodeGenFailedException(ioEx.getMessage(), ioEx); } codeGenCtx.setJavaSrcDestLocation(javaSrcDestLoc); codeGenCtx.setMetaSrcDestLocation(metaSrcDestLoc); return codeGenCtx; } private static TypeLibraryCodeGenContext createContext( TypeLibraryInputOptions typeLibraryOptions, UserResponseHandler userResponseHandler) throws CodeGenFailedException { TypeLibraryCodeGenContext typeLibraryCodeGenCtx = new TypeLibraryCodeGenContext(typeLibraryOptions, userResponseHandler); return typeLibraryCodeGenCtx; } public static TypeLibraryInputOptions getTypeLibraryInputOptions(String[] args) throws MissingInputOptionException, BadInputOptionException, BadInputValueException { // Parse & Validate input arguments TypeLibraryInputOptions typeLibraryInputOptions = TypeLibraryCodeGenArgsParser.getInstance().parseTypeLibraryOptions(args); TypeLibraryCodeGenArgsValidator.getInstance().validate(typeLibraryInputOptions); return typeLibraryInputOptions; } public static TypeLibraryCodeGenContext getTypeLibraryCodeGenContext(String[] pluginParameters, TypeLibraryCodeGenBuilder builder) throws Exception{ TypeLibraryInputOptions typeLibraryInputOptions = builder.getTypeLibraryInputOptions(pluginParameters); UserResponseHandler userResponseHandler = null; if (typeLibraryInputOptions.isDontPrompt()) { userResponseHandler = new DontPromptResponseHandler(); } else if (userResponseHandler == null) { userResponseHandler = new ConsoleResponseHandler(); } return createContext(typeLibraryInputOptions, userResponseHandler); } public static CodeGenContext getCodeGenContext(String testArgs[]) throws Exception{ //String testArgs[] = getTestAWsdlArgs(); InputOptions inputOptions =getInputOptions( testArgs ); UserResponseHandler userResponseHandler = null; if (inputOptions.isDontPrompt()) { userResponseHandler = new DontPromptResponseHandler(); } else if (userResponseHandler == null) { userResponseHandler = new ConsoleResponseHandler(); } CodeGenContext context = createContext( inputOptions , userResponseHandler); String wsdlFileLoc = context.getInputOptions().getInputFile(); if(context.getWsdlDefinition() == null){ Definition definition = WSDLUtil.getWSDLDefinition(wsdlFileLoc); context.setWsdlDefinition(definition); } context.setWSDLURI(wsdlFileLoc); WSDLUtil.populateCodegenCtxWithWSDLDetails(wsdlFileLoc, context); return context; } public static List<ProtobufMessage> loadFindItemServiceManuallyWrittenProtoFile( String dotprotofilepath ) throws Exception{ //String dotprotofilepath = "UnitTests/src/com/ebay/test/soaframework/tools/codegen/data/FindItemServiceAdjustedV3.proto"; DataInputStream in = null; try{ FileInputStream fstream = new FileInputStream( dotprotofilepath ); // Get the object of DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String strLine; boolean messageInLoop = false; boolean isEnumMessage = false; ProtobufMessage message = null; List<ProtobufMessage> messages = new ArrayList<ProtobufMessage>(); //Read File Line By Line while ((strLine = br.readLine()) != null) { // Print the content on the console //System.out.println (strLine); strLine = strLine.trim(); if(CodeGenUtil.isEmptyString(strLine)){ continue; } if(strLine.startsWith("//") || strLine.startsWith("package") || strLine.startsWith("option ")){ continue; }else if(strLine.startsWith("message")){ String messageName = getMessageNameFromLine( strLine ); message = new ProtobufMessage(); messageInLoop = true; message.setMessageName(messageName); }else if(messageInLoop && strLine.startsWith("enum")){ String enumMessageName = getEnumMessageNameFromLine( strLine ); isEnumMessage = true; ProtobufEnumMessage enumMessage = new ProtobufEnumMessage(); enumMessage.setEnumMessageName(message.getMessageName()); enumMessage.setMessageName(enumMessageName); enumMessage.setEnumType(true); message = enumMessage; }else if(messageInLoop && strLine.startsWith("}")){ if(messageInLoop && isEnumMessage){ isEnumMessage = false; }else if(messageInLoop){ messageInLoop = false; messages.add(message); } }else{ if(isEnumMessage){ ProtobufEnumEntry enumEntry = parseLineAndReturnEnumInstance( strLine ); ((ProtobufEnumMessage)message).getEnumEntries().add(enumEntry); }else{ ProtobufField field = parseLineAndReturnFieldInstance( strLine ); message.getFields().add(field); } } } return messages; }finally{ //Close the input stream if(in != null){ in.close(); } } } public static ProtobufField parseLineAndReturnFieldInstance(String strLine) throws Exception{ String[] parts = strLine.split("="); if(parts.length != 2){ throw new Exception("Invalid line"); } String lineBeforeEqualSign = parts[0]; lineBeforeEqualSign = lineBeforeEqualSign.trim(); String[] fieldInfoParts = lineBeforeEqualSign.split(" "); if(fieldInfoParts.length != 3){ throw new Exception("Invalid line"); } String lineAfterEqualSign = parts[1].trim(); String seqNo = lineAfterEqualSign.substring(0, lineAfterEqualSign.length()-1); seqNo = seqNo.trim(); ProtobufField field = new ProtobufField(); field.setFieldModifier( ProtobufFieldModifier.fromValue( fieldInfoParts[0] ) ); String fieldType = fieldInfoParts[1].trim(); field.setProtobufTypeName(fieldType); String fieldName = fieldInfoParts[2].trim(); field.setFieldName(fieldName); field.setConvertedFieldName(fieldName); field.setSequenceTagNumber( Integer.parseInt( seqNo ) ); return field; } public static ProtobufEnumEntry parseLineAndReturnEnumInstance(String strLine) throws Exception{ String[] parts = strLine.split("="); if(parts.length != 2){ throw new Exception("Invalid line"); } String lineBeforeEqualSign = parts[0]; lineBeforeEqualSign = lineBeforeEqualSign.trim(); String lineAfterEqualSign = parts[1].trim(); String seqNo = lineAfterEqualSign.substring(0, lineAfterEqualSign.length()-1); seqNo = seqNo.trim(); ProtobufEnumEntry field = new ProtobufEnumEntry(); field.setEnumValue(lineBeforeEqualSign); field.setSequenceNumber(Integer.parseInt( seqNo )); return field; } public static String getEnumMessageNameFromLine(String strLine){ final String messageKeyWord = "enum"; int index = strLine.indexOf( messageKeyWord ); strLine = strLine.substring(index + messageKeyWord.length()); int endIndex = strLine.lastIndexOf("{"); strLine = strLine.substring(0, endIndex); return strLine.trim(); } public static String getMessageNameFromLine(String strLine){ final String messageKeyWord = "message"; int index = strLine.indexOf( messageKeyWord ); strLine = strLine.substring(index + messageKeyWord.length()); int endIndex = strLine.lastIndexOf("{"); strLine = strLine.substring(0, endIndex); return strLine.trim(); } public static Map<SchemaTypeName, ProtobufMessage> createMessageMapFromList(List<ProtobufMessage> messages){ Map<SchemaTypeName, ProtobufMessage> schemaTypeMap = new HashMap<SchemaTypeName, ProtobufMessage>(); for(ProtobufMessage message : messages){ schemaTypeMap.put(message.getSchemaTypeName() , message); } return schemaTypeMap; } public static ProtobufFieldType getFieldType(ProtobufField field){ String typeName = field.getProtobufTypeName(); if( typeName.indexOf(".") > 0 ){ return ProtobufFieldType.ENUM_TYPE; } if(!s_protobufTypes.contains( typeName ) ){ return ProtobufFieldType.COMPLEX_TYPE; } return ProtobufFieldType.INBUILT_TYPE; } public static class ProtobufMessageComparator { public static boolean compareEnumMessage(ProtobufEnumMessage object1, ProtobufEnumMessage object2) { if(!compareMessage(object1, object2)){ return false; } if(object1.getEnumMessageName() == null || object2.getEnumMessageName() == null){ return false; } if( !(object1.getEnumMessageName().equals(object2.getEnumMessageName())) ){ return false; } if( !(compareEnumFields( object1.getEnumEntries(), object2.getEnumEntries() )) ){ return false; } return true; } public static boolean compareMessage(ProtobufMessage object1, ProtobufMessage object2) { if(object1.getMessageName() == null || object2.getMessageName() == null){ return false; } if( !(object1.getMessageName().equals(object2.getMessageName())) ){ return false; } if(object1.getEprotoClassName() == null || object2.getEprotoClassName() == null){ return false; } if( !(object1.getEprotoClassName().equals(object2.getEprotoClassName())) ){ return false; } if(object1.getJprotoClassName() == null || object2.getJprotoClassName() == null){ return false; } if( !(object1.getJprotoClassName().equals(object2.getJprotoClassName())) ){ return false; } if(object1.getJaxbClassName() == null || object2.getJaxbClassName() == null){ return false; } if( !(object1.getJaxbClassName().equals(object2.getJaxbClassName())) ){ return false; } if( object1.isEnumType() != object2.isEnumType() ){ return false; } if( !(compareFields( object1.getFields(), object2.getFields() ) ) ){ return false; } return true; } public static boolean compareFields(List<ProtobufField> msg1Fields, List<ProtobufField> msg2Fields) { List<ProtobufField> list1 = (List<ProtobufField>) msg1Fields; List<ProtobufField> list = (List<ProtobufField>) msg2Fields; if (list.size() != list1.size()) { return false; } Collections.sort(list1, new ProtobufFieldComparator() ); Collections.sort(list, new ProtobufFieldComparator() ); Iterator<ProtobufField> it1 = list1.iterator(), it2 = list.iterator(); while (it1.hasNext()) { ProtobufField e1 = it1.next(), e2 = it2.next(); if (!(e1 == null ? (e2 == null) : compareField(e1, e2)) ){ return false; } } return true; } public static boolean compareField(ProtobufField field1, ProtobufField field2) { if(field1.getConvertedFieldName() == null || field2.getConvertedFieldName() == null ){ return false; } if( !(field1.getConvertedFieldName().equals(field2.getConvertedFieldName())) ){ return false; } if( !(field1.getFieldModifier().equals(field2.getFieldModifier())) ){ return false; } if(field1.getProtobufTypeName() == null || field2.getProtobufTypeName() == null ){ return false; } if( !(field1.getProtobufTypeName().equals(field2.getProtobufTypeName())) ){ return false; } if(field1.getTypeOfField() == null || field2.getTypeOfField() == null ){ return false; } ProtobufFieldType type1 = field1.getTypeOfField(); ProtobufFieldType type2 = field2.getTypeOfField(); if( type1 != type2 ){ if(type1 == ProtobufFieldType.DATE_TYPE || type1 == ProtobufFieldType.DURATION_TYPE || type1 == ProtobufFieldType.DURATION_TYPE){ if(type2 != ProtobufFieldType.INBUILT_TYPE){ return false; } }else if(type2 == ProtobufFieldType.DATE_TYPE || type2 == ProtobufFieldType.DURATION_TYPE || type2 == ProtobufFieldType.DURATION_TYPE){ if(type1 != ProtobufFieldType.INBUILT_TYPE){ return false; } } } return true; } public static boolean compareEnumFields(List<ProtobufEnumEntry> msg1Fields, List<ProtobufEnumEntry> msg2Fields) { List<ProtobufEnumEntry> list1 = (List<ProtobufEnumEntry>) msg1Fields; List<ProtobufEnumEntry> list = (List<ProtobufEnumEntry>) msg2Fields; if (list.size() != list1.size()) { return false; } Iterator<ProtobufEnumEntry> it1 = list1.iterator(), it2 = list.iterator(); while (it1.hasNext()) { ProtobufEnumEntry e1 = it1.next(), e2 = it2.next(); if (!(e1 == null ? (e2 == null) : compareEnumField(e1, e2)) ){ return false; } } return true; } public static boolean compareEnumField(ProtobufEnumEntry field1, ProtobufEnumEntry field2) { if(field1.getEnumValue() == null || field2.getEnumValue() == null ){ return false; } if( !(field1.getEnumValue().equals(field2.getEnumValue())) ){ return false; } return true; } } private static class ProtobufFieldComparator implements Comparator<ProtobufField>{ @Override public int compare(ProtobufField object1, ProtobufField object2) { if( object1 == null && object2 == null){ return 0; } if( object1 == null ){ return -1; } if( object2 == null ){ return 1; } int xx = object1.getConvertedFieldName().compareTo( object2.getConvertedFieldName() ); return xx; } } public static void validateTagNumberGeneration( CodeGenContext context, ProtobufSchema schema ) throws Exception { ProtobufTagGenerator generator = null; try { generator = new DefaultProtobufTagGenerator(new File( context.getInputOptions().getInputFile() ), null ); } catch (Exception e) { throw e; } try { DotProtoGenerator.getInstance().updateSchemaWithSequenceNumbers( schema, generator, true ); } catch (Exception e1) { throw e1; } } }