This repository has been archived by the owner on Nov 9, 2017. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use hibernate entity listener to capture translation update and broad…
…case events
- Loading branch information
Patrick Huang
committed
Jan 29, 2014
1 parent
2dbb248
commit 8582b85
Showing
10 changed files
with
335 additions
and
19 deletions.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
zanata-war/src/main/java/org/zanata/events/TextFlowTargetUpdateContextEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.zanata.events; | ||
|
||
import org.zanata.common.LocaleId; | ||
import org.zanata.webtrans.shared.auth.EditorClientId; | ||
import org.zanata.webtrans.shared.model.TransUnitId; | ||
import org.zanata.webtrans.shared.rpc.TransUnitUpdated; | ||
import lombok.Data; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
/** | ||
* @author Patrick Huang | ||
* <a href="mailto:pahuang@redhat.com">pahuang@redhat.com</a> | ||
*/ | ||
@RequiredArgsConstructor | ||
@Getter | ||
public class TextFlowTargetUpdateContextEvent { | ||
public static final String EVENT_NAME = "org.zanata.event.TextFlowTargetUpdateContextEvent"; | ||
|
||
private final TransUnitId transUnitId; | ||
private final LocaleId localeId; | ||
private final EditorClientId editorClientId; | ||
private final TransUnitUpdated.UpdateType updateType; | ||
} |
52 changes: 52 additions & 0 deletions
52
zanata-war/src/main/java/org/zanata/webtrans/server/HibernateIntegrator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package org.zanata.webtrans.server; | ||
|
||
import org.hibernate.cfg.Configuration; | ||
import org.hibernate.engine.spi.SessionFactoryImplementor; | ||
import org.hibernate.event.service.spi.EventListenerRegistry; | ||
import org.hibernate.event.spi.EventType; | ||
import org.hibernate.event.spi.PostUpdateEventListener; | ||
import org.hibernate.integrator.spi.Integrator; | ||
import org.hibernate.metamodel.source.MetadataImplementor; | ||
import org.hibernate.service.spi.SessionFactoryServiceRegistry; | ||
import org.jboss.seam.Component; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* @author Patrick Huang <a | ||
* href="mailto:pahuang@redhat.com">pahuang@redhat.com</a> | ||
*/ | ||
@Slf4j | ||
public class HibernateIntegrator implements Integrator { | ||
@Override | ||
public void integrate(Configuration configuration, | ||
SessionFactoryImplementor sessionFactory, | ||
SessionFactoryServiceRegistry serviceRegistry) { | ||
// As you might expect, an EventListenerRegistry is the thing with which | ||
// event listeners are registered It is a | ||
// service so we look it up using the service registry | ||
|
||
final EventListenerRegistry eventListenerRegistry = | ||
serviceRegistry.getService(EventListenerRegistry.class); | ||
|
||
|
||
TranslationUpdateListener updateListener = | ||
(TranslationUpdateListener) Component | ||
.getInstance(TranslationUpdateListener.class); | ||
log.info("register event listener: {}", updateListener); | ||
eventListenerRegistry.appendListeners(EventType.POST_UPDATE, | ||
updateListener); | ||
eventListenerRegistry.appendListeners(EventType.POST_INSERT, | ||
updateListener); | ||
} | ||
|
||
@Override | ||
public void integrate(MetadataImplementor metadata, | ||
SessionFactoryImplementor sessionFactory, | ||
SessionFactoryServiceRegistry serviceRegistry) { | ||
} | ||
|
||
@Override | ||
public void disintegrate(SessionFactoryImplementor sessionFactory, | ||
SessionFactoryServiceRegistry serviceRegistry) { | ||
} | ||
} |
206 changes: 206 additions & 0 deletions
206
zanata-war/src/main/java/org/zanata/webtrans/server/TranslationUpdateListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
package org.zanata.webtrans.server; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
import javax.servlet.http.HttpSession; | ||
|
||
import org.hibernate.event.spi.PostInsertEvent; | ||
import org.hibernate.event.spi.PostInsertEventListener; | ||
import org.hibernate.event.spi.PostUpdateEvent; | ||
import org.hibernate.event.spi.PostUpdateEventListener; | ||
import org.jboss.seam.Component; | ||
import org.jboss.seam.ScopeType; | ||
import org.jboss.seam.annotations.AutoCreate; | ||
import org.jboss.seam.annotations.In; | ||
import org.jboss.seam.annotations.Name; | ||
import org.jboss.seam.annotations.Observer; | ||
import org.jboss.seam.annotations.Scope; | ||
import org.jboss.seam.contexts.Contexts; | ||
import org.jboss.seam.contexts.SessionContext; | ||
import org.jboss.seam.util.Work; | ||
import org.jboss.seam.web.ServletContexts; | ||
import org.jboss.seam.web.Session; | ||
import org.zanata.common.ContentState; | ||
import org.zanata.common.LocaleId; | ||
import org.zanata.common.ProjectType; | ||
import org.zanata.events.TextFlowTargetUpdateContextEvent; | ||
import org.zanata.model.HDocument; | ||
import org.zanata.model.HProjectIteration; | ||
import org.zanata.model.HTextFlow; | ||
import org.zanata.model.HTextFlowTarget; | ||
import org.zanata.webtrans.server.rpc.TransUnitTransformer; | ||
import org.zanata.webtrans.shared.auth.EditorClientId; | ||
import org.zanata.webtrans.shared.model.DocumentId; | ||
import org.zanata.webtrans.shared.model.ProjectIterationId; | ||
import org.zanata.webtrans.shared.model.TransUnit; | ||
import org.zanata.webtrans.shared.model.TransUnitId; | ||
import org.zanata.webtrans.shared.model.TransUnitUpdateInfo; | ||
import org.zanata.webtrans.shared.model.WorkspaceId; | ||
import org.zanata.webtrans.shared.rpc.TransUnitUpdated; | ||
import com.google.common.base.Optional; | ||
import com.google.common.base.Predicates; | ||
import com.google.common.cache.Cache; | ||
import com.google.common.cache.CacheBuilder; | ||
import com.google.common.collect.Iterables; | ||
import com.google.common.collect.Lists; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* @author Patrick Huang <a | ||
* href="mailto:pahuang@redhat.com">pahuang@redhat.com</a> | ||
*/ | ||
@Name("translationUpdateListener") | ||
@Scope(ScopeType.APPLICATION) | ||
@AutoCreate | ||
@Slf4j | ||
public class TranslationUpdateListener implements PostUpdateEventListener, | ||
PostInsertEventListener { | ||
|
||
private static final long serialVersionUID = 1L; | ||
private static final Cache<CacheKey, CacheValue> updateContext = | ||
CacheBuilder.newBuilder().softValues() | ||
.expireAfterAccess(1, TimeUnit.SECONDS).build(); | ||
|
||
@In(create = true) | ||
private TranslationWorkspaceManager translationWorkspaceManager; | ||
|
||
@In | ||
private TransUnitTransformer transUnitTransformer; | ||
|
||
@Observer(TextFlowTargetUpdateContextEvent.EVENT_NAME) | ||
public static void updateContext(TextFlowTargetUpdateContextEvent event) { | ||
updateContext | ||
.put(new CacheKey(event.getTransUnitId(), event.getLocaleId()), | ||
new CacheValue(event.getEditorClientId(), event | ||
.getUpdateType())); | ||
} | ||
|
||
@Override | ||
public void onPostUpdate(final PostUpdateEvent event) { | ||
Object entity = event.getEntity(); | ||
if (!(entity instanceof HTextFlowTarget)) { | ||
return; | ||
} | ||
|
||
try { | ||
new Work<Void>() { | ||
@Override | ||
protected Void work() throws Exception { | ||
ContentState oldContentState = | ||
(ContentState) Iterables.find( | ||
Lists.newArrayList(event.getOldState()), | ||
Predicates.instanceOf(ContentState.class)); | ||
|
||
HTextFlowTarget target = | ||
HTextFlowTarget.class.cast(event.getEntity()); | ||
publishTransUnitUpdatedEvent(target.getVersionNum() - 1, | ||
oldContentState, target); | ||
return null; | ||
} | ||
}.workInTransaction(); | ||
} catch (Exception e) { | ||
log.error("fail to publish TransUnitUpdate event", e); | ||
} | ||
|
||
} | ||
|
||
private void publishTransUnitUpdatedEvent(int previousVersionNum, | ||
ContentState previousState, HTextFlowTarget target) { | ||
LocaleId localeId = target.getLocaleId(); | ||
HTextFlow textFlow = target.getTextFlow(); | ||
HDocument document = textFlow.getDocument(); | ||
HProjectIteration projectIteration = document.getProjectIteration(); | ||
String iterationSlug = projectIteration.getSlug(); | ||
String projectSlug = projectIteration.getProject().getSlug(); | ||
ProjectType projectType = projectIteration.getProjectType(); | ||
|
||
WorkspaceId workspaceId = | ||
new WorkspaceId(new ProjectIterationId(projectSlug, | ||
iterationSlug, projectType), localeId); | ||
Optional<TranslationWorkspace> workspaceOptional = | ||
translationWorkspaceManager.tryGetWorkspace(workspaceId); | ||
if (!workspaceOptional.isPresent()) { | ||
return; | ||
} | ||
|
||
TransUnit transUnit = | ||
transUnitTransformer.transform(textFlow, target, | ||
target.getLocale()); | ||
|
||
DocumentId documentId = | ||
new DocumentId(document.getId(), document.getDocId()); | ||
int wordCount = textFlow.getWordCount().intValue(); | ||
|
||
TransUnitUpdateInfo updateInfo = | ||
createTransUnitUpdateInfo(transUnit, documentId, wordCount, | ||
previousVersionNum, previousState); | ||
|
||
CacheValue context = | ||
updateContext.getIfPresent(new CacheKey(transUnit.getId(), | ||
transUnit.getLocaleId())); | ||
TransUnitUpdated updated; | ||
if (context != null) { | ||
EditorClientId editorClientId = context.editorClientId; | ||
TransUnitUpdated.UpdateType updateType = context.updateType; | ||
updated = | ||
new TransUnitUpdated(updateInfo, editorClientId, updateType); | ||
log.debug("about to publish trans unit updated event {}", updated); | ||
} else if (ServletContexts.instance().getRequest() != null) { | ||
|
||
String sessionId = ServletContexts.instance().getRequest().getSession() | ||
.getId(); | ||
EditorClientId editorClientId = new EditorClientId(sessionId, -1); | ||
updated = new TransUnitUpdated(updateInfo, editorClientId, | ||
TransUnitUpdated.UpdateType.NonEditorSave); | ||
} else { | ||
updated = new TransUnitUpdated(updateInfo, new EditorClientId("unknown", -1), | ||
TransUnitUpdated.UpdateType.NonEditorSave); | ||
} | ||
workspaceOptional.get().publish(updated); | ||
} | ||
|
||
private static TransUnitUpdateInfo createTransUnitUpdateInfo( | ||
TransUnit transUnit, DocumentId documentId, int wordCount, | ||
int previousVersionNum, ContentState previousState) { | ||
return new TransUnitUpdateInfo(true, true, documentId, transUnit, | ||
wordCount, previousVersionNum, previousState, null); | ||
} | ||
|
||
@Override | ||
public void onPostInsert(final PostInsertEvent event) { | ||
Object entity = event.getEntity(); | ||
if (!(entity instanceof HTextFlowTarget)) { | ||
return; | ||
} | ||
try { | ||
new Work<Void>() { | ||
|
||
@Override | ||
protected Void work() throws Exception { | ||
HTextFlowTarget target = | ||
HTextFlowTarget.class.cast(event.getEntity()); | ||
publishTransUnitUpdatedEvent(0, ContentState.New, target); | ||
return null; | ||
} | ||
}.workInTransaction(); | ||
} catch (Exception e) { | ||
log.error("fail to publish TransUnitUpdate event", e); | ||
} | ||
|
||
} | ||
|
||
@RequiredArgsConstructor | ||
@EqualsAndHashCode | ||
private static class CacheKey { | ||
private final TransUnitId transUnitId; | ||
private final LocaleId localeId; | ||
} | ||
|
||
@RequiredArgsConstructor | ||
private static class CacheValue { | ||
private final EditorClientId editorClientId; | ||
private final TransUnitUpdated.UpdateType updateType; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.