/* * Copyright 2003-2015 JetBrains s.r.o. * * 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 jetbrains.mps.nodeEditor.updater; import gnu.trove.THashSet; import jetbrains.mps.nodeEditor.ReferencedNodeContext; import jetbrains.mps.nodeEditor.memory.MemoryAnalyzer; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.mps.openapi.model.SNode; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Queue; import java.util.Set; /** * User: shatalin * Date: 22/12/15 */ class UpdateInfoIndex { private static final Logger LOG = LogManager.getLogger(UpdateInfoIndex.class); private final UpdateInfoNode myRootNode; private Map<ReferencedNodeContext, List<UpdateInfoNode>> myIndex; private Set<SNode> myVisualizedRoots; UpdateInfoIndex(UpdateInfoNode rootNode) { myRootNode = rootNode; buildIndex(rootNode); } private void buildIndex(UpdateInfoNode node) { long start = System.currentTimeMillis(); myIndex = new HashMap<ReferencedNodeContext, List<UpdateInfoNode>>(); myVisualizedRoots = new THashSet<SNode>(); Queue<UpdateInfoNode> nodesToProcess = new LinkedList<UpdateInfoNode>(); nodesToProcess.add(node); while (!nodesToProcess.isEmpty()) { UpdateInfoNode nextNode = nodesToProcess.remove(); List<UpdateInfoNode> nodesInContext = myIndex.get(nextNode.getContext()); if (nodesInContext == null) { nodesInContext = new ArrayList<UpdateInfoNode>(1); myIndex.put(nextNode.getContext(), nodesInContext); } nodesInContext.add(nextNode); myVisualizedRoots.add(nextNode.getContext().getNode().getContainingRoot()); nodesToProcess.addAll(nextNode.getChildren()); } LOG.debug("Building index took: " + (System.currentTimeMillis() - start) + "ms"); MemoryAnalyzer memoryAnalyzer = new MemoryAnalyzer(); if (memoryAnalyzer.isValid()) { calculateSize(memoryAnalyzer); LOG.debug("UpdateInfoIndex size: " + (memoryAnalyzer.getSize() / 1024) + "Kb"); } } UpdateInfoNode remove(ReferencedNodeContext childContext) { List<UpdateInfoNode> updateInfoNodes = myIndex.get(childContext); assert updateInfoNodes != null : childContext; if (updateInfoNodes.isEmpty()) { return null; } return updateInfoNodes.remove(0).detach(); } boolean isVisualized(SNode changedNode) { return myVisualizedRoots.contains(changedNode.getContainingRoot()); } void calculateSize(MemoryAnalyzer memoryAnalyzer) { memoryAnalyzer.appendObject(this); memoryAnalyzer.appendObject(myIndex); memoryAnalyzer.appendFirstNonPrimitiveField(myIndex); for (Entry<ReferencedNodeContext, List<UpdateInfoNode>> entry : myIndex.entrySet()) { memoryAnalyzer.appendObject(entry); memoryAnalyzer.appendCollection(entry.getValue()); } memoryAnalyzer.appendObject(myVisualizedRoots); memoryAnalyzer.appendField(myVisualizedRoots, "_set"); myRootNode.calculateSize(memoryAnalyzer); } }