///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.plugins.skillmatrix; import java.io.Serializable; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider; import org.apache.wicket.model.IModel; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.projectforge.registry.Registry; import org.projectforge.user.PFUserContext; import org.projectforge.user.PFUserDO; /** * @author Billy Duong (b.duong@micromata.de) * */ public class SkillTreeProvider implements ITreeProvider<SkillNode> { private static final long serialVersionUID = 7692282103462630402L; private transient SkillDao skillDao; private final SkillFilter skillFilter; private boolean showRootNode; public SkillTreeProvider(final SkillFilter skillFilter) { this.skillFilter = skillFilter; skillFilter.resetMatch(); } /** * Nothing to do. * @see org.apache.wicket.model.IDetachable#detach() */ @Override public void detach() { } /** * @see org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider#getRoots() */ @Override public Iterator<SkillNode> getRoots() { if(getSkillTree().getRootSkillNode() == null) { // Force a refresh to load the root skill node getSkillTree().refresh(); } return iterator(getSkillTree().getRootSkillNode().getChilds(), showRootNode); } /** * @see org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider#hasChildren(java.lang.Object) */ @Override public boolean hasChildren(final SkillNode node) { if (node.isRootNode() == true) { // Don't show children of root node again. return false; } return node.hasChilds(); } /** * @see org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider#getChildren(java.lang.Object) */ @Override public Iterator<SkillNode> getChildren(final SkillNode node) { if (node.isRootNode() == true) { // Don't show children of root node again. return new LinkedList<SkillNode>().iterator(); } return iterator(node.getChilds()); } /** * @see org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider#model(java.lang.Object) */ @Override public IModel<SkillNode> model(final SkillNode object) { return new SkillNodeModel(object); } private Iterator<SkillNode> iterator(final List<SkillNode> nodes) { return iterator(nodes, false); } private Iterator<SkillNode> iterator(final List<SkillNode> nodes, final boolean appendRootNode) { // ensureSkillTree(); final SortedSet<SkillNode> list = new TreeSet<SkillNode>(new Comparator<SkillNode>() { /** * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(final SkillNode skillNode1, final SkillNode skillNode2) { if (skillNode1.isRootNode() == true) { // Show root node at last position. return 1; } if (skillNode2.isRootNode() == true) { // Show root node at last position. return -1; } String title1 = skillNode1.getSkill().getTitle(); title1 = title1 != null ? title1.toLowerCase() : ""; String title2 = skillNode2.getSkill().getTitle(); title2 = title2 != null ? title2.toLowerCase() : ""; return title1.compareTo(title2); } }); if (appendRootNode == true) { if (skillFilter.match(getSkillTree().getRootSkillNode(), null, null) == true) { list.add(getSkillTree().getRootSkillNode()); } } if (nodes == null || nodes.isEmpty() == true) { return list.iterator(); } final PFUserDO user = PFUserContext.getUser(); for (final SkillNode node : nodes) { final boolean isMatch = skillFilter.match(node, getSkillDao(), user); final boolean hasAccess = getSkillDao().hasSelectAccess(user, node.getSkill(), false); if (isMatch == true && hasAccess == true) { list.add(node); } } return list.iterator(); } /** * @param showRootNode the showRootNode to set * @return this for chaining. */ public SkillTreeProvider setShowRootNode(final boolean showRootNode) { this.showRootNode = showRootNode; return this; } /** * @return the skillTree */ private SkillTree getSkillTree() { return getSkillDao().getSkillTree(); } /** * A {@link Model} which uses an id to load its {@link Foo}. * * If {@link Foo}s were {@link Serializable} you could just use a standard {@link Model}. * * @see #equals(Object) * @see #hashCode() */ private static class SkillNodeModel extends LoadableDetachableModel<SkillNode> { private static final long serialVersionUID = 1L; private final Integer id; private transient SkillTree skillTree; public SkillNodeModel(final SkillNode skillNode) { super(skillNode); id = skillNode.getId(); } @Override protected SkillNode load() { if (skillTree == null) { skillTree = Registry.instance().getDao(SkillDao.class).getSkillTree(); } return skillTree.getSkillNodeById(id); } /** * Important! Models must be identifyable by their contained object. */ @Override public boolean equals(final Object obj) { if (obj instanceof SkillNodeModel) { return ((SkillNodeModel) obj).id.equals(id); } return false; } /** * Important! Models must be identifyable by their contained object. */ @Override public int hashCode() { return id.hashCode(); } } /** * @return the skillDao */ public SkillDao getSkillDao() { if (skillDao == null) { skillDao = Registry.instance().getDao(SkillDao.class); } return skillDao; } /** * @param skillDao the skillDao to set */ public void setSkillDao(final SkillDao skillDao) { this.skillDao = skillDao; } }