/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.lang.reflect;
import gw.config.BaseService;
import gw.config.CommonServices;
import gw.fs.IDirectory;
import gw.fs.IFile;
import gw.lang.reflect.gs.TypeName;
import gw.lang.reflect.module.IModule;
import gw.util.GosuClassUtil;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public abstract class TypeLoaderBase extends BaseService implements ITypeLoader {
protected IModule _module;
protected Set<String> _typeNames;
/**
* @deprecated use TypeLoaderBase( IModule )
*/
protected TypeLoaderBase() {
this(TypeSystem.getCurrentModule());
System.out.println("WARNING: " + getClass().getName() + " was constructed without specifying a module!");
}
protected TypeLoaderBase(IModule module) {
_module = module;
}
@Override
public IModule getModule() {
return _module;
}
@Override
public boolean isCaseSensitive() {
return false;
}
@Override
public boolean handlesFile(IFile file) {
return false;
}
@Override
public boolean handlesDirectory(IDirectory dir) {
return false;
}
@Override
public String getNamespaceForDirectory(IDirectory dir) {
return null;
}
@Override
public String[] getTypesForFile(IFile file) {
return NO_TYPES;
}
@Override
public RefreshKind refreshedFile(IFile file, String[] types, RefreshKind kind) {
return kind;
}
@Override
public URL getResource(String name) {
return null;
}
@Override
public final void refreshedTypes(RefreshRequest request) {
if (shouldCacheTypeNames()) {
// get the type name set initialized first
getAllTypeNames();
if (request.kind == RefreshKind.CREATION) {
for (String type : request.types) {
_typeNames.add(type);
}
} else if (request.kind == RefreshKind.DELETION) {
for (String type : request.types) {
_typeNames.remove(type);
}
} else if (request.kind == RefreshKind.MODIFICATION) {
for (String type : request.types) {
_typeNames.add(type);
}
}
} else {
clearTypeNames();
}
refreshedTypesImpl(request);
}
protected void refreshedTypesImpl(RefreshRequest request) {
// for subclasses to do their refresh work
}
@Override
public final void refreshed() {
clearTypeNames();
refreshedImpl();
}
protected void clearTypeNames() {
_typeNames = null;
}
protected void refreshedImpl() {
// for subclasses to do their refresh work
}
public String toString() {
return this.getClass().getSimpleName() + " for module " + getModule().getName();
}
@Override
public Set<TypeName> getTypeNames(String namespace) {
if (hasNamespace(namespace)) {
return TypeLoaderBase.getTypeNames(namespace, this);
} else {
return Collections.emptySet();
}
}
public static Set<TypeName> getTypeNames(String parentNamespace, ITypeLoader loader) {
Set<TypeName> typeNames = new HashSet<TypeName>();
for (CharSequence typeNameCS : loader.getAllTypeNames()) {
String typeName = typeNameCS.toString();
String packageName = GosuClassUtil.getPackage(typeName);
if (packageName.equals(parentNamespace)) {
typeNames.add(new TypeName(typeName, loader, TypeName.Kind.TYPE, TypeName.Visibility.PUBLIC));
}
}
for (CharSequence namespaceCs : loader.getAllNamespaces()) {
String namespace = namespaceCs.toString();
String containingPackageName = GosuClassUtil.getPackage(namespace);
if (containingPackageName.equals(parentNamespace)) {
typeNames.add(new TypeName(GosuClassUtil.getNameNoPackage(namespace), loader, TypeName.Kind.NAMESPACE, TypeName.Visibility.PUBLIC));
}
}
return typeNames;
}
@Override
public boolean showTypeNamesInIDE() {
return true;
}
@Override
public void shutdown() {
if (shouldCacheTypeNames()) {
saveTypeNames();
}
}
private String getId() {
return _module.getName() + "$" + getClass().getSimpleName();
}
protected void deleteIndexFile() {
File indexFile = CommonServices.getPlatformHelper().getIndexFile(getId());
try {
indexFile.delete();
} catch (Exception e) {
}
return;
}
public void saveTypeNames() {
final File ideaCorruptionMarkerFile = CommonServices.getPlatformHelper().getIDEACorruptionMarkerFile();
if (ideaCorruptionMarkerFile.exists()) { // clean typenames cache
deleteIndexFile();
return;
}
File indexFile = CommonServices.getPlatformHelper().getIndexFile(getId());
PrintWriter writer = null;
try {
Set<String> allTypeNames = getAllTypeNames();
writer = new PrintWriter(new FileWriter(indexFile));
for (CharSequence typeName : allTypeNames) {
writer.println(typeName);
}
} catch (IOException e) {
throw new RuntimeException("Error while saving Gosu Type Index for " + this);
} finally {
try {
writer.close();
} catch (Throwable e) {
}
}
}
public Set<String> loadTypeNames() {
File indexFile = CommonServices.getPlatformHelper().getIndexFile(getId());
if (indexFile.exists()) {
LineNumberReader reader = null;
try {
reader = new LineNumberReader(new FileReader(indexFile));
Set<String> names = new HashSet<String>();
for (String typeName = reader.readLine(); typeName != null; typeName = reader.readLine()) {
names.add(typeName);
}
return names;
} catch (IOException e) {
// will return null
} finally {
try {
reader.close();
} catch (Throwable e) {
}
}
}
return null;
}
@Override
public final Set<String> getAllTypeNames() {
if (_typeNames == null) {
Set<String> names = shouldCacheTypeNames() ? loadTypeNames() : null;
if (names != null) {
_typeNames = names;
} else {
_typeNames = CommonServices.getPlatformHelper().isInIDE()
? new HashSet<String>( computeTypeNames() )
: new HashSet<String>( computeTypeNames() );
}
}
return _typeNames;
}
protected boolean shouldCacheTypeNames() {
return CommonServices.getPlatformHelper().shouldCacheTypeNames();
}
}