/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.common.instance.helper; import javax.xml.namespace.QName; import eu.esdihumboldt.hale.common.instance.model.Group; import eu.esdihumboldt.hale.common.instance.model.Instance; import eu.esdihumboldt.hale.common.schema.model.DefinitionGroup; /** * Instance traverser that traverses the model depth first. * * @author Simon Templer */ public class DepthFirstInstanceTraverser implements InstanceTraverser { private final boolean cancelChildTraversalOnly; /** * Creates a depth first instance traverser. */ public DepthFirstInstanceTraverser() { this(false); } /** * Creates a depth first instance traverser. * * @param cancelChildTraversalOnly if when the callback cancels the * traversal, only the traversal of the children should be * canceled (meaning traversal is continued but not down from the * current object) */ public DepthFirstInstanceTraverser(boolean cancelChildTraversalOnly) { super(); this.cancelChildTraversalOnly = cancelChildTraversalOnly; } /** * @see InstanceTraverser#traverse(Instance, InstanceTraversalCallback) */ @Override public boolean traverse(Instance instance, InstanceTraversalCallback callback) { return traverse(instance, callback, null, null); } private boolean traverse(Instance instance, InstanceTraversalCallback callback, QName name, DefinitionGroup parent) { if (callback.visit(instance, name, parent)) { // traverse value (if applicable) Object value = instance.getValue(); if (value != null) { if (!traverse(value, callback, name, parent)) { if (!cancelChildTraversalOnly) { // cancel whole traversal return false; } else { // only skip traversing children return true; } } } // traverse children return traverseChildren(instance, callback); } else if (!cancelChildTraversalOnly) { // cancel whole traversal return false; } else { // only skipped traversing the current instance return true; } } /** * @see InstanceTraverser#traverse(Group, InstanceTraversalCallback) */ @Override public boolean traverse(Group group, InstanceTraversalCallback callback) { return traverse(group, callback, null, null); } private boolean traverse(Group group, InstanceTraversalCallback callback, QName name, DefinitionGroup parent) { if (callback.visit(group, name, parent)) { // traverse children return traverseChildren(group, callback); } else if (!cancelChildTraversalOnly) { // cancel whole traversal return false; } else { // only skipped traversing the current group return true; } } /** * Traverse the children of a given group. * * @param group the group * @param callback the traversal callback * @return if traversal shall be continued */ protected boolean traverseChildren(Group group, InstanceTraversalCallback callback) { for (QName name : group.getPropertyNames()) { Object[] values = group.getProperty(name); if (values != null) { for (Object value : values) { if (!traverse(value, callback, name, group.getDefinition())) { if (!cancelChildTraversalOnly) { return false; } } } } } return true; } /** * @see InstanceTraverser#traverse(Object, InstanceTraversalCallback) */ @Override public boolean traverse(Object value, InstanceTraversalCallback callback) { return traverse(value, callback, null, null); } private boolean traverse(Object value, InstanceTraversalCallback callback, QName name, DefinitionGroup parent) { if (value instanceof Instance) { return traverse((Instance) value, callback, name, parent); } if (value instanceof Group) { return traverse((Group) value, callback, name, parent); } return callback.visit(value, name, parent); } }