Package edu.stanford.bmir.protege.web.server.watches

Source Code of edu.stanford.bmir.protege.web.server.watches.WatchManagerImpl

package edu.stanford.bmir.protege.web.server.watches;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import edu.stanford.bmir.protege.web.server.MetaProjectManager;
import edu.stanford.bmir.protege.web.server.app.App;
import edu.stanford.bmir.protege.web.server.app.WebProtegeProperties;
import edu.stanford.bmir.protege.web.server.logging.WebProtegeLoggerManager;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProject;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProjectFileStore;
import edu.stanford.bmir.protege.web.shared.HasDispose;
import edu.stanford.bmir.protege.web.shared.event.*;
import edu.stanford.bmir.protege.web.shared.user.UserId;
import edu.stanford.bmir.protege.web.shared.watches.*;
import edu.stanford.smi.protege.server.metaproject.User;
import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.util.OWLEntityVisitorExAdapter;

import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* Author: Matthew Horridge<br>
* Stanford University<br>
* Bio-Medical Informatics Research Group<br>
* Date: 21/03/2013
*/
public class WatchManagerImpl implements WatchManager, HasDispose {

    private static final String WATCHES_FILE_NAME = "watches.csv";

    private static final String ENTITY_FRAME_WATCH_NAME = "EntityFrameWatch";

    private static final String HIERARCHY_BRANCH_WATCH_NAME = "HierarchyBranchWatch";

    private ExecutorService emailExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setPriority(Thread.MIN_PRIORITY).setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            WebProtegeLoggerManager.get(WatchManagerImpl.class).severe(e);
        }
    }).build());

    private Multimap<UserId, Watch<?>> userId2Watch = HashMultimap.create();

    private Multimap<Watch<?>, UserId> watch2UserId = HashMultimap.create();

    private Multimap<Object, Watch<?>> watchObject2Watch = HashMultimap.create();

    private OWLAPIProject project;


    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private Lock readLock = readWriteLock.readLock();

    private Lock writeLock = readWriteLock.writeLock();

    private File watchFile;

    public WatchManagerImpl(OWLAPIProject project) {
        this.project = project;
        final OWLAPIProjectFileStore projectFileStore = OWLAPIProjectFileStore.getProjectFileStore(project.getProjectId());
        watchFile = new File(projectFileStore.getProjectDirectory(), WATCHES_FILE_NAME);

        if(watchFile.exists()) {
            readWatches();
        }
        project.getEventManager().addHandler(ClassFrameChangedEvent.TYPE, new ClassFrameChangedEventHandler() {
            @Override
            public void classFrameChanged(ClassFrameChangedEvent event) {
                handleFrameChanged(event.getEntity());
            }
        });
        project.getEventManager().addHandler(ObjectPropertyFrameChangedEvent.TYPE, new ObjectPropertyFrameChangedEventHandler() {
            @Override
            public void objectPropertyFrameChanged(ObjectPropertyFrameChangedEvent event) {
                handleFrameChanged(event.getEntity());
            }
        });
        project.getEventManager().addHandler(DataPropertyFrameChangedEvent.TYPE, new DataPropertyFrameChangedEventHandler() {
            @Override
            public void dataPropertyFrameChanged(DataPropertyFrameChangedEvent event) {
                handleFrameChanged(event.getEntity());
            }
        });
        project.getEventManager().addHandler(AnnotationPropertyFrameChangedEvent.TYPE, new AnnotationPropertyFrameChangedEventHandler() {
            @Override
            public void annotationPropertyFrameChanged(AnnotationPropertyFrameChangedEvent event) {
                handleFrameChanged(event.getEntity());
            }
        });
        project.getEventManager().addHandler(NamedIndividualFrameChangedEvent.TYPE, new NamedIndividualFrameChangedEventHandler() {
            @Override
            public void namedIndividualFrameChanged(NamedIndividualFrameChangedEvent event) {
                handleFrameChanged(event.getEntity());
            }
        });
    }

    public Set<Watch<?>> getWatches(UserId userId) {
        try {
            readLock.lock();
            return new HashSet<Watch<?>>(userId2Watch.get(checkNotNull(userId)));
        }
        finally {
            readLock.unlock();
        }
    }

    public void addWatch(Watch<?> watch, UserId userId) {
        insertWatch(watch, userId);
        appendChange(Operation.ADD, watch, userId);
        project.getEventManager().postEvent(new WatchAddedEvent(project.getProjectId(), watch, userId));
    }

    private void insertWatch(Watch<?> watch, UserId userId) {
        try {
            writeLock.lock();
            userId2Watch.put(checkNotNull(userId), checkNotNull(watch));
            watch2UserId.put(watch, userId);
            watchObject2Watch.put(watch.getWatchedObject(), watch);
        }
        finally {
            writeLock.unlock();
        }
    }

    public void removeWatch(Watch<?> watch, UserId userId) {
        try {
            writeLock.lock();
            boolean removed = uninsertWatch(watch, userId);
            if (removed) {
                appendChange(Operation.REMOVE, watch, userId);
                project.getEventManager().postEvent(new WatchRemovedEvent(project.getProjectId(), watch, userId));
            }
        }
        finally {
            writeLock.unlock();
        }
    }

    private boolean uninsertWatch(Watch<?> watch, UserId userId) {
        boolean removed;
        try {
            writeLock.lock();
            removed = userId2Watch.remove(checkNotNull(userId), checkNotNull(watch));
            watch2UserId.remove(watch, userId);
            watchObject2Watch.remove(watch.getWatchedObject(), watch);
        }
        finally {
            writeLock.unlock();
        }
        return removed;
    }

    public void clearWatches(UserId userId) {
        try {
            writeLock.lock();
            userId2Watch.removeAll(checkNotNull(userId));
        }
        finally {
            writeLock.unlock();
        }
    }

    @Override
    public Set<Watch<?>> getDirectWatches(Object watchedObject, UserId userId) {
        try {
            readLock.lock();
            return new HashSet<Watch<?>>(watchObject2Watch.get(watchedObject));
        }
        finally {
            readLock.unlock();
        }
    }

    @Override
    public boolean hasEntityBasedWatch(OWLEntity entity, UserId userId) {
        try {
            readLock.lock();
            for (Watch<?> watch : userId2Watch.get(userId)) {
                if (watch instanceof EntityBasedWatch && ((EntityBasedWatch) watch).getEntity().equals(entity)) {
                    return true;
                }
            }
            return false;
        }
        finally {
            readLock.unlock();
        }
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    private void handleFrameChanged(OWLEntity entity) {
        try {
            readLock.lock();
            List<Watch<?>> watches = new ArrayList<Watch<?>>();
            watches.addAll(watchObject2Watch.get(entity));
            for (OWLEntity anc : getRelatedWatchEntities(entity)) {
                watches.addAll(watchObject2Watch.get(anc));
            }
            for (Watch<?> watch : watches) {
                for (UserId userId : watch2UserId.get(watch)) {
                    // Dispatch
                    fireWatch(watch, userId, entity);
                }
            }
        }
        finally {
            readLock.unlock();
        }
    }


    private Set<? extends OWLEntity> getRelatedWatchEntities(OWLEntity entity) {
        return entity.accept(new OWLEntityVisitorExAdapter<Set<? extends OWLEntity>>() {
            @Override
            protected Set<? extends OWLEntity> getDefaultReturnValue(OWLEntity object) {
                return Collections.emptySet();
            }

            @Override
            public Set<? extends OWLEntity> visit(OWLClass desc) {
                return project.getClassHierarchyProvider().getAncestors(desc);
            }

            @Override
            public Set<? extends OWLEntity> visit(OWLDataProperty property) {
                return project.getDataPropertyHierarchyProvider().getAncestors(property);
            }

            @Override
            public Set<? extends OWLEntity> visit(OWLObjectProperty property) {
                return project.getObjectPropertyHierarchyProvider().getAncestors(property);
            }

            @Override
            public Set<? extends OWLEntity> visit(OWLNamedIndividual individual) {
                Set<OWLClassExpression> types = individual.getTypes(project.getRootOntology().getImportsClosure());
                Set<OWLClass> result = new HashSet<OWLClass>();
                for(OWLClassExpression ce : types) {
                    if(!ce.isAnonymous()) {
                        result.addAll(project.getClassHierarchyProvider().getAncestors(ce.asOWLClass()));
                    }
                }
                return result;
            }
        });
    }

    private void fireWatch(final Watch<?> watch, final UserId userId, final OWLEntity entity) {

        emailExecutor.submit(new Runnable() {
            @Override
            public void run() {
                final User user = MetaProjectManager.getManager().getMetaProject().getUser(userId.getUserName());
                final String email = user.getEmail();
                if (email == null) {
                    return;
                }

                final String displayName = "watched project";
                final String emailSubject = String.format("Changes made in %s by %s", displayName, user.getName());
                String message = "\nChanges were made to " + entity.getEntityType().getName() + " " + project.getRenderingManager().getBrowserText(entity) + " " + entity.getIRI().toQuotedString();
                message = message + (" on " + new Date() + "\n\n");
                message = message + "You can view this " + entity.getEntityType().getName() + " at the link below:";
                StringBuilder directLinkBuilder = new StringBuilder();
                directLinkBuilder.append("http://");
                directLinkBuilder.append(WebProtegeProperties.get().getApplicationHostName());
                directLinkBuilder.append("#Edit:projectId=");
                directLinkBuilder.append(project.getProjectId().getId());
                directLinkBuilder.append(";tab=ClassesTab&id=");
                directLinkBuilder.append(URLEncoder.encode(entity.getIRI().toString()));
                message += "\n" + directLinkBuilder.toString();
                App.get().getMailManager().sendMail(email, emailSubject, message);

            }
        });
    }

    @Override
    public void dispose() {
    }

    private void readWatches() {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(watchFile), "utf-8"));
            String line;
            while((line = bufferedReader.readLine()) != null) {
                int pos = line.indexOf(",");
                String opName = line.substring(0, pos);
                String watchTypeName = line.substring(pos + 1, pos = line.indexOf(",", pos + 1));
                String entityTypeName = line.substring(pos + 1, pos = line.indexOf(",", pos + 1));
                String iri = line.substring(pos + 2, pos = line.indexOf(">,"));
                String userName = line.substring(pos + 2);
                OWLEntity entity = parseEntity(entityTypeName, iri);
                final Watch<?> watch;
                if(ENTITY_FRAME_WATCH_NAME.equals(watchTypeName)) {
                    watch = new EntityFrameWatch(entity);
                }
                else {
                    watch = new HierarchyBranchWatch(entity);
                }
                final UserId userId = UserId.getUserId(userName);
                if(opName.equals(Operation.ADD.name())) {
                    insertWatch(watch, userId);
                }
                else {
                    uninsertWatch(watch, userId);
                }
            }
            bufferedReader.close();
        }
        catch (IOException e) {
            WebProtegeLoggerManager.get(WatchManagerImpl.class).severe(e);
        }

    }

    private OWLEntity parseEntity(String entityTypeName, String iri) {
        OWLEntity entity;
        if(entityTypeName.equals(EntityType.CLASS.getName())) {
            entity = project.getDataFactory().getOWLClass(IRI.create(iri));
        }
        else if(entityTypeName.equals(EntityType.OBJECT_PROPERTY.getName())) {
            entity = project.getDataFactory().getOWLObjectProperty(IRI.create(iri));
        }
        else if(entityTypeName.equals(EntityType.DATA_PROPERTY.getName())) {
            entity = project.getDataFactory().getOWLObjectProperty(IRI.create(iri));
        }
        else if(entityTypeName.equals(EntityType.ANNOTATION_PROPERTY.getName())) {
            entity = project.getDataFactory().getOWLObjectProperty(IRI.create(iri));
        }
        else if(entityTypeName.equals(EntityType.NAMED_INDIVIDUAL.getName())) {
            entity = project.getDataFactory().getOWLObjectProperty(IRI.create(iri));
        }
        else if(entityTypeName.equals(EntityType.DATATYPE.getName())) {
            entity = project.getDataFactory().getOWLObjectProperty(IRI.create(iri));
        }
        else {
            throw new RuntimeException("Invalid entity type: " + entityTypeName);
        }
        return entity;
    }

    private synchronized void appendChange(Operation operation, Watch<?> watch, UserId userId) {
        try {
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(watchFile, true)));
            pw.print(operation);
            pw.print(",");
            if(watch instanceof EntityFrameWatch) {
                pw.print(ENTITY_FRAME_WATCH_NAME);
                pw.print(",");
                final EntityFrameWatch entityWatch = (EntityFrameWatch) watch;
                pw.print(entityWatch.getEntity().getEntityType().getName());
                pw.print(",");
                pw.print((entityWatch.getEntity().getIRI().toQuotedString()));
            }
            else if(watch instanceof HierarchyBranchWatch) {
                pw.print(HIERARCHY_BRANCH_WATCH_NAME);
                pw.print(",");
                final HierarchyBranchWatch entityWatch = (HierarchyBranchWatch) watch;
                pw.print(entityWatch.getEntity().getEntityType().getName());
                pw.print(",");
                pw.print((entityWatch.getEntity().getIRI().toQuotedString()));
            }
            else {
                throw new RuntimeException("Unknown watch type: " + watch);
            }
            pw.print(",");
            pw.print(userId.getUserName());
            pw.println();
            pw.close();
        }
        catch (IOException e) {
            WebProtegeLoggerManager.get(WatchManagerImpl.class).severe(e);
        }
    }


    private enum Operation {
        ADD,
        REMOVE
    }
}
TOP

Related Classes of edu.stanford.bmir.protege.web.server.watches.WatchManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.