/*
* Copyright 2012 Guido Steinacker
*
* 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 de.otto.jsonhome.generator;
import de.otto.jsonhome.model.JsonHome;
import de.otto.jsonhome.model.ResourceLink;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static de.otto.jsonhome.model.JsonHome.jsonHome;
import static de.otto.jsonhome.model.ResourceLinkHelper.mergeResources;
import static java.util.Collections.emptyList;
/**
* Abstract base class for JsonHome Generators.
*
* @author Guido Steinacker
* @since 15.09.12
*/
public abstract class JsonHomeGenerator {
private final Collection<Class<?>> controllers = new ArrayList<Class<?>>();
private ResourceLinkGenerator resourceLinkGenerator;
/**
* Injects the generator implementation used to generate ResourceLink instances.
*
* @param resourceLinkGenerator implementation of the ResourceLinkGenerator
*/
protected void setResourceLinkGenerator(final ResourceLinkGenerator resourceLinkGenerator) {
this.resourceLinkGenerator = resourceLinkGenerator;
}
/**
* Specifies a controller class, possibly providing one or more resource links.
*
* The injected generator is used to find the resource links supported by the controller.
*
* @param controller a class that is implementing a HTTP API.
* @return this
*/
public final JsonHomeGenerator with(final Class<?> controller) {
if (isCandidateForAnalysis(controller)) {
this.controllers.add(controller);
}
return this;
}
/**
* Specifies a number of controller classes, possibly providing one or more resource links.
*
* The injected generator is used to find the resource links supported by the controllers.
*
* @param controllers classes implementing a HTTP API.
* @return this
*/
public final JsonHomeGenerator with(final Collection<Class<?>> controllers) {
this.controllers.addAll(controllers.stream()
.filter(this::isCandidateForAnalysis)
.collect(Collectors.toList()));
return this;
}
/**
* Runs the generator and returns the JsonHome instance describing the HTTP API implemented by the controllers.
* @return JsonHome instance.
*/
public final JsonHome generate() {
List<? extends ResourceLink> resources = new ArrayList<>();
for (final Class<?> controllerClass : controllers) {
resources = mergeResources(resources, resourceLinksFor(controllerClass));
}
return jsonHome(resources);
}
/**
* Returns the ResourceLink instances of the controller.
* @param controller the controller
* @return list of ResourceLinks.
*/
protected final List<? extends ResourceLink> resourceLinksFor(final Class<?> controller) {
List<? extends ResourceLink> resourceLinks = emptyList();
for (final Method method : controller.getMethods()) {
resourceLinks = mergeResources(
resourceLinks,
resourceLinkGenerator.resourceLinkFor(method));
}
return resourceLinks;
}
/**
* Returns true if the controller is a candidate for further processing, false otherwise.
*
* @param controller the controller to check
* @return boolean
*/
protected abstract boolean isCandidateForAnalysis(final Class<?> controller);
}