/* * * * Copyright (c) 2016. David Sowerby * * * * 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 uk.q3c.krail.core.navigate.sitemap; import com.google.inject.AbstractModule; import com.google.inject.multibindings.MapBinder; import org.reflections.Reflections; import uk.q3c.krail.core.guice.DefaultBindingManager; import uk.q3c.krail.core.i18n.I18NKey; import uk.q3c.krail.core.view.KrailView; import java.lang.ProcessBuilder.Redirect; /** * If you want to create Sitemap entries for your own code using {@link View} annotations on your {@link KrailView} * classes, you can either subclass this module and provide the entries in the {@link #define} method, or just simply * use this as an example and create your own. The module then needs to be added to your subclass of * {@link DefaultBindingManager}. By convention, modules relating to the Sitemap are added in the * addSitemapModules() * method. * <p/> * You can add any number of modules this way, but any duplicated map keys (the URI segments) will cause the map * injection to fail. There is an option to change this behaviour in MapBinder#permitDuplicates() * <p/> * You can use multiple subclasses of this, Guice will merge all of the bindings into a single MapBinder<Class, View> * for use by the {@link AnnotationSitemapLoader} * * @author David Sowerby */ public abstract class AnnotationSitemapModule extends AbstractModule { private MapBinder<String, AnnotationSitemapEntry> mapBinder; @Override protected void configure() { mapBinder = MapBinder.newMapBinder(binder(), String.class, AnnotationSitemapEntry.class); define(); } /** * Override this to provide the root or roots you want to scan for classes with a {@link View} or * {@link RedirectFrom} annotation, each with a 'sample' key from the I18NKey class you are using for the labels in * the Views you are scanning.<br> * A sample is needed because Annotations cannot contain enum constants as parameters, so a label key name is used * - * that name then needs to be looked from an I18NKey class, which is taken from the sample you provide here. It * does * not matter what the sample is as long as it is a member of the I18NKey class you want to use. This is only used * for the {@link View} annotation, the {@link Redirect} annotation does not use the key * <p/> * Krail uses the {@link Reflections} utility to scan for the annotations. When you add a package root in your * module, * you are actually using the Reflections facility to scan from a package prefix. Note that this is a literal * prefix * from the full class name. This means that a prefix of 'com.example.view' would scan both of these: * <p/> * <p/> * com.example.view<br> * com.example.views<br> * <br> * In essence, it is as though the prefix has a wildcard, in this example: com.example.view* * <p/> * The full entry would be something like this: * <p/> * addEntry("uk.q3c.krail.core.view",LabelKey.Home); * <p/> * which would scan all packages beginning with 'uk.q3c.krail.core.view', and the LabelKey class would be used to * lookup the label key names from the View annotations * <p/> */ protected abstract void define(); protected void addEntry(String reflectionRoot, I18NKey labelSample) { AnnotationSitemapEntry entry = new AnnotationSitemapEntry(); entry.setLabelSample(labelSample); mapBinder.addBinding(reflectionRoot) .toInstance(entry); } }