package jetbrains.mps.persistence.java.library;
/*Generated by MPS */
import jetbrains.mps.extapi.persistence.FileBasedModelRoot;
import jetbrains.mps.extapi.persistence.CopyableModelRoot;
import jetbrains.mps.java.stub.PackageScopeControl;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SModelId;
import org.jetbrains.mps.openapi.persistence.Memento;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import jetbrains.mps.vfs.IFile;
import java.util.HashSet;
import jetbrains.mps.internal.collections.runtime.CollectionSequence;
import jetbrains.mps.internal.collections.runtime.ISelector;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import jetbrains.mps.vfs.path.Path;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import org.jetbrains.mps.openapi.module.SModule;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.internal.collections.runtime.Sequence;
import org.jetbrains.mps.openapi.model.SModelReference;
import jetbrains.mps.java.stub.JavaPackageNameStub;
import jetbrains.mps.extapi.persistence.FolderSetDataSource;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.extapi.persistence.CopyNotSupportedException;
public class JavaClassStubsModelRoot extends FileBasedModelRoot implements CopyableModelRoot<JavaClassStubsModelRoot> {
private PackageScopeControl myPackageScope;
@Override
public String getType() {
return JavaClassStubConstants.STUB_TYPE;
}
@Override
public SModel getModel(@NotNull SModelId id) {
// todo implement
return null;
}
@Override
public void load(@NotNull Memento memento) {
super.load(memento);
// Perhaps, shall support multiple scope configurations per root
Memento packScope = memento.getChild("PackageScope");
if (packScope != null) {
myPackageScope = new PackageScopeControl();
myPackageScope.load(packScope);
}
}
@Override
public void save(@NotNull Memento memento) {
super.save(memento);
if (myPackageScope != null) {
myPackageScope.save(memento.createChild("PackageScope"));
}
}
@NotNull
@Override
public Iterable<SModel> loadModels() {
final List<SModel> result = ListSequence.fromList(new ArrayList<SModel>());
final Collection<String> files = getFiles(FileBasedModelRoot.SOURCE_ROOTS);
final Collection<String> excludedFiles = getFiles(FileBasedModelRoot.EXCLUDED);
Set<IFile> jarsToLoad = new HashSet<IFile>();
Set<IFile> cpRootsToLoad = new HashSet<IFile>();
for (IFile file : CollectionSequence.fromCollection(files).select(new ISelector<String, IFile>() {
public IFile select(String it) {
return getFileSystem().getFile(it);
}
})) {
collectJarFiles(file, excludedFiles, jarsToLoad);
// we suppose here that each path can be either a jar-file or a classes directory or a jar directory,
// but does not contain both jar-fils and class-files
if (SetSequence.fromSet(jarsToLoad).isNotEmpty()) {
continue;
}
SetSequence.fromSet(cpRootsToLoad).addElement(file);
}
SetSequence.fromSet(jarsToLoad).select(new ISelector<IFile, IFile>() {
public IFile select(IFile it) {
return getFileSystem().getFile(it.getPath() + Path.ARCHIVE_SEPARATOR);
}
}).visitAll(new IVisitor<IFile>() {
public void visit(IFile it) {
getModelDescriptors(result, it, "", getModule());
}
});
SetSequence.fromSet(cpRootsToLoad).visitAll(new IVisitor<IFile>() {
public void visit(IFile it) {
getModelDescriptors(result, it, "", getModule());
}
});
return result;
}
private void collectJarFiles(final IFile file, Collection<String> excluded, Set<IFile> files) {
if (CollectionSequence.fromCollection(excluded).contains(file.getPath())) {
return;
}
if (file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
SetSequence.fromSet(files).addElement(file);
return;
}
if (!(file.isDirectory())) {
return;
}
for (IFile child : file.getChildren()) {
collectJarFiles(child, excluded, files);
}
}
@Override
public boolean canCreateModels() {
return false;
}
@Override
public boolean canCreateModel(@NotNull String string) {
return false;
}
@Override
public SModel createModel(@NotNull String string) {
return null;
}
public void getModelDescriptors(final List<SModel> result, IFile file, String prefix, SModule module) {
List<IFile> children = file.getChildren();
for (IFile subdir : ListSequence.fromList(children).where(new IWhereFilter<IFile>() {
public boolean accept(IFile it) {
return it.isDirectory();
}
})) {
String pack = ((prefix.length() == 0 ? subdir.getName() : prefix + '.' + subdir.getName()));
if (myPackageScope != null && !(myPackageScope.isIncluded(pack))) {
if (myPackageScope.isAnyChildIncluded(pack)) {
getModelDescriptors(result, subdir, pack, module);
}
continue;
}
List<IFile> subchildren = subdir.getChildren();
Iterable<IFile> rootClasses = ListSequence.fromList(subchildren).where(new IWhereFilter<IFile>() {
public boolean accept(IFile it) {
return it.getName().endsWith(".class") && !(it.getName().contains("$"));
}
});
if (Sequence.fromIterable(rootClasses).isNotEmpty()) {
final SModelReference modelReference = new JavaPackageNameStub(pack).asModelReference(module.getModuleReference());
JavaClassStubModelDescriptor smd;
// FIXME: hack, see comment below
SModel modelDescriptor = getModelAlreadyRegistered(module, modelReference);
if (modelDescriptor != null) {
assert modelDescriptor instanceof JavaClassStubModelDescriptor;
smd = (JavaClassStubModelDescriptor) modelDescriptor;
ListSequence.fromList(result).addElement(modelDescriptor);
} else if (ListSequence.fromList(result).any(new IWhereFilter<SModel>() {
public boolean accept(SModel it) {
return it.getModelId().equals(modelReference.getModelId());
}
})) {
modelDescriptor = ListSequence.fromList(result).findFirst(new IWhereFilter<SModel>() {
public boolean accept(SModel it) {
return it.getModelId().equals(modelReference.getModelId());
}
});
assert modelDescriptor instanceof JavaClassStubModelDescriptor;
smd = (JavaClassStubModelDescriptor) modelDescriptor;
} else {
smd = new JavaClassStubModelDescriptor(modelReference, new FolderSetDataSource());
smd.setModelRoot(this);
if (myPackageScope != null) {
smd.setSkipPrivate(myPackageScope.isSkipPrivate());
}
ListSequence.fromList(result).addElement(smd);
}
smd.getSource().addPath(subdir, this);
}
getModelDescriptors(result, subdir, pack, module);
}
}
/**
* DIRTY_HACK
* AlexP:
* Here we check whether some another classes root is already registered
* Because of the model's name clash we cannot simply return new model with new root.
* FIXME:
* Probably the solution is to get rid of multiple *java_classes* stub roots and
* Allow user to have only one stub root of this kind
*/
@Nullable
private SModel getModelAlreadyRegistered(SModule module, SModelReference modelReference) {
return module.getModel(modelReference.getModelId());
}
@Override
public void copyTo(@NotNull JavaClassStubsModelRoot root) throws CopyNotSupportedException {
super.copyContentRootAndFiles(root);
}
}