GlobalRegistry.java
/*
* Copyright 2016 Providence Authors
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package net.morimekta.providence.reflect;
import net.morimekta.providence.descriptor.PDeclaredDescriptor;
import net.morimekta.providence.descriptor.PService;
import net.morimekta.providence.types.TypeReference;
import net.morimekta.providence.types.TypeRegistry;
import net.morimekta.util.FileUtil;
import net.morimekta.util.collect.UnmodifiableList;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static net.morimekta.providence.reflect.util.ReflectionUtils.programNameFromPath;
/**
* A global type registry containing lots of individual program
* registries for each program.
*
* The program registry is a wrapper around a set of type
* registries for each of a set of different files. The individual
* registries are identified by the <code>path</code> to the
* thrift file that was parsed.
*/
public class GlobalRegistry extends TypeRegistry {
private final Map<String, ProgramRegistry> pathToRegistry;
/**
* Create an empty program registry.
*/
public GlobalRegistry() {
pathToRegistry = new LinkedHashMap<>();
}
@Nonnull
public ProgramRegistry registryForPath(String filePath) {
try {
Path canonicalPath = FileUtil.readCanonicalPath(Paths.get(filePath));
return pathToRegistry.computeIfAbsent(
canonicalPath.toString(),
path -> new ProgramRegistry(programNameFromPath(canonicalPath)));
} catch (IOException e) {
throw new UncheckedIOException(e.getMessage(), e);
}
}
public List<ProgramRegistry> getRegistries() {
return UnmodifiableList.copyOf(pathToRegistry.values());
}
// TypeRegistry
@Nonnull
@Override
public Optional<PDeclaredDescriptor<?>> getDeclaredType(@Nonnull TypeReference reference) {
for (ProgramRegistry registry : pathToRegistry.values()) {
if (registry.getProgramContext().equals(reference.programName)) {
Optional<PDeclaredDescriptor<?>> out = registry.getDeclaredType(reference);
if (out.isPresent()) {
return out;
}
}
}
return Optional.empty();
}
@Nonnull
@Override
public Optional<PService> getService(@Nonnull TypeReference reference) {
for (ProgramRegistry registry : pathToRegistry.values()) {
if (registry.getProgramContext().equals(reference.programName)) {
Optional<PService> out = registry.getService(reference);
if (out.isPresent()) {
return out;
}
}
}
return Optional.empty();
}
@Nonnull
@Override
public <T> Optional<T> getConstantValue(@Nonnull TypeReference reference) {
for (ProgramRegistry registry : pathToRegistry.values()) {
if (registry.getProgramContext().equals(reference.programName)) {
Optional<T> out = registry.getConstantValue(reference);
if (out.isPresent()) {
return out;
}
}
}
return Optional.empty();
}
@Nonnull
@Override
public Optional<TypeReference> getTypedef(@Nonnull TypeReference reference) {
for (ProgramRegistry registry : pathToRegistry.values()) {
if (registry.getProgramContext().equals(reference.programName)) {
Optional<TypeReference> out = registry.getTypedef(reference);
if (out.isPresent()) {
return out;
}
}
}
return Optional.empty();
}
@Override
public List<PDeclaredDescriptor<?>> getDeclaredTypes() {
Set<PDeclaredDescriptor<?>> combined = new HashSet<>();
for (ProgramRegistry registry : pathToRegistry.values()) {
combined.addAll(registry.getDeclaredTypes());
}
return UnmodifiableList.copyOf(combined);
}
@Override
public boolean isKnownProgram(@Nonnull String program) {
for (ProgramRegistry registry : pathToRegistry.values()) {
if (registry.getProgramContext().equals(program)) {
return true;
}
}
return false;
}
}