/* * Copyright 2003-2011 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.generator.impl.cache; import jetbrains.mps.generator.impl.GenerationFailureException; import jetbrains.mps.generator.impl.dependencies.DependenciesBuilder; import jetbrains.mps.util.io.ModelInputStream; import jetbrains.mps.util.io.ModelOutputStream; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.model.SNodeId; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import java.io.IOException; import java.util.*; import java.util.Map.Entry; /** * Evgeny Gryaznov, Sep 23, 2010 */ public class TransientModelWithMetainfo { private static final int END_MARKER = '$' + ('M' << 24) + ('P' << 16) + ('S' << 8); public static final String CONDITIONALS_ID = ""; private SModelReference myReference; private List<SNode> myRoots; private Map<SNodeId, SNodeId> myRootToOriginal; private Map<SNodeId, MappingsMemento> myMappingsMemento; public TransientModelWithMetainfo(SModelReference reference, List<SNode> roots) { myReference = reference; myRoots = roots; myRootToOriginal = new HashMap<SNodeId, SNodeId>(); myMappingsMemento = new HashMap<SNodeId, MappingsMemento>(); } public List<SNode> getRoots() { return myRoots; } public MappingsMemento getMappingsMemento(String originalId) { return myMappingsMemento.get(PersistenceFacade.getInstance().createNodeId(originalId)); } public MappingsMemento getMappingsMemento(SNode originalRoot, boolean create) { SNodeId key = originalRoot == null ? null : originalRoot.getNodeId(); MappingsMemento mappingsMemento = myMappingsMemento.get(key); if(mappingsMemento == null && create) { mappingsMemento = new MappingsMemento(); myMappingsMemento.put(key, mappingsMemento); } return mappingsMemento; } public void updateMappings(String originalId, MappingsMemento mappingsMemento) { myMappingsMemento.put(PersistenceFacade.getInstance().createNodeId(originalId), mappingsMemento); } public String getOriginal(SNode root) { SNodeId id = myRootToOriginal.get(root.getNodeId()); if(id == null) { return CONDITIONALS_ID; } return id.toString(); } public void setOriginal(SNodeId sNodeId, String originalId) { myRootToOriginal.put(sNodeId, originalId.equals(CONDITIONALS_ID) ? null : PersistenceFacade.getInstance().createNodeId(originalId)); } public void save(ModelOutputStream os) throws IOException { new TransientModelPersistence(myReference).saveModel(myRoots, os); saveMetainfo(os); } private void saveMetainfo(ModelOutputStream os) throws IOException { os.writeInt(myRootToOriginal.size()); for (Entry<SNodeId, SNodeId> e : myRootToOriginal.entrySet()) { os.writeNodeId(e.getKey()); os.writeNodeId(e.getValue()); } os.writeInt(myMappingsMemento.size()); for(Entry<SNodeId, MappingsMemento> e : myMappingsMemento.entrySet()) { os.writeNodeId(e.getKey()); e.getValue().save(os); } os.writeInt(END_MARKER); } private void loadMetainfo(ModelInputStream is) throws IOException { int size = is.readInt(); for (; size > 0; size--) { SNodeId key = is.readNodeId(); SNodeId value = is.readNodeId(); myRootToOriginal.put(key, value); } size = is.readInt(); for(; size > 0; size--) { SNodeId key = is.readNodeId(); MappingsMemento mappingsMemento = MappingsMemento.load(is); myMappingsMemento.put(key, mappingsMemento); } if(is.readInt() != END_MARKER) { throw new IOException("corrupted file"); } } public static TransientModelWithMetainfo load(ModelInputStream is, SModelReference modelReference) throws IOException { List<SNode> roots = new TransientModelPersistence(modelReference).loadModel(is); TransientModelWithMetainfo result = new TransientModelWithMetainfo(modelReference, roots); result.loadMetainfo(is); return result; } public static TransientModelWithMetainfo create(SModel model, DependenciesBuilder builder) throws GenerationFailureException { ArrayList<SNode> roots = new ArrayList<SNode>(); for (SNode root1 : model.getRootNodes()) { roots.add(root1); } TransientModelWithMetainfo metainfo = new TransientModelWithMetainfo(model.getReference(), roots); Iterator<SNode> it = model.getRootNodes().iterator(); while (it.hasNext()) { SNode root = it.next(); SNode node = builder.getOriginalForOutput(root); metainfo.myRootToOriginal.put(root.getNodeId(), node == null ? null: node.getNodeId()); } builder.updateUnchanged(metainfo); return metainfo; } }