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); } }