package org.orienteer.core.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton;
import org.apache.wicket.Component;
import org.apache.wicket.markup.IMarkupFragment;
import org.apache.wicket.markup.Markup;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.FormComponentPanel;
import org.apache.wicket.markup.html.form.ListMultipleChoice;
import org.apache.wicket.markup.html.form.NumberTextField;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.util.lang.Generics;
import org.orienteer.core.component.structuretable.StructureTable;
import org.orienteer.core.service.IMarkupProvider;
import org.wicketstuff.select2.Select2Choice;
import org.wicketstuff.select2.Select2MultiChoice;
import com.google.common.base.Function;
import com.google.common.collect.Ordering;
/**
* Implementation of {@link IMarkupProvider}
*/
@Singleton
public class MarkupProvider implements IMarkupProvider
{
private ConcurrentHashMap<Class<? extends Component>, IMarkupFragment> markupsCache = Generics.newConcurrentHashMap();
private ConcurrentHashMap<Class<? extends Component>, IMarkupFragment> markupsMap = Generics.newConcurrentHashMap();
public MarkupProvider()
{
registerMarkupContent(DropDownChoice.class, "<select wicket:id=\"component\" class=\"form-control\"></select>");
registerMarkupContent(ListMultipleChoice.class, "<select wicket:id=\"component\" class=\"form-control\"></select>");
registerMarkupContent(CheckBox.class, "<input type=\"checkbox\" wicket:id=\"component\"/>");
registerMarkupContent(TextField.class, "<input type=\"text\" wicket:id=\"component\" class=\"form-control\"/>");
registerMarkupContent(NumberTextField.class, "<input type=\"number\" wicket:id=\"component\" class=\"form-control\"/>");
registerMarkupContent(TextArea.class, "<textarea wicket:id=\"component\" class=\"form-control\"></textarea>");
registerMarkupContent(FormComponentPanel.class, "<div wicket:id=\"component\"></div>");
registerMarkupContent(Panel.class, "<div wicket:id=\"component\"></div>");
registerMarkupContent(AbstractLink.class, "<a wicket:id=\"component\"></a>");
registerMarkupContent(StructureTable.class, "<table wicket:id=\"component\"></table>");
registerMarkupContent(Select2MultiChoice.class, "<select wicket:id=\"component\" class=\"form-control\"/>");
registerMarkupContent(Select2Choice.class, "<select wicket:id=\"component\" class=\"form-control\"/>");
}
@Override
public IMarkupFragment provideMarkup(Component component) {
return provideMarkup(component.getClass());
}
@Override
public IMarkupFragment provideMarkup(
final Class<? extends Component> componentClass) {
IMarkupFragment ret = markupsCache.get(componentClass);
if(ret==null)
{
ret = markupsMap.get(componentClass);
if(ret==null)
{
List<Class<? extends Component>> candidates = new ArrayList<Class<? extends Component>>();
for (Map.Entry<Class<? extends Component>, IMarkupFragment> entry : markupsMap.entrySet())
{
if(entry.getKey().isAssignableFrom(componentClass)) candidates.add(entry.getKey());
}
if(candidates.size()==1)
{
ret = markupsMap.get(candidates.get(0));
}
else if(candidates.size()>1)
{
Class<? extends Component> minParents = Ordering.<Integer>natural().onResultOf(new Function<Class<? extends Component>, Integer>() {
@Override
public Integer apply(Class<? extends Component> input) {
int ret = 0;
Class<?> thisClass = componentClass;
while(thisClass!=null && !input.equals(thisClass))
{
thisClass = thisClass.getSuperclass();
ret++;
}
return ret;
}
}).min(candidates);
ret = markupsMap.get(minParents);
}
}
if(ret==null) ret = Markup.NO_MARKUP;
markupsCache.put(componentClass, ret);
}
return ret!=Markup.NO_MARKUP?ret:null;
}
@Override
public void registerMarkupContent(
Class<? extends Component> componentClass, String content) {
registerMarkupContent(componentClass, Markup.of(content));
}
@Override
public void registerMarkupContent(
Class<? extends Component> componentClass, IMarkupFragment markup) {
markupsMap.put(componentClass, markup);
markupsCache.clear();
}
}