/*
* Copyright 2015 MovingBlocks
*
* Licensed 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 org.terasology.world.viewer.layers;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.module.ModuleEnvironment;
import org.terasology.world.generation.WorldFacet;
/**
* Additional functionality around the {@link FacetLayer} interface that is
* independent from any actual implementation.
*/
public final class FacetLayers {
private static final Logger logger = LoggerFactory.getLogger(FacetLayers.class);
private FacetLayers() {
// no instances
}
/**
* @param facets the facets that should be rendered
* @param environment the module environment that contains the facet layers
* @return an ordered list of facet layers
*/
public static List<FacetLayer> createLayersFor(Set<Class<? extends WorldFacet>> facets, ModuleEnvironment environment) {
Iterable<Class<? extends FacetLayer>> layers = environment.getSubtypesOf(FacetLayer.class);
List<FacetLayer> loadedLayers = new ArrayList<>();
for (Class<? extends WorldFacet> facet : facets) {
loadedLayers.addAll(createLayersFor(facet, layers));
}
// sort by annotated z-order
loadedLayers.sort((l1, l2) -> {
int o1 = l1.getClass().getAnnotation(Renders.class).order();
int o2 = l2.getClass().getAnnotation(Renders.class).order();
return Integer.compare(o1, o2);
});
return loadedLayers;
}
private static Collection<FacetLayer> createLayersFor(Class<? extends WorldFacet> facetClass,
Iterable<Class<? extends FacetLayer>> layers) {
Collection<FacetLayer> result = new ArrayList<>();
for (Class<? extends FacetLayer> layer : layers) {
Renders anno = layer.getAnnotation(Renders.class);
if (anno == null) {
if (!Modifier.isAbstract(layer.getModifiers())) {
// ignore abstract classes
logger.warn("FacetLayer class {} is not annotated with @Renders", layer);
}
} else {
Class<? extends WorldFacet> annotated = anno.value();
if (facetClass.equals(annotated)) {
try {
FacetLayer instance = layer.newInstance();
result.add(instance);
} catch (InstantiationException | IllegalAccessException e) {
logger.warn("Could not call default constructor for {}", layer);
}
}
}
}
if (result.isEmpty()) {
logger.warn("No layers found for facet {}", facetClass.getName());
}
return result;
}
}