/*
* Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC
* All rights reserved.
*
* The source code of this document is proprietary work, and is not licensed for
* distribution. For information about licensing, contact Sam Harwell at:
* sam@tunnelvisionlabs.com
*/
package org.tvl.goworks.editor.go.codemodel.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.tvl.goworks.editor.go.codemodel.ImportDeclarationModel;
import org.tvl.goworks.editor.go.codemodel.IntrinsicTypeModels;
import org.tvl.goworks.editor.go.codemodel.TypeKind;
import org.tvl.goworks.editor.go.codemodel.TypeModel;
import org.tvl.goworks.editor.go.codemodel.TypeReferenceModel;
/**
*
* @author Sam Harwell
*/
public class TypeReferenceModelImpl extends TypeModelImpl implements TypeReferenceModel {
private final String referencedPackageName;
private final String referencedTypeName;
public TypeReferenceModelImpl(String referencedPackageName, String referencedTypeName, FileModelImpl fileModel) {
super(getQualifiedName(referencedPackageName, referencedTypeName), fileModel, null, null);
this.referencedPackageName = referencedPackageName;
this.referencedTypeName = referencedTypeName;
}
@Override
public TypeKind getKind() {
Collection<? extends TypeModelImpl> resolved = resolve();
if (resolved.isEmpty()) {
return TypeKind.UNKNOWN;
}
return resolved.iterator().next().getKind();
}
@Override
public String getSimpleName() {
return getName();
}
private static String getQualifiedName(String packageName, String typeName) {
if (packageName == null || packageName.isEmpty()) {
return typeName;
}
return packageName + "." + typeName;
}
@Override
public Collection<? extends TypeModelImpl> resolve() {
if (referencedPackageName == null || referencedPackageName.isEmpty()) {
// check for built-in types
TypeModel intrinsicType = IntrinsicTypeModels.getIntrinsicType(referencedTypeName);
if (intrinsicType != null) {
return Collections.singletonList((TypeModelImpl)intrinsicType);
}
}
CodeModelCacheImpl cache = CodeModelCacheImpl.getInstance();
List<PackageModelImpl> packages = new ArrayList<>();
FileModelImpl file = getFile();
if (file != null) {
for (ImportDeclarationModel importModel : file.getImportDeclarations()) {
boolean include = false;
if (referencedPackageName != null && !importModel.isMergeWithLocal() && referencedPackageName.equals(importModel.getName())) {
include = true;
} else if (referencedPackageName == null && importModel.isMergeWithLocal()) {
include = true;
}
if (include) {
packages.addAll(cache.resolvePackages(importModel));
}
}
}
if (referencedPackageName == null) {
packages.add(getPackage());
}
Collection<TypeModelImpl> resolved = new ArrayList<>();
for (PackageModelImpl packageModel : packages) {
resolved.addAll(packageModel.getTypes(referencedTypeName));
}
return resolved;
}
@Override
public boolean isResolved() {
return false;
}
@Override
public Collection<FieldModelImpl> getFields() {
Collection<? extends TypeModelImpl> resolved = resolve();
if (resolved == null || resolved.isEmpty()) {
return Collections.emptyList();
}
if (resolved.size() == 1) {
TypeModelImpl model = resolved.iterator().next();
return model.getFields();
} else {
List<FieldModelImpl> elements = new ArrayList<>();
for (TypeModelImpl model : resolved) {
elements.addAll(model.getFields());
}
return elements;
}
}
@Override
public Collection<FunctionModelImpl> getMethods() {
Collection<? extends TypeModelImpl> resolved = resolve();
if (resolved == null || resolved.isEmpty()) {
return Collections.emptyList();
}
if (resolved.size() == 1) {
TypeModelImpl model = resolved.iterator().next();
return model.getMethods();
} else {
List<FunctionModelImpl> elements = new ArrayList<>();
for (TypeModelImpl model : resolved) {
elements.addAll(model.getMethods());
}
return elements;
}
}
@Override
public Collection<? extends AbstractCodeElementModel> getMembers() {
Collection<? extends TypeModelImpl> resolved = resolve();
if (resolved == null || resolved.isEmpty()) {
return Collections.emptyList();
}
if (resolved.size() == 1) {
TypeModelImpl model = resolved.iterator().next();
return model.getMembers();
} else {
List<AbstractCodeElementModel> elements = new ArrayList<>();
for (TypeModelImpl model : resolved) {
elements.addAll(model.getMembers());
}
return elements;
}
}
}