/*******************************************************************************
* Copyright (c) 2000, 2015 QNX Software Systems 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:
* QNX Software Systems - Initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IArchive;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.ICContainer;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ISourceRoot;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.util.MementoTokenizer;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
public class CContainer extends Openable implements ICContainer {
CModelManager factory = CModelManager.getDefault();
public CContainer(ICElement parent, IResource res) {
this(parent, res, ICElement.C_CCONTAINER);
}
public CContainer(ICElement parent, IResource res, int type) {
super(parent, res, type);
}
@Override
public IBinary[] getBinaries() throws CModelException {
List<?> list = getChildrenOfType(C_BINARY);
IBinary[] array = new IBinary[list.size()];
list.toArray(array);
return array;
}
@Override
public IBinary getBinary(String name) {
IFile file = getContainer().getFile(new Path(name));
return getBinary(file);
}
public IBinary getBinary(IFile file) {
IBinaryFile bin = factory.createBinaryFile(file);
if (bin instanceof IBinaryObject) {
return new Binary(this, file, (IBinaryObject) bin);
}
return new Binary(this, file, null);
}
@Override
public IArchive[] getArchives() throws CModelException {
List<?> list = getChildrenOfType(C_ARCHIVE);
IArchive[] array = new IArchive[list.size()];
list.toArray(array);
return array;
}
@Override
public IArchive getArchive(String name) {
IFile file = getContainer().getFile(new Path(name));
return getArchive(file);
}
public IArchive getArchive(IFile file) {
IBinaryFile ar = factory.createBinaryFile(file);
if (ar != null && ar.getType() == IBinaryFile.ARCHIVE) {
return new Archive(this, file, (IBinaryArchive) ar);
}
return new Archive(this, file, null);
}
@Override
public ITranslationUnit[] getTranslationUnits() throws CModelException {
List<?> list = getChildrenOfType(C_UNIT);
ITranslationUnit[] array = new ITranslationUnit[list.size()];
list.toArray(array);
return array;
}
@Override
public ITranslationUnit getTranslationUnit(String name) {
IFile file = getContainer().getFile(new Path(name));
return getTranslationUnit(file);
}
public ITranslationUnit getTranslationUnit(IFile file) {
String id = CoreModel.getRegistedContentTypeId(file.getProject(), file.getName());
return new TranslationUnit(this, file, id);
}
@Override
public ICContainer[] getCContainers() throws CModelException {
List<?> list = getChildrenOfType(C_CCONTAINER);
ICContainer[] array = new ICContainer[list.size()];
list.toArray(array);
return array;
}
@Override
public ICContainer getCContainer(String name) {
IFolder folder = getContainer().getFolder(new Path(name));
return getCContainer(folder);
}
public ICContainer getCContainer(IFolder folder) {
return new CContainer(this, folder);
}
public IContainer getContainer() {
return getResource();
}
@Override
protected CElementInfo createElementInfo() {
return new CContainerInfo(this);
}
// CHECKPOINT: folders will return the hash code of their path
@Override
public int hashCode() {
return getPath().hashCode();
}
@Override
protected boolean buildStructure(OpenableInfo info, IProgressMonitor pm, Map<ICElement, CElementInfo> newElements, IResource underlyingResource)
throws CModelException {
boolean validInfo = false;
try {
IResource res = getResource();
if (res != null && res.isAccessible()) {
validInfo = computeChildren(info, res);
} else {
throw newNotPresentException();
}
} finally {
if (!validInfo) {
CModelManager.getDefault().removeInfo(this);
}
}
return validInfo;
}
@Override
public Object[] getNonCResources() throws CModelException {
return ((CContainerInfo) getElementInfo()).getNonCResources(getResource());
}
protected boolean computeChildren(OpenableInfo info, IResource res) throws CModelException {
ArrayList<ICElement> vChildren = new ArrayList<>();
try {
IResource[] resources = null;
if (res instanceof IContainer) {
IContainer container = (IContainer) res;
resources = container.members(false);
}
if (resources != null) {
ICProject cproject = getCProject();
for (IResource resource : resources) {
ICElement celement = computeChild(resource, cproject);
if (celement != null) {
vChildren.add(celement);
}
}
}
} catch (CoreException e) {
throw new CModelException(e);
}
info.setChildren(vChildren);
if (info instanceof CContainerInfo) {
((CContainerInfo) info).setNonCResources(null);
}
return true;
}
protected ICElement computeChild(IResource res, ICProject cproject) throws CModelException {
ICElement celement = null;
ISourceRoot sroot = getSourceRoot();
switch (res.getType()) {
case IResource.FILE: {
IFile file = (IFile) res;
boolean checkBinary = true;
if (sroot != null && sroot.isOnSourceEntry(res)) {
// Check for Valid C Element only.
String id = CoreModel.getRegistedContentTypeId(file.getProject(), file.getName());
if (id != null) {
celement = new TranslationUnit(this, file, id);
checkBinary = false;
} else {
checkBinary = true;
}
}
if (checkBinary && cproject.isOnOutputEntry(file)) {
IBinaryParser.IBinaryFile bin = factory.createBinaryFile(file);
if (bin != null) {
if (bin.getType() == IBinaryFile.ARCHIVE) {
celement = new Archive(this, file, (IBinaryArchive) bin);
ArchiveContainer vlib = (ArchiveContainer) cproject.getArchiveContainer();
vlib.addChild(celement);
} else {
final Binary binElement= new Binary(this, file, (IBinaryObject) bin);
celement= binElement;
if (binElement.showInBinaryContainer()) {
BinaryContainer vbin = (BinaryContainer) cproject.getBinaryContainer();
vbin.addChild(celement);
}
}
}
}
break;
}
case IResource.FOLDER:
if (sroot != null && sroot.isOnSourceEntry(res) || (sroot == null && cproject.isOnOutputEntry(res))) {
celement = new CContainer(this, res);
}
break;
}
return celement;
}
@Override
public ICElement getHandleFromMemento(String token, MementoTokenizer memento) {
switch (token.charAt(0)) {
case CEM_SOURCEFOLDER:
String name;
if (memento.hasMoreTokens()) {
name = memento.nextToken();
char firstChar = name.charAt(0);
if (firstChar == CEM_TRANSLATIONUNIT) {
token = name;
name = ""; //$NON-NLS-1$
} else {
token = null;
}
} else {
name = ""; //$NON-NLS-1$
token = null;
}
CElement folder = (CElement) getCContainer(name);
if (folder != null) {
if (token == null) {
return folder.getHandleFromMemento(memento);
} else {
return folder.getHandleFromMemento(token, memento);
}
}
break;
case CEM_TRANSLATIONUNIT:
if (!memento.hasMoreTokens())
return this;
String tuName = memento.nextToken();
CElement tu = (CElement) getTranslationUnit(tuName);
if (tu != null) {
return tu.getHandleFromMemento(memento);
}
}
return null;
}
@Override
protected char getHandleMementoDelimiter() {
return CElement.CEM_SOURCEFOLDER;
}
@Override
public IContainer getResource() {
return (IContainer) super.getResource();
}
}