/******************************************************************************* * 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 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.erlide.engine.internal.model.root; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.erlide.engine.ErlangEngine; import org.erlide.engine.internal.util.ModelConfig; import org.erlide.engine.model.ErlElementKind; import org.erlide.engine.model.ErlModelException; import org.erlide.engine.model.ErlModelStatus; import org.erlide.engine.model.ErlModelStatusConstants; import org.erlide.engine.model.IErlElement; import org.erlide.engine.model.IParent; import org.erlide.engine.model.root.IOpenable; import org.erlide.util.ErlLogger; /** * Abstract class for implementations of Erlang elements which are IOpenable. * * @see IErlElement * @see IOpenable */ public abstract class Openable extends ErlElement implements IOpenable { protected IResource findResult; protected Openable(final IParent parent, final String name) { super(parent, name); } /** * Builds this element's structure and properties in the given info object, * based on this element's current contents (reuse buffer contents if this * element has an open buffer, or resource contents if this element does not * have an open buffer). Children are placed in the given newElements table * (note, this element has already been placed in the newElements table). * Returns true if successful, or false if an error is encountered while * determining the structure of this element. * * @param dirtyRegion */ public abstract boolean buildStructure(IProgressMonitor pm) throws ErlModelException; @Override public boolean exists() { final IResource resource = getResource(); if (resource != null) { return resource.exists(); } return true; } @Override public synchronized void open(final IProgressMonitor monitor) throws ErlModelException { // open the parent if necessary openParent(monitor); if (monitor != null && monitor.isCanceled()) { return; } // build the structure of the openable (this will open the buffer if // needed) if (!isStructureKnown()) { if (ModelConfig.verbose) { ErlLogger.debug("open " + isStructureKnown() + " > " + this); } final boolean knownStructure = buildStructure(monitor); setStructureKnown(knownStructure); } } class ErlangResourceVisitor implements IResourceVisitor { private final String aname; public ErlangResourceVisitor(final String name) { aname = name; } @Override public boolean visit(final IResource resource) { if (resource.getType() == IResource.FILE && resource.getName().equals(aname)) { findResult = resource; return false; } // return true to continue visiting children. return true; } } /** * Returns true if this element may have an associated source buffer, * otherwise false. Subclasses must override as required. */ protected boolean hasBuffer() { return false; } @Override public boolean hasUnsavedChanges() throws ErlModelException { if (isReadOnly() || !isOpen()) { return false; } // final IBuffer buf = this.getBuffer(); // if (buf != null && buf.hasUnsavedChanges()) { // return true; // } // for packages and projects must check open buffers // to see if they have an child with unsaved changes final ErlElementKind elementType = getKind(); if (elementType == ErlElementKind.PROJECT || elementType == ErlElementKind.MODEL) { // final Enumeration openBuffers = // getBufferManager().getOpenBuffers(); // while (openBuffers.hasMoreElements()) { // final IBuffer buffer = (IBuffer) openBuffers.nextElement(); // if (buffer.hasUnsavedChanges()) { // final IErlElement owner = (IErlElement) buffer.getOwner(); // if (isAncestorOf(owner)) { // return true; // } // } // } } return false; } @Override public boolean isConsistent() { return true; } @Override public boolean isOpen() { return true; } protected boolean isSourceElement() { return false; } @Override public void makeConsistent(final IProgressMonitor monitor) throws ErlModelException { if (isConsistent()) { return; } } protected void openParent(final IProgressMonitor pm) throws ErlModelException { final Openable openableParent = (Openable) getOpenableParent(); if (openableParent != null && !openableParent.isOpen()) { openableParent.open(pm); } } protected boolean parentExists() { final IParent parent = getParent(); if (parent == null) { return true; } if (parent instanceof IErlElement) { final IErlElement element = (IErlElement) parent; return element.exists(); } return false; } protected boolean resourceExists() { final IWorkspace workspace = ResourcesPlugin.getWorkspace(); if (workspace == null) { return false; } return ErlangEngine.getInstance().getModelUtilService().getTarget( workspace.getRoot(), getResource().getFullPath().makeRelative(), true) != null; } @Override public void save(final IProgressMonitor pm, final boolean force) throws ErlModelException { if (isReadOnly()) { throw new ErlModelException( new ErlModelStatus(ErlModelStatusConstants.READ_ONLY, this)); } // final IBuffer buf = getBuffer(); // if (buf != null) { // some Openables (like a ErlProject) don't have a // // buffer // buf.save(pm, force); // makeConsistent(pm); // update the element info of this // // element // } } @Override public void close() throws ErlModelException { for (final IErlElement child : getChildren()) { if (child instanceof IOpenable) { final IOpenable openable = (IOpenable) child; if (openable.isOpen()) { openable.close(); } } } internalGetChildren().clear(); setStructureKnown(false); } }