org.infinispan.protostream.descriptors.ResolutionContext Maven / Gradle / Ivy
package org.infinispan.protostream.descriptors;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.infinispan.protostream.DescriptorParserException;
import org.infinispan.protostream.FileDescriptorSource;
import org.infinispan.protostream.impl.Log;
/**
* @author [email protected]
* @since 3.1
*/
public class ResolutionContext {
private static final Log log = Log.LogFactory.getLog(ResolutionContext.class);
private final FileDescriptorSource.ProgressCallback progressCallback;
private final Map fileDescriptorMap;
private final Map allTypeIds;
private final Map typeIds = new HashMap<>();
private Map allGlobalTypes;
private Map globalTypes = new HashMap<>();
private Map allEnumValueDescriptors;
private Map enumValueDescriptors = new HashMap<>();
public ResolutionContext(FileDescriptorSource.ProgressCallback progressCallback,
Map fileDescriptorMap,
Map allGlobalTypes,
Map allTypeIds,
Map allEnumValueDescriptors) {
this.progressCallback = progressCallback;
this.fileDescriptorMap = fileDescriptorMap;
this.allGlobalTypes = allGlobalTypes;
this.allTypeIds = allTypeIds;
this.allEnumValueDescriptors = allEnumValueDescriptors;
}
void handleError(FileDescriptor fileDescriptor, DescriptorParserException dpe) {
if (log.isDebugEnabled()) {
log.debugf(dpe, "File has errors : %s", fileDescriptor.getName());
}
fileDescriptor.status = FileDescriptor.Status.ERROR;
if (progressCallback == null) {
throw dpe;
}
progressCallback.handleError(fileDescriptor.getName(), dpe);
}
void handleSuccess(FileDescriptor fileDescriptor) {
if (log.isDebugEnabled()) {
log.debugf("File resolved successfully : %s", fileDescriptor.getName());
}
if (progressCallback != null) {
progressCallback.handleSuccess(fileDescriptor.getName());
}
}
Map getFileDescriptorMap() {
return fileDescriptorMap;
}
void addGenericDescriptor(GenericDescriptor genericDescriptor) {
checkUniqueName(genericDescriptor);
if (genericDescriptor.getTypeId() != null) {
checkUniqueTypeId(genericDescriptor);
typeIds.put(genericDescriptor.getTypeId(), genericDescriptor);
}
globalTypes.put(genericDescriptor.getFullName(), genericDescriptor);
if (genericDescriptor instanceof EnumDescriptor) {
EnumDescriptor enumDescriptor = (EnumDescriptor) genericDescriptor;
for (EnumValueDescriptor ev : enumDescriptor.getValues()) {
enumValueDescriptors.put(ev.getScopedName(), ev);
}
}
}
private void checkUniqueName(GenericDescriptor genericDescriptor) {
GenericDescriptor existingGenericDescriptor = lookup(globalTypes, allGlobalTypes, genericDescriptor.getFullName());
if (existingGenericDescriptor != null) {
List locations = Arrays.asList(genericDescriptor.getFileDescriptor().getName(), existingGenericDescriptor.getFileDescriptor().getName());
if (locations.get(0).equals(locations.get(1))) {
throw new DescriptorParserException("Duplicate definition of " + genericDescriptor.getFullName() + " in " + locations.get(0));
}
Collections.sort(locations); // sort names for more predictable error messages in unit tests
throw new DescriptorParserException("Duplicate definition of " + genericDescriptor.getFullName() + " in " + locations.get(0) + " and " + locations.get(1));
}
EnumValueDescriptor existingEnumValueDescriptor = lookup(enumValueDescriptors, allEnumValueDescriptors, genericDescriptor.getFullName());
if (existingEnumValueDescriptor != null) {
List locations = Arrays.asList(genericDescriptor.getFileDescriptor().getName(), existingEnumValueDescriptor.getFileDescriptor().getName());
Collections.sort(locations);
throw new DescriptorParserException((genericDescriptor instanceof EnumDescriptor ? "Enum" : "Message") + " definition " + genericDescriptor.getFullName()
+ " clashes with enum value " + existingEnumValueDescriptor.getFullName());
}
if (genericDescriptor instanceof EnumDescriptor) {
EnumDescriptor enumDescriptor = (EnumDescriptor) genericDescriptor;
for (EnumValueDescriptor ev : enumDescriptor.getValues()) {
// check if this enum value constant conflicts with another enum value constant
existingEnumValueDescriptor = lookup(enumValueDescriptors, allEnumValueDescriptors, ev.getScopedName());
if (existingEnumValueDescriptor != null) {
throw new DescriptorParserException("Enum value " + ev.getFullName() + " clashes with enum value " + existingEnumValueDescriptor.getFullName());
}
existingGenericDescriptor = lookup(globalTypes, allGlobalTypes, ev.getScopedName());
if (existingGenericDescriptor != null) {
throw new DescriptorParserException("Enum value " + ev.getFullName() + " clashes with " + (existingGenericDescriptor instanceof EnumDescriptor ? "enum" : "message")
+ " definition " + existingGenericDescriptor.getFullName());
}
}
}
}
private void checkUniqueTypeId(GenericDescriptor descriptor) {
GenericDescriptor existing = lookup(typeIds, allTypeIds, descriptor.getTypeId());
if (existing != null) {
throw new DescriptorParserException("Duplicate type id " + descriptor.getTypeId() + " for type " + descriptor.getFullName() + ". Already used by " + existing.getFullName());
}
}
private V lookup(Map first, Map second, K k) {
V v = first.get(k);
return v != null ? v : second.get(k);
}
void flush() {
allGlobalTypes.putAll(globalTypes);
allTypeIds.putAll(typeIds);
allEnumValueDescriptors.putAll(enumValueDescriptors);
clear();
}
void clear() {
globalTypes.clear();
typeIds.clear();
enumValueDescriptors.clear();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy