| /******************************************************************************* |
| * Copyright (c) 2004, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.xml.core.tests.contentmodel; |
| |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMContent; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; |
| import org.eclipse.wst.xml.core.internal.contentmodel.util.CMVisitor; |
| |
| |
| public class CMUtility |
| { |
| /** |
| * return true if the child or any of its ancestor group nodes are repeatable |
| */ |
| public static boolean isNodeOrAncestorGroupRepeatable(CMContent content, CMNode child) |
| { |
| // since we can't walk up the CMNode tree (why you ask? ... its a long story) |
| // we walk down the tree to consider the child's parent node's |
| // |
| boolean result = isRepeatable(child); |
| if (!result) |
| { |
| CanRepeatVisitor visitor = new CanRepeatVisitor(content, child); |
| visitor.visitCMNode(content); |
| result = visitor.getResult(); |
| } |
| return result; |
| } |
| |
| /** |
| * return true if the child is repeatable |
| */ |
| public static boolean isNodeRepeatable(CMContent content, CMNode child) |
| { |
| // since we can't walk up the CMNode tree (why you ask? ... its a long story) |
| // we walk down the tree to consider the child's parent node's |
| // |
| boolean result = isRepeatable(child); |
| if (!result) |
| { |
| IsRepeatableVisitor visitor = new IsRepeatableVisitor(content, child); |
| visitor.visitCMNode(content); |
| result = visitor.getResult(); |
| } |
| return result; |
| } |
| |
| public static boolean isRepeatable(CMNode child) |
| { |
| boolean result = false; |
| if (child instanceof CMContent) |
| { |
| CMContent content = (CMContent)child; |
| result = content.getMaxOccur() > 1 || content.getMaxOccur() == -1; |
| } |
| return result; |
| } |
| |
| |
| protected static class CanRepeatVisitor extends CMVisitor |
| { |
| public boolean result; |
| protected boolean isWithinRepeatableGroup; |
| |
| protected CMNode root; |
| protected CMNode target; |
| |
| public CanRepeatVisitor(CMNode root, CMNode target) |
| { |
| this.root = root; |
| this.target = target; |
| } |
| |
| public void visitCMGroup(CMGroup group) |
| { |
| boolean oldIsWithinRepeatableGroup = isWithinRepeatableGroup; |
| |
| isWithinRepeatableGroup = isRepeatable(group); |
| |
| super.visitCMGroup(group); |
| |
| isWithinRepeatableGroup = oldIsWithinRepeatableGroup; |
| } |
| |
| public void visitCMElementDeclaration(CMElementDeclaration cmelement) |
| { |
| if (cmelement == target) |
| { |
| result = isWithinRepeatableGroup; |
| } |
| } |
| |
| public boolean getResult() |
| { |
| return result; |
| } |
| } |
| |
| |
| protected static class IsRepeatableVisitor extends CMVisitor |
| { |
| public boolean result = false; |
| protected CMGroup currentGroup; |
| |
| protected CMNode root; |
| protected CMNode target; |
| |
| public IsRepeatableVisitor(CMNode root, CMNode target) |
| { |
| this.root = root; |
| this.target = target; |
| } |
| |
| public void visitCMGroup(CMGroup group) |
| { |
| CMGroup previousGroup = currentGroup; |
| currentGroup = group; |
| super.visitCMGroup(group); |
| currentGroup = previousGroup; |
| } |
| |
| public void visitCMElementDeclaration(CMElementDeclaration cmelement) |
| { |
| if (cmelement == target) |
| { |
| if (currentGroup != null) |
| { |
| result = ((currentGroup.getOperator() == CMGroup.CHOICE) && |
| (isRepeatable(currentGroup))); |
| } |
| } |
| } |
| |
| public boolean getResult() |
| { |
| return result; |
| } |
| } |
| } |