/*******************************************************************************
* Copyright (c) 2015 Bruno Medeiros and other Contributors.
* 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:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.tooling.structure;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
import static melnorme.utilbox.core.CoreUtil.areEqual;
import static melnorme.utilbox.misc.StringUtil.prefixStr;
import melnorme.lang.tooling.ElementAttributes;
import melnorme.lang.tooling.ast.SourceRange;
import melnorme.utilbox.collections.ArrayList2;
import melnorme.utilbox.collections.Indexable;
import melnorme.utilbox.misc.HashcodeUtil;
/**
* Only {@link StructureElement} can extend this class!
*/
abstract class StructureElement_Default extends AbstractStructureContainer implements IStructureElement {
protected final String name;
protected final SourceRange sourceRange;
protected final SourceRange nameSourceRange2; // Can be null
protected final StructureElementKind elementKind;
protected final ElementAttributes elementAttributes;
protected final String type;
protected IStructureElementContainer parent;
public StructureElement_Default(
String name,
SourceRange nameSourceRange, SourceRange sourceRange,
StructureElementKind elementKind,
ElementAttributes elementAttributes,
String type, Indexable<StructureElement> children) {
super(children);
this.name = assertNotNull(name);
this.sourceRange = assertNotNull(sourceRange);
this.nameSourceRange2 = nameSourceRange;
this.elementKind = assertNotNull(elementKind);
this.elementAttributes = elementAttributes == null ? new ElementAttributes(null) : elementAttributes;
this.type = type;
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(!(obj instanceof StructureElement)) return false;
StructureElement other = (StructureElement) obj;
return
areEqual(name, other.name) &&
areEqual(nameSourceRange2, other.nameSourceRange2) &&
areEqual(sourceRange, other.sourceRange) &&
areEqual(elementKind, other.elementKind) &&
areEqual(elementAttributes, other.elementAttributes) &&
areEqual(type, other.type) &&
areEqual(children, other.children)
;
}
@Override
public int hashCode() {
// This should be enough to provide a good hash code
return HashcodeUtil.combinedHashCode(name, sourceRange, elementKind, elementAttributes, children.size());
}
protected String toStringNode() {
return "ELEM " + name + sourceRange + " " + elementKind + prefixStr(" : ", type) + " " + elementAttributes;
}
public StructureElement cloneSubTree() {
return new StructureElement(name, nameSourceRange2, sourceRange,
elementKind, elementAttributes, type, cloneSubTree(children));
}
public static ArrayList2<StructureElement> cloneSubTree(Indexable<StructureElement> elements) {
ArrayList2<StructureElement> clonedElements = new ArrayList2<>(elements.size());
for (StructureElement child : elements) {
clonedElements.add(child.cloneSubTree());
}
return clonedElements;
}
/* ----------------- ----------------- */
@Override
public String getName() {
return name;
}
@Override
public SourceRange getSourceRange() {
return sourceRange;
}
@Override
public SourceRange getNameSourceRange2() {
return nameSourceRange2;
}
@Override
public StructureElementKind getKind() {
return elementKind;
}
@Override
public ElementAttributes getAttributes() {
return elementAttributes;
}
@Override
public String getType() {
return type;
}
/* ----------------- ----------------- */
@Override
public IStructureElementContainer getParent() {
return parent;
}
@Override
public void setParent(IStructureElementContainer parent) {
assertNotNull(parent);
assertTrue(this.parent == null); // Can only set parent once
this.parent = parent;
}
// @Override
// public String getModuleName() {
// IStructureElementContainer parent = getParent();
// return parent == null ? null : parent.getModuleName();
// }
@Override
public ISourceFileStructure getContainingFileStructure() {
return getFileStructure(this);
}
public static ISourceFileStructure getFileStructure(IStructureElement element) {
IStructureElementContainer parent = element.getParent();
if(parent instanceof ISourceFileStructure) {
return (ISourceFileStructure) parent;
} else if (parent instanceof IStructureElement) {
return getFileStructure((IStructureElement) parent);
} else {
return null;
}
}
/* ----------------- ----------------- */
@Override
public String toString() {
return toString(true);
}
public String toString(boolean printChildren) {
if(printChildren) {
return new StructureElementPrinter().printElement((StructureElement) this);
} else {
return toStringNode();
}
}
}