/*******************************************************************************
* Copyright (c) 2011 Gerd Wuetherich (gerd@gerd-wuetherich.de).
* 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:
* Gerd Wuetherich (gerd@gerd-wuetherich.de) - initial API and implementation
******************************************************************************/
package org.bundlemaker.core.jtype.internal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.bundlemaker.core.common.FlyWeightString;
import org.bundlemaker.core.common.IResource;
import org.bundlemaker.core.jtype.IModifiableType;
import org.bundlemaker.core.jtype.IReference;
import org.bundlemaker.core.jtype.IType;
import org.bundlemaker.core.jtype.ITypeModularizedSystem;
import org.bundlemaker.core.jtype.ITypeResource;
import org.bundlemaker.core.jtype.ReferenceAttributes;
import org.bundlemaker.core.jtype.TypeEnum;
import org.bundlemaker.core.project.IProjectContentResource;
import org.bundlemaker.core.resource.IModularizedSystem;
import org.bundlemaker.core.resource.IModule;
import org.bundlemaker.core.resource.IModuleResource;
import org.eclipse.core.runtime.Assert;
/**
* <p>
* </p>
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public class Type implements IType, IModifiableType {
/** the fully qualified name */
private FlyWeightString _fullyQualifiedName;
/** the references set */
private Set<Reference> _references;
/** the type of this type (enum, class, interface, annotation) **/
private TypeEnum _typeEnum;
/** Is this type abstract? */
private boolean _abstractType;
/** - */
private transient String _projectContentEntryId;
/** transient: the source resource */
private transient IModuleResource _sourceResource;
/** transient: the binary resource */
private transient IModuleResource _binaryResource;
/** transient: the reference container */
private transient ReferenceContainer _referenceContainer;
/**
* <p>
* </p>
*
* @param fullyQualifiedName
* @param typeEnum
*/
public Type(String fullyQualifiedName, TypeEnum typeEnum, String contentEntry, boolean abstractType) {
Assert.isNotNull(fullyQualifiedName);
Assert.isNotNull(typeEnum);
Assert.isNotNull(contentEntry);
//
_fullyQualifiedName = new FlyWeightString(fullyQualifiedName);
// the type of the type
_typeEnum = typeEnum;
_abstractType = abstractType;
//
_projectContentEntryId = contentEntry;
}
// /**
// * <p>
// * Creates a new instance of type {@link Type}.
// * </p>
// *
// * @param fullyQualifiedName
// */
// public Type(String fullyQualifiedName) {
//
// Assert.isNotNull(fullyQualifiedName);
//
// //
// _fullyQualifiedName = new FlyWeightString(fullyQualifiedName);
// }
/**
* <p>
* </p>
*
* @param flyWeightCache
*/
public Type(String fullyQualifiedName, TypeEnum typeEnum, FlyWeightReferenceCache flyWeightCache, boolean abstractType) {
Assert.isNotNull(fullyQualifiedName);
Assert.isNotNull(typeEnum);
Assert.isNotNull(flyWeightCache);
//
_fullyQualifiedName = flyWeightCache.getFlyWeightStringCache().getFlyWeightString(fullyQualifiedName);
// the type of the type
_typeEnum = typeEnum;
_abstractType = abstractType;
createReferenceContainer(flyWeightCache);
}
@Override
public String getProjectContentEntryId() {
if (_projectContentEntryId != null) {
return _projectContentEntryId;
}
return (_binaryResource != null && _binaryResource instanceof IProjectContentResource) ? ((IProjectContentResource) _binaryResource)
.getProjectContentEntryId()
: ((IProjectContentResource) _sourceResource).getProjectContentEntryId();
}
@Override
public String getFullyQualifiedName() {
return _fullyQualifiedName.toString();
}
@Override
public String getPackageName() {
//
String typeName = _fullyQualifiedName.toString();
// get index of the last '.'
int lastIndex = typeName.lastIndexOf('.');
//
return lastIndex == -1 ? "" : typeName.substring(0, lastIndex);
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
// get the fully qualified name
String fullyQualifiedName = _fullyQualifiedName.toString();
// get the index
int index = fullyQualifiedName.lastIndexOf('.');
// return the result
return index != -1 ? fullyQualifiedName.substring(index + 1) : fullyQualifiedName;
}
/**
* {@inheritDoc}
*/
@Override
public Set<IReference> getReferences() {
Set<? extends IReference> result = references();
return Collections.unmodifiableSet(result);
}
/**
* {@inheritDoc}
*/
@Override
public IReference getReference(String fullyQualifiedName) {
//
Assert.isNotNull(fullyQualifiedName);
//
for (Reference reference : _references) {
//
if (fullyQualifiedName.equals(reference.getFullyQualifiedName())) {
return reference;
}
}
//
return null;
}
/**
* {@inheritDoc}
*/
@Override
public TypeEnum getType() {
return _typeEnum;
}
/**
* {@inheritDoc}
*/
@Override
public IModuleResource getSourceResource() {
return _sourceResource;
}
/**
* {@inheritDoc}
*/
@Override
public IModuleResource getBinaryResource() {
return _binaryResource;
}
@Override
public IResource getBinaryReadableResource() {
return _binaryResource;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasSourceResource() {
return _sourceResource != null;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasBinaryResource() {
return getBinaryResource() != null;
}
/**
* <p>
* </p>
*
* @param type
* @return
*/
@Override
public final boolean handleAsPrimaryType() {
// if the type does not has a source resource,
// handle the type as primary type
if (!this.hasSourceResource()) {
return true;
}
//
IModuleResource sourceResource = this.getSourceResource();
// if the source resource does not contain a primary type,
// handle the non primary type as a primary type
if (!sourceResource.adaptAs(ITypeResource.class).hasPrimaryType()) {
return true;
}
//
return sourceResource.adaptAs(ITypeResource.class).isPrimaryType(this);
}
/**
* {@inheritDoc}
*/
@Override
public IModule getModule(IModularizedSystem modularizedSystem) {
Assert.isNotNull(modularizedSystem);
IModule result = null;
if (_binaryResource != null && _binaryResource instanceof IModuleResource) {
result = ((IModuleResource) _binaryResource).getModule(modularizedSystem);
}
if (result == null && _sourceResource != null && _sourceResource instanceof IModuleResource) {
result = ((IModuleResource) _sourceResource).getModule(modularizedSystem);
}
if (result == null) {
result = modularizedSystem.adaptAs(ITypeModularizedSystem.class).getAssociatedModule(this);
}
if (result == null) {
// throw new RuntimeException("Type has no module " + this.toString());
// System.out.println("Type has no module " + this.toString());
return null;
} else {
return result;
}
}
/**
* {@inheritDoc}
*/
@Override
public void recordReference(String fullyQualifiedName, ReferenceAttributes referenceAttributes) {
_referenceContainer.recordReference(fullyQualifiedName, referenceAttributes);
}
/**
* <p>
* </p>
*
* @param sourceResource
*/
public void setSourceResource(IModuleResource sourceResource) {
_sourceResource = sourceResource;
}
/**
* <p>
* </p>
*
* @param binaryResource
*/
public void setBinaryResource(IModuleResource binaryResource) {
_binaryResource = binaryResource;
}
/**
* <p>
* </p>
*
* @param typeEnum
*/
public void setTypeEnum(TypeEnum typeEnum) {
_typeEnum = typeEnum;
}
/*
* (non-Javadoc)
*
* @see org.bundlemaker.core.resource.IModifiableType#getModifiableReferences()
*/
public Set<Reference> getModifiableReferences() {
return references();
}
/*
* (non-Javadoc)
*
* @see org.bundlemaker.core.resource.IType#isAbstractType()
*/
@Override
public boolean isAbstractType() {
return _abstractType;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isLocalOrAnonymousType() {
return _fullyQualifiedName.toString().matches(".*\\$\\d.*");
}
/**
* {@inheritDoc}
*/
@Override
public boolean isInnerType() {
return _fullyQualifiedName.toString().matches(".*\\$.*");
}
@Override
public boolean isPrimaryType() {
if (!hasSourceResource()) {
return true;
}
IModuleResource sourceResource = getSourceResource();
return sourceResource.adaptAs(ITypeResource.class).isPrimaryType(this);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "Type [_fullyQualifiedName=" + _fullyQualifiedName + ", _typeEnum=" + _typeEnum + "]";
}
/**
* <p>
* </p>
*
* @param flyWeightCache
*/
public void createReferenceContainer(FlyWeightReferenceCache flyWeightCache) {
//
_referenceContainer = new ReferenceContainer(flyWeightCache) {
@Override
protected Set<Reference> createReferencesSet() {
return references();
}
};
}
@Override
public int compareTo(IType o) {
return this.getFullyQualifiedName().compareTo(o.getFullyQualifiedName());
}
/**
* <p>
* </p>
*
* @return
*/
private Set<Reference> references() {
// create if necessary
if (_references == null) {
_references = new HashSet<Reference>();
}
// return the result
return _references;
}
}