package org.bundlemaker.core.project.internal; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.bundlemaker.core.common.ResourceType; import org.bundlemaker.core.common.utils.FileUtils; import org.bundlemaker.core.internal.resource.Resource; import org.bundlemaker.core.internal.resource.ResourceStandin; import org.bundlemaker.core.project.AnalyzeMode; import org.bundlemaker.core.project.IProjectContentEntry; import org.bundlemaker.core.project.IProjectContentProvider; import org.bundlemaker.core.project.IProjectContentResource; import org.bundlemaker.core.project.IProjectDescription; import org.bundlemaker.core.project.VariablePath; import org.bundlemaker.core.project.spi.AbstractProjectContentProvider; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; /** * <p> * Abstract base class for all {@link IProjectContentEntry} implementations. * </p> * * @author Gerd Wütherich (gerd@gerd-wuetherich.de) */ public class ProjectContentEntry implements IProjectContentEntry { /** the empty resource standin set */ private static final Set<IResourceStandinNEW> EMPTY_RESOURCE_STANDIN_SET = Collections .unmodifiableSet(new HashSet<IResourceStandinNEW>()); /** - */ private static final Set<VariablePath> EMPTY_ROOTPATH_SET = Collections .unmodifiableSet(new HashSet<VariablePath>()); /** the internal identifier of this content entry */ private String _id; /** the name of this entry */ private String _name; /** the version of this entry */ private String _version; /** the analyze mode of this entry */ private AnalyzeMode _analyze; /** the binary pathes */ protected Set<VariablePath> _binaryPaths; /** the source pathes */ private Set<VariablePath> _sourcePaths; /** indicates that the content has been initialized */ private boolean _isInitialized; /** the set of binary resource standins */ private Map<String, IResourceStandinNEW> _binaryResourceStandins; /** the set of source resource standins */ private Map<String, IResourceStandinNEW> _sourceResourceStandins; /** the project description */ private IInternalProjectDescription _projectDescription; /** the bundle maker project content provider */ private IProjectContentProvider _provider; /** the user attributes */ private Map<String, Object> _userAttributes; /** - */ private IResourceFactory _resourceFactory; /** * indicates wether changes to this instance should be notified. * * <p> * This flag may be set to 'false' to prevent change notification while initializing this Content instance. * */ private boolean _notifyChanges = true; /** * <p> * Creates a new instance of type {@link ProjectContentEntry}. * </p> */ public ProjectContentEntry(IProjectContentProvider provider) { this(provider, false); } /** * <p> * Creates a new instance of type {@link ProjectContentEntry}. * </p> */ public ProjectContentEntry(IProjectContentProvider provider, boolean notifyChanges) { Assert.isNotNull(provider); // set notify flag _notifyChanges = notifyChanges; // set the provider _provider = provider; // setAnalyzeMode(AnalyzeMode.BINARIES_ONLY); // _binaryPaths = new HashSet<VariablePath>(); } /** * {@inheritDoc} */ @Override public Map<String, Object> getUserAttributes() { // if (_userAttributes == null) { _userAttributes = new HashMap<String, Object>(); } // return _userAttributes; } /** * {@inheritDoc} */ @Override public IProjectContentProvider getProvider() { return _provider; } /** * {@inheritDoc} */ @Override public String getId() { return _id; } /** * {@inheritDoc} */ @Override public String getName() { return _name; } /** * {@inheritDoc} */ @Override public String getVersion() { return _version; } /** * {@inheritDoc} */ public boolean isAnalyze() { return _analyze.isAnalyze(); } /** * {@inheritDoc} */ @Override public AnalyzeMode getAnalyzeMode() { return _analyze; } /** * {@inheritDoc} */ @Override public final Collection<? extends IProjectContentResource> getBinaryResources() { return Collections.unmodifiableCollection(getBinaryResourceStandins()); } /** * {@inheritDoc} */ @Override public final Collection<? extends IProjectContentResource> getSourceResources() { assertIsInitialized(); return Collections.unmodifiableCollection(getSourceResourceStandins()); } /** * {@inheritDoc} */ @Override public Collection<? extends IProjectContentResource> getResources(ResourceType type) { assertIsInitialized(); switch (type) { case BINARY: { return getBinaryResources(); } case SOURCE: { return getSourceResources(); } default: { return null; } } } /** * {@inheritDoc} */ @Override public IProjectContentResource getResource(String path, ResourceType type) { assertIsInitialized(); switch (type) { case BINARY: { return binaryResourceStandins().get(path); } case SOURCE: { return sourceResourceStandins().get(path); } default: { return null; } } } /** * <p> * Returns <code>true</code> if the content has been initialized yet. * </p> * * @return <code>true</code> if the content has been initialized yet. */ protected boolean isInitialized() { return _isInitialized; } /** * <p> * Sets the id of this content entry. * </p> * * @param id * the id of this content entry. */ public void setId(String id) { Assert.isNotNull(id); _id = id; } /** * <p> * Sets the name of this content entry. * </p> * * @param name * the name of this content entry. */ public void setName(String name) { Assert.isNotNull(name); _name = name; fireProjectDescriptionChangeEvent(); } /** * <p> * Sets the version of this content entry. * </p> * * @param name * the version of this content entry. */ public void setVersion(String version) { Assert.isNotNull(version); _version = version; fireProjectDescriptionChangeEvent(); } /** * <p> * Sets the {@link AnalyzeMode} of this content entry. * </p> * * @param name * the {@link AnalyzeMode} of this content entry. */ public void setAnalyzeMode(AnalyzeMode analyzeMode) { Assert.isNotNull(analyzeMode, "Paramter 'analyzeMode' must not be null"); // _analyze = analyzeMode; fireProjectDescriptionChangeEvent(); } /** * <p> * Returns the set of all contained binary {@link IResourceStandinNEW}. * </p> * * @return the set of all contained binary {@link IResourceStandinNEW}. */ public final Collection<IResourceStandinNEW> getBinaryResourceStandins() { assertIsInitialized(); return _binaryResourceStandins != null ? _binaryResourceStandins.values() : EMPTY_RESOURCE_STANDIN_SET; } /** * <p> * Returns the set of all contained source {@link IResourceStandinNEW}. * </p> * * @return the set of all contained source {@link IResourceStandinNEW}. */ public final Collection<IResourceStandinNEW> getSourceResourceStandins() { assertIsInitialized(); return _sourceResourceStandins != null ? _sourceResourceStandins.values() : EMPTY_RESOURCE_STANDIN_SET; } /** * This method can be used to switch on/off the notification of changes that are made on this Content instance. * * @param notifyChanges */ public void setNotifyChanges(boolean notifyChanges) { _notifyChanges = notifyChanges; } /** * <p> * Initializes this content entry. * </p> * * @param projectDescription * the project description. * @throws CoreException */ public final void initialize(IProjectDescription projectDescription) throws CoreException { // Assert.isNotNull(projectDescription); Assert.isTrue(projectDescription instanceof IInternalProjectDescription, String.format("Project description must be instance of %s.", IInternalProjectDescription.class.getName())); // return if content already is initialized if (isInitialized()) { return; } // the project description _projectDescription = (IInternalProjectDescription) projectDescription; // onInitialize(projectDescription); // set initialized _isInitialized = true; } /** * <p> * </p> * * @param contentId * @param root * @param path * @param type * @return */ protected IResourceStandinNEW createNewResourceStandin(String contentId, String root, String path, ResourceType type, boolean analyzeReferences) { Assert.isNotNull(contentId); Assert.isNotNull(root); Assert.isNotNull(path); Assert.isNotNull(type); // IResourceStandinNEW resourceStandin = getResourceFactory().createResourceStandin(contentId, root, path); resourceStandin.setAnalyzeReferences(analyzeReferences); // add the resource switch (type) { case BINARY: { _projectDescription.addBinaryResource(resourceStandin); binaryResourceStandins().put(path, resourceStandin); break; } case SOURCE: { _projectDescription.addSourceResource(resourceStandin); sourceResourceStandins().put(path, resourceStandin); break; } default: break; } // return resourceStandin; } protected void fireProjectDescriptionChangeEvent() { if (_notifyChanges && _provider instanceof AbstractProjectContentProvider) { ((AbstractProjectContentProvider) _provider).fireProjectDescriptionChangedEvent(); } } /** * <p> * </p> * * @return */ private Map<String, IResourceStandinNEW> binaryResourceStandins() { // if (_binaryResourceStandins == null) { _binaryResourceStandins = new HashMap<String, IResourceStandinNEW>(); } // return _binaryResourceStandins; } /** * <p> * </p> * * @return */ private Map<String, IResourceStandinNEW> sourceResourceStandins() { // if (_sourceResourceStandins == null) { _sourceResourceStandins = new HashMap<String, IResourceStandinNEW>(); } // return _sourceResourceStandins; } /** * {@inheritDoc} */ public Set<VariablePath> getBinaryRootPaths() { return Collections.unmodifiableSet(_binaryPaths); } /** * {@inheritDoc} */ public Set<VariablePath> getSourceRootPaths() { return _sourcePaths != null ? _sourcePaths : EMPTY_ROOTPATH_SET; } /** * {@inheritDoc} */ protected void onInitialize(IProjectDescription projectDescription) throws CoreException { // add the binary resources for (VariablePath root : _binaryPaths) { for (String filePath : FileUtils.getAllChildren(root.getAsFile())) { // createNewProjectContentResource(root.getResolvedPath().toString(), filePath, ResourceType.BINARY); } } // add the source resources if (getAnalyzeMode().equals(AnalyzeMode.BINARIES_AND_SOURCES)) { if (_sourcePaths != null) { for (VariablePath root : _sourcePaths) { for (String filePath : FileUtils.getAllChildren(root.getAsFile())) { // createNewProjectContentResource(root.getResolvedPath().toString(), filePath, ResourceType.SOURCE); } } } } } /** * <p> * </p> * * @param rootPath * @param type */ public void addRootPath(VariablePath rootPath, ResourceType type) { Assert.isNotNull(rootPath); Assert.isNotNull(type); // if (type.equals(ResourceType.BINARY)) { _binaryPaths.add(rootPath); } else if (type.equals(ResourceType.SOURCE)) { sourcePaths().add(rootPath); } fireProjectDescriptionChangeEvent(); } /** * <p> * </p> * * @param rootPath * @param type */ public void removeRootPath(VariablePath rootPath, ResourceType type) { Assert.isNotNull(rootPath); Assert.isNotNull(type); // if (type.equals(ResourceType.BINARY)) { _binaryPaths.remove(rootPath); } else if (type.equals(ResourceType.SOURCE)) { _sourcePaths.remove(rootPath); } fireProjectDescriptionChangeEvent(); } /** * <p> * </p> * * @param binaryRootPaths */ public void setBinaryPaths(String[] binaryRootPaths) { Assert.isNotNull(binaryRootPaths); _binaryPaths.clear(); for (String path : binaryRootPaths) { _binaryPaths.add(new VariablePath(path)); } fireProjectDescriptionChangeEvent(); } /** * <p> * </p> * * @param sourceRootPaths */ public void setSourcePaths(String[] sourceRootPaths) { Assert.isNotNull(sourceRootPaths); sourcePaths().clear(); for (String path : sourceRootPaths) { sourcePaths().add(new VariablePath(path)); } fireProjectDescriptionChangeEvent(); } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder builder = new StringBuilder(getClass().getSimpleName()); builder.append(" [_binaryPaths="); builder.append(_binaryPaths); builder.append(", _sourcePaths="); builder.append(_sourcePaths); builder.append(", getId()="); builder.append(getId()); builder.append(", getName()="); builder.append(getName()); builder.append(", getVersion()="); builder.append(getVersion()); builder.append(", isAnalyze()="); builder.append(isAnalyze()); builder.append("]"); return builder.toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((_analyze == null) ? 0 : _analyze.hashCode()); result = prime * result + ((_binaryPaths == null) ? 0 : _binaryPaths.hashCode()); result = prime * result + ((_id == null) ? 0 : _id.hashCode()); result = prime * result + ((_name == null) ? 0 : _name.hashCode()); result = prime * result + ((_sourcePaths == null) ? 0 : _sourcePaths.hashCode()); result = prime * result + ((_userAttributes == null) ? 0 : _userAttributes.hashCode()); result = prime * result + ((_version == null) ? 0 : _version.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ProjectContentEntry other = (ProjectContentEntry) obj; if (_analyze != other._analyze) return false; if (_binaryPaths == null) { if (other._binaryPaths != null) return false; } else if (!_binaryPaths.equals(other._binaryPaths)) return false; if (_id == null) { if (other._id != null) return false; } else if (!_id.equals(other._id)) return false; if (_name == null) { if (other._name != null) return false; } else if (!_name.equals(other._name)) return false; if (_sourcePaths == null) { if (other._sourcePaths != null) return false; } else if (!_sourcePaths.equals(other._sourcePaths)) return false; if (_userAttributes == null) { if (other._userAttributes != null) return false; } else if (!_userAttributes.equals(other._userAttributes)) return false; if (_version == null) { if (other._version != null) return false; } else if (!_version.equals(other._version)) return false; return true; } public IProjectContentResource createNewProjectContentResource(String root, String path, ResourceType type) { // Map<String, IResourceStandinNEW> standins = type.equals(ResourceType.BINARY) ? binaryResourceStandins() : sourceResourceStandins(); // if (!standins.containsKey(path)) { // create the resource standin IResourceStandinNEW resourceStandin = createNewResourceStandin(getId(), root, path, type, isAnalyze()); // set resource IResourceStandinAwareProjectContentResource resource = getResourceFactory().createResource( resourceStandin.getProjectContentEntryId(), resourceStandin.getRoot(), resourceStandin.getPath()); // resourceStandin.setResource(resource); // return resource return resourceStandin; } else { // System.out.println(String.format("DUPLICATE RESOURCE IN ENTRY '%s': '%s'", getId(), path)); if (_isInitialized) { return getResource(path, type); } else { return null; } } } public void removeProjectContentResource(IProjectContentResource resource, ResourceType type) { // // add the resource switch (type) { case BINARY: { IResourceStandinNEW resourceStandin = binaryResourceStandins().remove(resource.getPath()); _projectDescription.removeBinaryResource(resourceStandin); break; } case SOURCE: { IResourceStandinNEW resourceStandin = sourceResourceStandins().remove(resource.getPath()); _projectDescription.removeSourceResource(resourceStandin); break; } default: break; } } /** * <p> * </p> * * @return */ private Set<VariablePath> sourcePaths() { // lazy initialization if (_sourcePaths == null) { _sourcePaths = new HashSet<VariablePath>(); } // return the source paths return _sourcePaths; } /** * <p> * </p> */ private void assertIsInitialized() { if (!_isInitialized) { Assert.isTrue(false, String.format("ProjectContentEntry '%s' has to be initialized.", toString())); } } /** * <p> * </p> * * @return */ private IResourceFactory getResourceFactory() { // TODO: REPLACE if (_resourceFactory == null) { // _resourceFactory = new IResourceFactory() { @Override public IResourceStandinNEW createResourceStandin(String contentId, String root, String path) { return new ResourceStandin(contentId, root, path); } @Override public IResourceStandinAwareProjectContentResource createResource(String contentId, String root, String path) { return new Resource(contentId, root, path); } }; } // return _resourceFactory; } }