/*
* Copyright 2013-2016 consulo.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package consulo.roots.impl;
import com.google.common.base.Predicate;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.UnknownFeaturesCollector;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import consulo.annotations.RequiredReadAction;
import consulo.module.extension.*;
import consulo.module.extension.impl.ModuleExtensionImpl;
import consulo.module.extension.impl.ModuleExtensionIndexCache;
import consulo.module.extension.impl.ModuleExtensionProviders;
import consulo.roots.ContentFolderScopes;
import consulo.roots.ContentFolderTypeProvider;
import consulo.roots.ModifiableModuleRootLayer;
import consulo.roots.orderEntry.OrderEntrySerializationUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author VISTALL
* @since 29.07.14
*/
public class ModuleRootLayerImpl implements ModifiableModuleRootLayer, Disposable {
public static final Logger LOGGER = Logger.getInstance(ModuleRootLayerImpl.class);
private static class ContentComparator implements Comparator<ContentEntry> {
public static final ContentComparator INSTANCE = new ContentComparator();
@Override
public int compare(@NotNull final ContentEntry o1, @NotNull final ContentEntry o2) {
return o1.getUrl().compareTo(o2.getUrl());
}
}
private static class CollectDependentModules extends RootPolicy<List<String>> {
@NotNull
@Override
public List<String> visitModuleOrderEntry(@NotNull ModuleOrderEntry moduleOrderEntry, @NotNull List<String> arrayList) {
arrayList.add(moduleOrderEntry.getModuleName());
return arrayList;
}
}
private class Order extends ArrayList<OrderEntry> {
@Override
public void clear() {
super.clear();
clearCachedEntries();
}
@NotNull
@Override
public OrderEntry set(int i, @NotNull OrderEntry orderEntry) {
super.set(i, orderEntry);
((OrderEntryBaseImpl)orderEntry).setIndex(i);
clearCachedEntries();
return orderEntry;
}
@Override
public boolean add(@NotNull OrderEntry orderEntry) {
super.add(orderEntry);
((OrderEntryBaseImpl)orderEntry).setIndex(size() - 1);
clearCachedEntries();
return true;
}
@Override
public void add(int i, OrderEntry orderEntry) {
super.add(i, orderEntry);
clearCachedEntries();
setIndicies(i);
}
@Override
public OrderEntry remove(int i) {
OrderEntry entry = super.remove(i);
setIndicies(i);
clearCachedEntries();
return entry;
}
@Override
public boolean remove(Object o) {
int index = indexOf(o);
if (index < 0) return false;
remove(index);
clearCachedEntries();
return true;
}
@Override
public boolean addAll(Collection<? extends OrderEntry> collection) {
int startSize = size();
boolean result = super.addAll(collection);
setIndicies(startSize);
clearCachedEntries();
return result;
}
@Override
public boolean addAll(int i, Collection<? extends OrderEntry> collection) {
boolean result = super.addAll(i, collection);
setIndicies(i);
clearCachedEntries();
return result;
}
@Override
public void removeRange(int i, int i1) {
super.removeRange(i, i1);
clearCachedEntries();
setIndicies(i);
}
@Override
public boolean removeAll(@NotNull Collection<?> collection) {
boolean result = super.removeAll(collection);
setIndicies(0);
clearCachedEntries();
return result;
}
@Override
public boolean retainAll(@NotNull Collection<?> collection) {
boolean result = super.retainAll(collection);
setIndicies(0);
clearCachedEntries();
return result;
}
private void clearCachedEntries() {
myCachedOrderEntries = null;
}
private void setIndicies(int startIndex) {
for (int j = startIndex; j < size(); j++) {
((OrderEntryBaseImpl)get(j)).setIndex(j);
}
}
}
private final Set<ContentEntry> myContent = new TreeSet<>(ContentComparator.INSTANCE);
private final List<OrderEntry> myOrderEntries = new Order();
// cleared by myOrderEntries modification, see Order
@Nullable
private OrderEntry[] myCachedOrderEntries;
private ModuleExtension[] myExtensions = ModuleExtension.EMPTY_ARRAY;
private final List<Element> myUnknownModuleExtensions = new SmartList<>();
private RootModelImpl myRootModel;
@NotNull
private final ModuleLibraryTable myModuleLibraryTable;
@RequiredReadAction
public ModuleRootLayerImpl(@Nullable ModuleRootLayerImpl originalLayer, @NotNull RootModelImpl rootModel) {
myRootModel = rootModel;
myModuleLibraryTable = new ModuleLibraryTable(this);
if (originalLayer != null) {
createMutableExtensions(originalLayer);
setContentEntriesFrom(originalLayer);
setOrderEntriesFrom(originalLayer);
}
else {
init();
}
}
public void loadState(@NotNull Element element, @Nullable ProgressIndicator progressIndicator) throws InvalidDataException {
removeAllContentEntries();
removeAllOrderEntries();
List<Element> children = element.getChildren();
int i = 0;
boolean moduleSourceAdded = false;
for (Element child : children) {
i++;
if (i % 10 == 0) {
if (progressIndicator != null) {
progressIndicator.checkCanceled();
}
}
String name = child.getName();
switch (name) {
case ModuleExtensionImpl.ELEMENT_NAME:
final String id = child.getAttributeValue("id");
ModuleExtensionProviderEP providerEP = ModuleExtensionProviders.findProvider(id);
if (providerEP != null) {
ModuleExtension<?> moduleExtension = getExtensionWithoutCheck(id);
assert moduleExtension != null;
moduleExtension.loadState(child);
}
else {
UnknownFeaturesCollector.getInstance(getProject()).registerUnknownFeature(ModuleExtensionProviders.getEpName(), id);
myUnknownModuleExtensions.add(child.clone());
}
break;
case ContentEntryImpl.ELEMENT_NAME:
ContentEntryImpl contentEntry = new ContentEntryImpl(child, this);
myContent.add(contentEntry);
break;
case OrderEntrySerializationUtil.ORDER_ENTRY_ELEMENT_NAME:
final OrderEntry orderEntry = OrderEntrySerializationUtil.loadOrderEntry(child, this);
if (orderEntry == null) {
continue;
}
if (orderEntry instanceof ModuleSourceOrderEntry) {
if (moduleSourceAdded) {
continue;
}
moduleSourceAdded = true;
}
myOrderEntries.add(orderEntry);
break;
}
}
if (!moduleSourceAdded) {
myOrderEntries.add(new ModuleSourceOrderEntryImpl(this));
}
}
public void writeExternal(@NotNull Element element) {
List<Element> moduleExtensionElements = new ArrayList<>();
for (ModuleExtension<?> extension : myExtensions) {
if (extension == null) {
continue;
}
final Element state = extension.getState();
if (state == null) {
continue;
}
moduleExtensionElements.add(state);
}
for (Element unknownModuleExtension : myUnknownModuleExtensions) {
moduleExtensionElements.add(unknownModuleExtension.clone());
}
Collections.sort(moduleExtensionElements, (o1, o2) -> Comparing.compare(o1.getAttributeValue("id"), o2.getAttributeValue("id")));
element.addContent(moduleExtensionElements);
for (ContentEntry contentEntry : getContent()) {
if (contentEntry instanceof ContentEntryImpl) {
final Element subElement = new Element(ContentEntryImpl.ELEMENT_NAME);
((ContentEntryImpl)contentEntry).writeExternal(subElement);
element.addContent(subElement);
}
}
for (OrderEntry orderEntry : getOrderEntries()) {
Element newElement = OrderEntrySerializationUtil.storeOrderEntry(orderEntry);
element.addContent(newElement);
}
}
@SuppressWarnings("unchecked")
@RequiredReadAction
public boolean copy(@NotNull ModuleRootLayerImpl toSet, boolean notifyExtensionListener) {
boolean changed = false;
ModuleExtensionChangeListener moduleExtensionChangeListener = getModule().getProject().getMessageBus().syncPublisher(ModuleExtension.CHANGE_TOPIC);
for (ModuleExtension extension : myExtensions) {
if (extension == null) {
continue;
}
MutableModuleExtension mutableExtension = (MutableModuleExtension)extension;
ModuleExtension originalExtension = toSet.getExtensionWithoutCheck(extension.getId());
assert originalExtension != null;
if (mutableExtension.isModified(originalExtension)) {
if (notifyExtensionListener) {
moduleExtensionChangeListener.beforeExtensionChanged(originalExtension, mutableExtension);
}
originalExtension.commit(mutableExtension);
changed = true;
}
}
if (areOrderEntriesChanged(toSet)) {
toSet.setOrderEntriesFrom(this);
changed = true;
}
if (areContentEntriesChanged(toSet)) {
toSet.setContentEntriesFrom(this);
changed = true;
}
toSet.myUnknownModuleExtensions.addAll(myUnknownModuleExtensions);
return changed;
}
@SuppressWarnings("unchecked")
@RequiredReadAction
public void createMutableExtensions(@Nullable ModuleRootLayerImpl layer) {
ModuleExtensionProviderEP[] providers = ModuleExtensionProviders.getProviders();
myExtensions = new ModuleExtension[providers.length];
for (ModuleExtensionProviderEP providerEP : providers) {
MutableModuleExtension mutable = providerEP.createMutable(this);
if (mutable == null) {
continue;
}
if (layer != null) {
final ModuleExtension<?> originalExtension = layer.getExtensionWithoutCheck(providerEP.getKey());
assert originalExtension != null;
mutable.commit(originalExtension);
}
myExtensions[providerEP.getInternalIndex()] = mutable;
}
}
private void setOrderEntriesFrom(@NotNull ModuleRootLayerImpl layer) {
removeAllOrderEntries();
for (OrderEntry orderEntry : layer.myOrderEntries) {
if (orderEntry instanceof ClonableOrderEntry) {
myOrderEntries.add(((ClonableOrderEntry)orderEntry).cloneEntry(this));
}
}
}
private void setContentEntriesFrom(@NotNull ModuleRootLayerImpl layer) {
removeAllContentEntries();
for (ContentEntry contentEntry : layer.myContent) {
if (contentEntry instanceof ClonableContentEntry) {
myContent.add(((ClonableContentEntry)contentEntry).cloneEntry(this));
}
}
}
@RequiredReadAction
public void init() {
removeAllOrderEntries();
myExtensions = ModuleExtension.EMPTY_ARRAY;
addSourceOrderEntries();
createMutableExtensions(null);
}
public void addSourceOrderEntries() {
myOrderEntries.add(new ModuleSourceOrderEntryImpl(this));
}
@NotNull
private ContentEntry addContentEntry(@NotNull ContentEntry e) {
if (myContent.contains(e)) {
for (ContentEntry contentEntry : getContentEntries()) {
if (ContentComparator.INSTANCE.compare(contentEntry, e) == 0) return contentEntry;
}
}
myContent.add(e);
return e;
}
public boolean areContentEntriesChanged(@NotNull ModuleRootLayerImpl original) {
return ArrayUtil.lexicographicCompare(getContentEntries(), original.getContentEntries()) != 0;
}
public boolean areOrderEntriesChanged(@NotNull ModuleRootLayerImpl original) {
OrderEntry[] orderEntries = getOrderEntries();
OrderEntry[] sourceOrderEntries = original.getOrderEntries();
if (orderEntries.length != sourceOrderEntries.length) return true;
for (int i = 0; i < orderEntries.length; i++) {
OrderEntry orderEntry = orderEntries[i];
OrderEntry sourceOrderEntry = sourceOrderEntries[i];
if (!orderEntriesEquals(orderEntry, sourceOrderEntry)) {
return true;
}
}
return false;
}
@NotNull
public RootModelImpl getRootModel() {
return myRootModel;
}
@SuppressWarnings("unchecked")
public boolean areExtensionsChanged(@NotNull ModuleRootLayerImpl original) {
for (int i = 0; i < ModuleExtensionProviders.getProviders().length; i++) {
MutableModuleExtension selfExtension = getExtension0(i);
ModuleExtension originalExtension = original.getExtension0(i);
if (selfExtension == null || originalExtension == null) {
continue;
}
if (selfExtension.isModified(originalExtension)) {
return true;
}
}
return false;
}
private static boolean orderEntriesEquals(@NotNull OrderEntry orderEntry1, @NotNull OrderEntry orderEntry2) {
if (orderEntry1.getClass() != orderEntry2.getClass()) {
return false;
}
if (orderEntry1 instanceof ExportableOrderEntry) {
if (!(((ExportableOrderEntry)orderEntry1).isExported() == ((ExportableOrderEntry)orderEntry2).isExported())) {
return false;
}
if (!(((ExportableOrderEntry)orderEntry1).getScope() == ((ExportableOrderEntry)orderEntry2).getScope())) {
return false;
}
}
return orderEntry1.isEquivalentTo(orderEntry2);
}
@NotNull
public Collection<ContentEntry> getContent() {
return myContent;
}
public Iterator<OrderEntry> getOrderIterator() {
return Collections.unmodifiableList(myOrderEntries).iterator();
}
@Override
@NotNull
public Project getProject() {
return getModule().getProject();
}
public boolean isChanged(@NotNull ModuleRootLayerImpl original) {
return areExtensionsChanged(original) || areOrderEntriesChanged(original) || areContentEntriesChanged(original);
}
@NotNull
@Override
public Module getModule() {
return myRootModel.getModule();
}
@Override
public ContentEntry[] getContentEntries() {
final Collection<ContentEntry> content = getContent();
return content.toArray(new ContentEntry[content.size()]);
}
@Override
public boolean iterateContentEntries(@NotNull Processor<ContentEntry> processor) {
for (ContentEntry contentEntry : myContent) {
if (!processor.process(contentEntry)) {
return false;
}
}
return true;
}
@NotNull
@Override
public OrderEntry[] getOrderEntries() {
OrderEntry[] cachedOrderEntries = myCachedOrderEntries;
if (cachedOrderEntries == null) {
myCachedOrderEntries = cachedOrderEntries = myOrderEntries.toArray(new OrderEntry[myOrderEntries.size()]);
}
return cachedOrderEntries;
}
@NotNull
@Override
public VirtualFile[] getContentRoots() {
final ArrayList<VirtualFile> result = new ArrayList<>();
for (ContentEntry contentEntry : getContent()) {
final VirtualFile file = contentEntry.getFile();
if (file != null) {
result.add(file);
}
}
return VfsUtilCore.toVirtualFileArray(result);
}
@NotNull
@Override
public String[] getContentRootUrls() {
if (getContent().isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
final ArrayList<String> result = new ArrayList<>(getContent().size());
for (ContentEntry contentEntry : getContent()) {
result.add(contentEntry.getUrl());
}
return ArrayUtil.toStringArray(result);
}
@NotNull
@Override
public String[] getContentFolderUrls(@NotNull Predicate<ContentFolderTypeProvider> predicate) {
List<String> result = new SmartList<>();
for (ContentEntry contentEntry : getContent()) {
Collections.addAll(result, contentEntry.getFolderUrls(predicate));
}
return ArrayUtil.toStringArray(result);
}
@NotNull
@Override
public VirtualFile[] getContentFolderFiles(@NotNull Predicate<ContentFolderTypeProvider> predicate) {
List<VirtualFile> result = new SmartList<>();
for (ContentEntry contentEntry : getContent()) {
Collections.addAll(result, contentEntry.getFolderFiles(predicate));
}
return VfsUtilCore.toVirtualFileArray(result);
}
@NotNull
@Override
public ContentFolder[] getContentFolders(@NotNull Predicate<ContentFolderTypeProvider> predicate) {
List<ContentFolder> result = new SmartList<>();
for (ContentEntry contentEntry : getContent()) {
Collections.addAll(result, contentEntry.getFolders(predicate));
}
return result.isEmpty() ? ContentFolder.EMPTY_ARRAY : result.toArray(new ContentFolder[result.size()]);
}
@NotNull
@Override
public VirtualFile[] getExcludeRoots() {
final List<VirtualFile> result = new SmartList<>();
for (ContentEntry contentEntry : getContent()) {
Collections.addAll(result, contentEntry.getFolderFiles(ContentFolderScopes.excluded()));
}
return VfsUtilCore.toVirtualFileArray(result);
}
@NotNull
@Override
public String[] getExcludeRootUrls() {
final List<String> result = new SmartList<>();
for (ContentEntry contentEntry : getContent()) {
Collections.addAll(result, contentEntry.getFolderUrls(ContentFolderScopes.excluded()));
}
return ArrayUtil.toStringArray(result);
}
@NotNull
@Override
public VirtualFile[] getSourceRoots() {
return getSourceRoots(true);
}
@NotNull
@Override
public VirtualFile[] getSourceRoots(boolean includingTests) {
List<VirtualFile> result = new SmartList<>();
for (ContentEntry contentEntry : getContent()) {
Collections.addAll(result, includingTests
? contentEntry.getFolderFiles(ContentFolderScopes.productionAndTest())
: contentEntry.getFolderFiles(ContentFolderScopes.production()));
}
return VfsUtilCore.toVirtualFileArray(result);
}
@NotNull
@Override
public String[] getSourceRootUrls() {
return getSourceRootUrls(true);
}
@NotNull
@Override
public String[] getSourceRootUrls(boolean includingTests) {
List<String> result = new SmartList<>();
for (ContentEntry contentEntry : getContent()) {
Collections.addAll(result, includingTests
? contentEntry.getFolderUrls(ContentFolderScopes.productionAndTest())
: contentEntry.getFolderUrls(ContentFolderScopes.production()));
}
return ArrayUtil.toStringArray(result);
}
@Override
public <R> R processOrder(RootPolicy<R> policy, R initialValue) {
R result = initialValue;
for (OrderEntry orderEntry : getOrderEntries()) {
result = orderEntry.accept(policy, result);
}
return result;
}
@NotNull
@Override
public OrderEnumerator orderEntries() {
return new ModuleOrderEnumerator(this, null);
}
@NotNull
@Override
public String[] getDependencyModuleNames() {
List<String> result =
orderEntries().withoutSdk().withoutLibraries().withoutModuleSourceEntries().process(new CollectDependentModules(), new ArrayList<String>());
return ArrayUtil.toStringArray(result);
}
@NotNull
@Override
public ModuleExtension[] getExtensions() {
if (myExtensions.length == 0) {
return ModuleExtension.EMPTY_ARRAY;
}
List<ModuleExtension> list = new ArrayList<>(myExtensions.length);
for (ModuleExtension<?> extension : myExtensions) {
if (extension.isEnabled()) {
list.add(extension);
}
}
return list.toArray(new ModuleExtension[list.size()]);
}
@NotNull
@Override
public Module[] getModuleDependencies() {
return getModuleDependencies(true);
}
@NotNull
@Override
public Module[] getModuleDependencies(boolean includeTests) {
final List<Module> result = new ArrayList<>();
for (OrderEntry entry : getOrderEntries()) {
if (entry instanceof ModuleOrderEntry) {
ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
final DependencyScope scope = moduleOrderEntry.getScope();
if (!includeTests && !scope.isForProductionCompile() && !scope.isForProductionRuntime()) {
continue;
}
final Module module1 = moduleOrderEntry.getModule();
if (module1 != null) {
result.add(module1);
}
}
}
return result.isEmpty() ? Module.EMPTY_ARRAY : ContainerUtil.toArray(result, new Module[result.size()]);
}
@Override
@Nullable
@SuppressWarnings("unchecked")
public <T extends ModuleExtension> T getExtension(Class<T> clazz) {
if(myExtensions.length == 0) {
return null;
}
int[] ids = ModuleExtensionIndexCache.get(clazz);
for (int id : ids) {
ModuleExtension extension = myExtensions[id];
if (extension != null && extension.isEnabled()) {
return (T)extension;
}
}
return null;
}
@Override
@Nullable
@SuppressWarnings("unchecked")
public <T extends ModuleExtension> T getExtensionWithoutCheck(Class<T> clazz) {
if(myExtensions.length == 0) {
return null;
}
int[] ids = ModuleExtensionIndexCache.get(clazz);
for (int id : ids) {
ModuleExtension extension = myExtensions[id];
if (extension != null) {
return (T)extension;
}
}
return null;
}
@Override
@Nullable
@SuppressWarnings("unchecked")
public <T extends ModuleExtension> T getExtension(@NotNull String key) {
ModuleExtensionProviderEP ep = ModuleExtensionProviders.findProvider(key);
if (ep == null) {
return null;
}
ModuleExtension extension = getExtension0(ep.getInternalIndex());
return extension != null && extension.isEnabled() ? (T)extension : null;
}
@Override
@Nullable
@SuppressWarnings("unchecked")
public <T extends ModuleExtension> T getExtensionWithoutCheck(@NotNull String key) {
ModuleExtensionProviderEP ep = ModuleExtensionProviders.findProvider(key);
if (ep == null) {
return null;
}
return getExtension0(ep.getInternalIndex());
}
@Nullable
@SuppressWarnings("unchecked")
private <T extends ModuleExtension> T getExtension0(int i) {
ModuleExtension extension = myExtensions.length == 0 ? null : myExtensions[i];
return (T)extension;
}
@NotNull
@Override
public ContentEntry addContentEntry(@NotNull VirtualFile file) {
return addContentEntry(new ContentEntryImpl(file, this));
}
@NotNull
@Override
public ContentEntry addContentEntry(@NotNull String url) {
return addContentEntry(new ContentEntryImpl(url, this));
}
@Override
public void removeContentEntry(@NotNull ContentEntry entry) {
LOGGER.assertTrue(myContent.contains(entry));
if (entry instanceof Disposable) {
Disposer.dispose((Disposable)entry);
}
myContent.remove(entry);
}
@Override
public void addOrderEntry(@NotNull OrderEntry entry) {
LOGGER.assertTrue(!myOrderEntries.contains(entry));
myOrderEntries.add(entry);
}
@NotNull
@Override
public LibraryOrderEntry addLibraryEntry(@NotNull Library library) {
final LibraryOrderEntry libraryOrderEntry = new LibraryOrderEntryImpl(library, this);
assert libraryOrderEntry.isValid();
myOrderEntries.add(libraryOrderEntry);
return libraryOrderEntry;
}
@NotNull
@Override
public ModuleExtensionWithSdkOrderEntry addModuleExtensionSdkEntry(@NotNull ModuleExtensionWithSdk<?> moduleExtension) {
final ModuleExtensionWithSdkOrderEntryImpl moduleSdkOrderEntry = new ModuleExtensionWithSdkOrderEntryImpl(moduleExtension.getId(), this);
assert moduleSdkOrderEntry.isValid();
// add module extension sdk entry after another SDK entry or before module source
int sourcePosition = -1, sdkPosition = -1;
for (int j = 0; j < myOrderEntries.size(); j++) {
OrderEntry orderEntry = myOrderEntries.get(j);
if (orderEntry instanceof ModuleSourceOrderEntry) {
sourcePosition = j;
}
else if (orderEntry instanceof ModuleExtensionWithSdkOrderEntry) {
sdkPosition = j;
}
}
if (sdkPosition >= 0) {
myOrderEntries.add(sdkPosition + 1, moduleSdkOrderEntry);
}
else if (sourcePosition >= 0) {
myOrderEntries.add(sourcePosition, moduleSdkOrderEntry);
}
else {
myOrderEntries.add(0, moduleSdkOrderEntry);
}
return moduleSdkOrderEntry;
}
@NotNull
@Override
public LibraryOrderEntry addInvalidLibrary(@NotNull @NonNls String name, @NotNull String level) {
final LibraryOrderEntry libraryOrderEntry = new LibraryOrderEntryImpl(name, level, this);
myOrderEntries.add(libraryOrderEntry);
return libraryOrderEntry;
}
@NotNull
@Override
public ModuleOrderEntry addModuleOrderEntry(@NotNull Module module) {
LOGGER.assertTrue(!module.equals(getModule()));
LOGGER.assertTrue(Comparing.equal(myRootModel.getModule().getProject(), module.getProject()));
final ModuleOrderEntryImpl moduleOrderEntry = new ModuleOrderEntryImpl(module, this);
myOrderEntries.add(moduleOrderEntry);
return moduleOrderEntry;
}
@NotNull
@Override
public ModuleOrderEntry addInvalidModuleEntry(@NotNull String name) {
LOGGER.assertTrue(!name.equals(getModule().getName()));
final ModuleOrderEntryImpl moduleOrderEntry = new ModuleOrderEntryImpl(name, this);
myOrderEntries.add(moduleOrderEntry);
return moduleOrderEntry;
}
@Nullable
@Override
public LibraryOrderEntry findLibraryOrderEntry(@NotNull Library library) {
for (OrderEntry orderEntry : getOrderEntries()) {
if (orderEntry instanceof LibraryOrderEntry && library.equals(((LibraryOrderEntry)orderEntry).getLibrary())) {
return (LibraryOrderEntry)orderEntry;
}
}
return null;
}
@Nullable
@Override
public ModuleExtensionWithSdkOrderEntry findModuleExtensionSdkEntry(@NotNull ModuleExtension extension) {
for (OrderEntry orderEntry : getOrderEntries()) {
if (orderEntry instanceof ModuleExtensionWithSdkOrderEntry &&
extension.getId().equals(((ModuleExtensionWithSdkOrderEntry)orderEntry).getModuleExtensionId())) {
return (ModuleExtensionWithSdkOrderEntry)orderEntry;
}
}
return null;
}
@Override
public void removeOrderEntry(@NotNull OrderEntry orderEntry) {
removeOrderEntryInternal(orderEntry);
}
private void removeOrderEntryInternal(OrderEntry entry) {
LOGGER.assertTrue(myOrderEntries.contains(entry));
Disposer.dispose((OrderEntryBaseImpl)entry);
myOrderEntries.remove(entry);
}
@Override
public void rearrangeOrderEntries(@NotNull OrderEntry[] newEntries) {
assertValidRearrangement(newEntries);
myOrderEntries.clear();
ContainerUtil.addAll(myOrderEntries, newEntries);
}
private void assertValidRearrangement(@NotNull OrderEntry[] newEntries) {
String error = checkValidRearrangement(newEntries);
LOGGER.assertTrue(error == null, error);
}
@Nullable
private String checkValidRearrangement(@NotNull OrderEntry[] newEntries) {
if (newEntries.length != myOrderEntries.size()) {
return "Size mismatch: old size=" + myOrderEntries.size() + "; new size=" + newEntries.length;
}
Set<OrderEntry> set = new HashSet<>();
for (OrderEntry newEntry : newEntries) {
if (!myOrderEntries.contains(newEntry)) {
return "Trying to add nonexisting order entry " + newEntry;
}
if (set.contains(newEntry)) {
return "Trying to add duplicate order entry " + newEntry;
}
set.add(newEntry);
}
return null;
}
public void removeAllContentEntries() {
for (ContentEntry entry : myContent) {
if (entry instanceof BaseModuleRootLayerChild) {
Disposer.dispose((BaseModuleRootLayerChild)entry);
}
}
myContent.clear();
}
public void removeAllOrderEntries() {
for (OrderEntry entry : myOrderEntries) {
Disposer.dispose((OrderEntryBaseImpl)entry);
}
myOrderEntries.clear();
}
@Override
public void dispose() {
removeAllContentEntries();
removeAllOrderEntries();
for (ModuleExtension<?> extension : myExtensions) {
if (extension instanceof Disposable) {
Disposer.dispose((Disposable)extension);
}
}
myExtensions = ModuleExtension.EMPTY_ARRAY;
}
@NotNull
@Override
public LibraryTable getModuleLibraryTable() {
return myModuleLibraryTable;
}
@Override
public <T extends OrderEntry> void replaceEntryOfType(Class<T> entryClass, T entry) {
for (int i = 0; i < myOrderEntries.size(); i++) {
OrderEntry orderEntry = myOrderEntries.get(i);
if (entryClass.isInstance(orderEntry)) {
myOrderEntries.remove(i);
if (entry != null) {
myOrderEntries.add(i, entry);
}
return;
}
}
if (entry != null) {
myOrderEntries.add(0, entry);
}
}
}