/* * Copyright 2003-2016 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 org.jetbrains.mps.openapi.module; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.event.SNodeAddEvent; import org.jetbrains.mps.openapi.event.SNodeReadEvent; import org.jetbrains.mps.openapi.event.SNodeRemoveEvent; import org.jetbrains.mps.openapi.event.SPropertyChangeEvent; import org.jetbrains.mps.openapi.event.SPropertyReadEvent; import org.jetbrains.mps.openapi.event.SReferenceChangeEvent; import org.jetbrains.mps.openapi.event.SReferenceReadEvent; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SModel.Problem; import org.jetbrains.mps.openapi.model.SModelAccessListener; import org.jetbrains.mps.openapi.model.SModelChangeListener; import org.jetbrains.mps.openapi.model.SModelListener; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.model.SNodeAccessListener; import org.jetbrains.mps.openapi.model.SNodeChangeListener; import org.jetbrains.mps.openapi.model.SReference; /** * This class serves as a convenient implementation of all repository listeners at once. * In addition it tracks all objects (modules, models and nodes) as they come and leave the repository. */ public class SRepositoryContentAdapter extends SModuleListenerBase implements SModelChangeListener, SModelAccessListener, SModelListener, SModuleListener, SRepositoryListener, SRepositoryAttachListener, SNodeChangeListener, SNodeAccessListener { protected SRepositoryContentAdapter() { } // Own methods public void subscribeTo(SRepository repository) { repository.getModelAccess().checkReadAccess(); repository.addRepositoryListener(this); } public void unsubscribeFrom(SRepository repository) { repository.getModelAccess().checkReadAccess(); repository.removeRepositoryListener(this); } @Override public void startListening(@NotNull SRepository repository) { for (SModule module : repository.getModules()) { startListening(module); } } @Override public void stopListening(@NotNull SRepository repository) { for (SModule module : repository.getModules()) { stopListening(module); } } protected void startListening(SModule module) { if (!isIncluded(module)) return; module.addModuleListener(this); for (SModel model : module.getModels()) { startListening(model); } } protected void stopListening(SModule module) { // it's not very nice to stop listening models of any module, even the one we didn't include this module in startListening(SModule), but who cares for (SModel model : module.getModels()) { stopListening(model); } module.removeModuleListener(this); } /** * no-op by default. * Subclasses that wish to get model/node change/access events, shall add appropriate listeners here. These listeners * are implemented by this class only for convenience, events are not dispatched unless proper listener is explicitly attached. */ protected void startListening(SModel model) { } /** * no-op by default */ protected void stopListening(SModel model) { } /** * @return always <code>true</code> */ protected boolean isIncluded(SModule module) { return true; } // SRepositoryListener methods @Override public void moduleAdded(@NotNull SModule module) { startListening(module); repositoryChanged(); } @Override public void beforeModuleRemoved(@NotNull SModule module) { stopListening(module); } @Override public void moduleRemoved(@NotNull SModuleReference module) { repositoryChanged(); } @Override public void commandStarted(SRepository repository) { } @Override public void commandFinished(SRepository repository) { } @Override public void updateStarted(SRepository repository) { } @Override public void updateFinished(SRepository repository) { } @Override public void repositoryCommandStarted(SRepository repository) { } @Override public void repositoryCommandFinished(SRepository repository) { } // SModuleListener methods @Override public void moduleChanged(SModule module) { repositoryChanged(); } @Override public void modelAdded(SModule module, SModel model) { startListening(model); repositoryChanged(); } @Override public void beforeModelRemoved(SModule module, SModel model) { stopListening(model); } @Override public void modelRemoved(SModule module, SModelReference ref) { repositoryChanged(); } // SModelChangeListener listeners @Override public void nodeAdded(SModel model, SNode node, String role, SNode child) { } @Override public void nodeRemoved(SModel model, SNode node, String role, SNode child) { } @Override public void propertyChanged(SNode node, String propertyName, String oldValue, String newValue) { } @Override public void referenceChanged(SNode node, String role, SReference oldRef, SReference newRef) { } // SModelListener methods @Override public void modelLoaded(SModel model, boolean partially) { } @Override public void modelReplaced(SModel model) { } @Override public void modelUnloaded(SModel model) { } @Override public void modelSaved(SModel model) { } @Override public void conflictDetected(SModel model) { } @Override public void problemsDetected(SModel model, Iterable<Problem> problems) { } @Override public void modelAttached(SModel model, SRepository repository) { } @Override public void modelDetached(SModel model, SRepository repository) { } // SModelAccessListener methods @Override public void nodeRead(SNode node) { } @Override public void propertyRead(SNode node, String name) { } @Override public void referenceRead(SNode node, String role) { } /** * Handy notification about change in repository structure, namely added/removed modules and models. * For unknown reason also notifies about {@link SModuleListener#moduleChanged(SModule) 'unspecified'} module changes * no-op by default. */ public void repositoryChanged() { } // SNodeAccessListener @Override public void nodeRead(@NotNull SNodeReadEvent event) {} @Override public void propertyRead(@NotNull SPropertyReadEvent event) {} @Override public void referenceRead(@NotNull SReferenceReadEvent event) {} // SNodeChangeListener @Override public void propertyChanged(@NotNull SPropertyChangeEvent event) {} @Override public void referenceChanged(@NotNull SReferenceChangeEvent event) {} @Override public void nodeAdded(@NotNull SNodeAddEvent event) {} @Override public void nodeRemoved(@NotNull SNodeRemoveEvent event) {} }