/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.internal.core; import org.rubypeople.rdt.core.IRubyElement; /** * Holds cached structure and properties for a Ruby element. Subclassed to carry * properties for specific kinds of elements. */ /* package */class RubyElementInfo { /** * Collection of handles of immediate children of this object. This is an * empty array if this element has no children. */ protected IRubyElement[] children; /** * Is the structure of this element known * * @see IRubyElement#isStructureKnown() */ protected boolean isStructureKnown = false; /** * Shared empty collection used for efficiency. */ static Object[] NO_NON_RUBY_RESOURCES = new Object[] {}; protected RubyElementInfo() { this.children = RubyElement.NO_ELEMENTS; } public void addChild(IRubyElement child) { if (this.children == RubyElement.NO_ELEMENTS) { setChildren(new IRubyElement[] { child}); } else { if (!includesChild(child)) { setChildren(growAndAddToArray(this.children, child)); } } } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new Error(); } } public IRubyElement[] getChildren() { return this.children; } /** * Adds the new element to a new array that contains all of the elements of * the old array. Returns the new array. */ protected IRubyElement[] growAndAddToArray(IRubyElement[] array, IRubyElement addition) { IRubyElement[] old = array; array = new IRubyElement[old.length + 1]; System.arraycopy(old, 0, array, 0, old.length); array[old.length] = addition; return array; } /** * Returns <code>true</code> if this child is in my children collection */ protected boolean includesChild(IRubyElement child) { for (int i = 0; i < this.children.length; i++) { if (this.children[i].equals(child)) { return true; } } return false; } /** * @see IRubyElement#isStructureKnown() */ public boolean isStructureKnown() { return this.isStructureKnown; } /** * Returns an array with all the same elements as the specified array except * for the element to remove. Assumes that the deletion is contained in the * array. */ protected IRubyElement[] removeAndShrinkArray(IRubyElement[] array, IRubyElement deletion) { IRubyElement[] old = array; array = new IRubyElement[old.length - 1]; int j = 0; for (int i = 0; i < old.length; i++) { if (!old[i].equals(deletion)) { array[j] = old[i]; } else { System.arraycopy(old, i + 1, array, j, old.length - (i + 1)); return array; } j++; } return array; } public void removeChild(IRubyElement child) { if (includesChild(child)) { setChildren(removeAndShrinkArray(this.children, child)); } } public void setChildren(IRubyElement[] children) { this.children = children; } /** * Sets whether the structure of this element known * * @see IRubyElement#isStructureKnown() */ public void setIsStructureKnown(boolean newIsStructureKnown) { this.isStructureKnown = newIsStructureKnown; } }