blob: 7882961cf1aa62c159b12cd86446d635715ba2e3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc 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
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.internal.core.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.rcptt.core.model.IOpenable;
import org.eclipse.rcptt.core.model.IQ7Element;
import org.eclipse.rcptt.core.model.IQ7ElementVisitor;
import org.eclipse.rcptt.core.model.IQ7Model;
import org.eclipse.rcptt.core.model.IQ7Project;
import org.eclipse.rcptt.core.model.ModelException;
import org.eclipse.rcptt.core.model.Q7Status;
import org.eclipse.rcptt.core.model.Q7Status.Q7StatusCode;
public abstract class Q7Element extends PlatformObject implements IQ7Element {
public static final IQ7Element[] NO_ELEMENTS = new IQ7Element[0];
protected static final Object NO_INFO = new Object();
protected Q7Element parent;
protected Q7Element(Q7Element parent) throws IllegalArgumentException {
this.parent = parent;
}
public Object getElementInfo() throws ModelException {
return getElementInfo(null);
}
public Object getElementInfo(IProgressMonitor monitor)
throws ModelException {
ModelManager manager = ModelManager.getModelManager();
Object info = manager.getInfo(this);
if (info != null)
return info;
return openWhenClosed(createElementInfo(), monitor);
}
protected abstract Object createElementInfo();
protected boolean isInWorkingCopyMode() {
return false;
}
protected abstract void generateInfos(Object info,
Map<IQ7Element, Object> newElements, IProgressMonitor pm)
throws ModelException;
public IOpenable getOpenable() {
return this.getOpenableParent();
}
public IOpenable getOpenableParent() {
return (IOpenable) this.parent;
}
protected synchronized Object openWhenClosed(Object info,
IProgressMonitor monitor) throws ModelException {
ModelManager manager = ModelManager.getModelManager();
final boolean isWC = isInWorkingCopyMode();
try {
Map<IQ7Element, Object> newElements = new HashMap<IQ7Element, Object>();
generateInfos(info, newElements, monitor);
if (info == null) {
info = newElements.get(this);
}
if (info == null) {
throw newNotPresentException();
}
if (!isWC) {
// Do not put info if in working copy mode
manager.putInfos(this, newElements);
}
} finally {
}
Object info2 = isWC ? info : manager.getInfo(this);
return info2;
}
public void close() throws ModelException {
ModelManager.getModelManager().removeInfoAndChildren(this);
}
protected abstract void closing(Object info) throws ModelException;
public boolean exists() {
try {
getElementInfo();
return true;
} catch (ModelException e) {
if (e.getStatus() instanceof Q7Status)
if (((Q7Status) e.getStatus()).getStatusCode() == Q7StatusCode.NotPressent)
return false;
throw new RuntimeException(e);
}
}
public IQ7Element getAncestor(HandleType type) {
IQ7Element element = this;
while (element != null) {
if (element.getElementType().equals(type))
return element;
element = element.getParent();
}
return null;
}
public ModelException newNotPresentException() {
Q7Status status = new Q7Status(Q7Status.ERROR, "Element: " + getPath()
+ " doesn't exist");
status.setStatusCode(Q7StatusCode.NotPressent);
return new ModelException(status);
}
public IQ7Element getParent() {
return this.parent;
}
public IQ7Project getQ7Project() {
IQ7Element current = this;
do {
if (current instanceof IQ7Project)
return (IQ7Project) current;
} while ((current = current.getParent()) != null);
return null;
}
public IQ7Element[] getChildren() throws ModelException {
return getChildren(null);
}
public IQ7Element[] getChildren(IProgressMonitor monitor)
throws ModelException {
Object elementInfo = getElementInfo(monitor);
if (elementInfo instanceof Q7ElementInfo) {
return ((Q7ElementInfo) elementInfo).getChildren();
} else {
return NO_ELEMENTS;
}
}
/**
* @see IModelElement
*/
public IQ7Model getModel() {
IQ7Element current = this;
do {
if (current instanceof IQ7Model)
return (IQ7Model) current;
} while ((current = current.getParent()) != null);
return null;
}
protected List<IQ7Element> getChildrenOfType(HandleType type)
throws ModelException {
return getChildrenOfType(type, null);
}
protected List<IQ7Element> getChildrenOfType(HandleType type,
IProgressMonitor monitor) throws ModelException {
IQ7Element[] children = getChildren(monitor);
int size = children.length;
List<IQ7Element> list = new ArrayList<IQ7Element>(size);
for (int i = 0; i < size; ++i) {
IQ7Element elt = children[i];
if (elt.getElementType().equals(type)) {
list.add(elt);
}
}
return list;
}
public boolean hasChildren() throws ModelException {
Object elementInfo = ModelManager.getModelManager().getInfo(this);
if (elementInfo instanceof Q7ElementInfo) {
return ((Q7ElementInfo) elementInfo).getChildren().length > 0;
} else {
return true;
}
}
public void accept(IQ7ElementVisitor visitor) throws ModelException {
if (visitor.visit(this)) {
IQ7Element[] elements = getChildren();
for (int i = 0; i < elements.length; ++i) {
elements[i].accept(visitor);
}
visitor.endVisit(this);
}
}
public boolean equals(Object o) {
if (this == o)
return true;
// model parent is null
if (this.parent == null) {
return super.equals(o);
}
if (o == null) {
return false;
}
// assume instanceof check is done in subclass
final Q7Element other = (Q7Element) o;
return getName().equals(other.getName())
&& this.parent.equals(other.parent);
}
public int hashCode() {
if (this.parent == null)
return super.hashCode();
return Util.combineHashCodes(getName().hashCode(),
this.parent.hashCode());
}
public String toString() {
StringBuffer buffer = new StringBuffer();
toString(0, buffer);
return buffer.toString();
}
protected void toString(int tab, StringBuffer buffer) {
Object info = this.toStringInfo(tab, buffer);
if (tab == 0) {
this.toStringAncestors(buffer);
}
this.toStringChildren(tab, buffer, info);
}
public Object toStringInfo(int tab, StringBuffer buffer) {
Object info = ModelManager.getModelManager().peekAtInfo(this);
this.toStringInfo(tab, buffer, info, true/* show resolved info */);
return info;
}
protected void toStringInfo(int tab, StringBuffer buffer, Object info,
boolean showResolvedInfo) {
buffer.append(this.tabString(tab));
toStringName(buffer);
if (info == null) {
buffer.append(" (not open)"); //$NON-NLS-1$
}
}
protected void toStringAncestors(StringBuffer buffer) {
Q7Element parentElement = (Q7Element) this.getParent();
if (parentElement != null && parentElement.getParent() != null) {
buffer.append(" [in "); //$NON-NLS-1$
parentElement.toStringInfo(0, buffer, NO_INFO, false); // don't show
// resolved
// info
parentElement.toStringAncestors(buffer);
buffer.append("]"); //$NON-NLS-1$
}
}
protected void toStringName(StringBuffer buffer) {
buffer.append(getName());
}
protected String tabString(int tab) {
StringBuffer buffer = new StringBuffer();
for (int i = tab; i > 0; i--)
buffer.append(" "); //$NON-NLS-1$
return buffer.toString();
}
protected void toStringChildren(int tab, StringBuffer buffer, Object info) {
if (info == null || !(info instanceof Q7ElementInfo))
return;
IQ7Element[] children = ((Q7ElementInfo) info).getChildren();
for (int i = 0; i < children.length; i++) {
buffer.append("\n"); //$NON-NLS-1$
((Q7Element) children[i]).toString(tab + 1, buffer);
}
}
public String toDebugString() {
StringBuffer buffer = new StringBuffer();
this.toStringInfo(0, buffer, NO_INFO, true/* show resolved info */);
return buffer.toString();
}
public String toStringWithAncestors() {
return toStringWithAncestors(true/* show resolved info */);
}
public String toStringWithAncestors(boolean showResolvedInfo) {
StringBuffer buffer = new StringBuffer();
this.toStringInfo(0, buffer, NO_INFO, showResolvedInfo);
this.toStringAncestors(buffer);
return buffer.toString();
}
}