package org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.tag; import java.io.File; import java.io.FileInputStream; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import javax.wsdl.Definition; import javax.wsdl.factory.WSDLFactory; import javax.wsdl.xml.WSDLReader; import javax.xml.namespace.QName; import org.ebayopensource.turmeric.tools.codegen.external.wsdl.parser.schema.SchemaType; import org.xml.sax.InputSource; public class DefaultProtobufTagGenerator implements ProtobufTagGenerator { private ProtobufMetadataReader metadataReader = new ProtobufMetadataFileReader(); private QnameMapBuilder qnameMapBuilder = null; private Map<QName, SchemaType> schemaMap = null; private Map<QName, SchemaType> elementMap = null; private Map<String, Integer> tagKeyMap = new HashMap<String, Integer>(); private Map<String, Integer> tagRepeatedTypeNameMap = new HashMap<String, Integer>(); private Map<String, Integer> tagSingleTypeNameMap = new HashMap<String, Integer>(); private Definition definition; public DefaultProtobufTagGenerator(File wsdlFileLocation, File protofileLocation) { try { Map<String, Integer> read = null; if (protofileLocation!=null && protofileLocation.exists()) { FileInputStream fileInputStream = new FileInputStream(protofileLocation); read = metadataReader.read(fileInputStream); fileInputStream.close(); } else { read = new HashMap<String, Integer>(); } ProtobufMetadataHelper helper = new ProtobufMetadataHelper(read); Map<String, Integer> compoundKeys = helper.getCompoundKeys(); Map<String, Integer> repeatedKeys = helper.getRepeatedKeys(); Map<String, Integer> singleKeys = helper.getSingleKeys(); tagKeyMap.putAll(compoundKeys); tagRepeatedTypeNameMap.putAll(repeatedKeys); tagSingleTypeNameMap.putAll(singleKeys); WSDLReader reader = WSDLFactory.newInstance().newWSDLReader(); InputSource inputSource = new InputSource(new FileInputStream(wsdlFileLocation)); definition = reader.readWSDL(null, inputSource); qnameMapBuilder = new QnameMapBuilder(definition); schemaMap = qnameMapBuilder.getSchemaMap(); elementMap = qnameMapBuilder.getElementMap(); } catch (Exception e) { throw new RuntimeException(e); } } @Override public Map<String, Integer> getTagsForType(QName qName) { Map<String, Integer> result = new TreeMap<String, Integer>(); SchemaTypeResolver resolver = new SchemaTypeResolver(qnameMapBuilder); // TODO reserved values. Avoid them. SchemaType schemaType = schemaMap.get(qName); schemaType = schemaType==null ?elementMap.get(qName):schemaType; if(schemaType==null) { return Collections.emptyMap(); } List<ProtoMessageTag> elements = resolver.getElements(schemaType); for (ProtoMessageTag tag : elements) { String elementName = tag.getElementName(); String tagKey = tag.getKey(); String typeName = tag.getTypeName(); if(elementName==null) { elementName = tag.getElementType(); } Integer tagNumber = tagKeyMap.get(tagKey); if(result.containsKey(elementName)) { throw new RuntimeException("Internal Exception. Tag generation contains duplicate keys: " + elementName); } if (tagNumber == null) { Map<String, Integer> mapToUse = null; Integer lastUsedNumber = null; if (tag.isRepeating() || tag.isRequired()) { mapToUse = tagRepeatedTypeNameMap; lastUsedNumber = mapToUse.get(typeName); if (lastUsedNumber == null) { lastUsedNumber = ProtobufTagConstants.S_PROTO_REQUIRED_TAG_START_NUMBER-1; } if (lastUsedNumber > ProtobufTagConstants.S_PROTO_OPTIONAL_TAG_START_NUMBER-2) { mapToUse = tagSingleTypeNameMap; lastUsedNumber = mapToUse.get(typeName); if (lastUsedNumber == null) { lastUsedNumber = ProtobufTagConstants.S_PROTO_OPTIONAL_TAG_START_NUMBER-1; } } } else { mapToUse = tagSingleTypeNameMap; lastUsedNumber = mapToUse.get(typeName); if (lastUsedNumber == null) { lastUsedNumber = ProtobufTagConstants.S_PROTO_OPTIONAL_TAG_START_NUMBER-1; } } lastUsedNumber = lastUsedNumber + 1; mapToUse.put(typeName, lastUsedNumber); tagKeyMap.put(tagKey, lastUsedNumber); result.put(elementName, lastUsedNumber); } else { result.put(elementName, tagNumber); } } return Collections.unmodifiableMap(result); } @Override public Map<String, Integer> getTagsToPersist() { Map<String, Integer> toWrite = new TreeMap<String, Integer>(); toWrite.putAll(tagKeyMap); Set<Entry<String, Integer>> entrySet = tagRepeatedTypeNameMap.entrySet(); for (Entry<String, Integer> entry : entrySet) { String key = entry.getKey(); Integer value = entry.getValue(); key = key + ProtobufMetadataConstants.S_REPEATED_TAG_KEY; toWrite.put(key, value); } entrySet = tagSingleTypeNameMap.entrySet(); for (Entry<String, Integer> entry : entrySet) { String key = entry.getKey(); Integer value = entry.getValue(); key = key + ProtobufMetadataConstants.S_SINGLE_TAG_KEY; toWrite.put(key, value); } return toWrite; } }