DocMirroringServiceV9.java
package sk.iway.iwcm.components.structuremirroring;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import sk.iway.iwcm.Constants;
import sk.iway.iwcm.LabelValueDetails;
import sk.iway.iwcm.Logger;
import sk.iway.iwcm.PkeyGenerator;
import sk.iway.iwcm.RequestBean;
import sk.iway.iwcm.SetCharacterEncodingFilter;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.database.ComplexQuery;
import sk.iway.iwcm.database.Mapper;
import sk.iway.iwcm.database.SimpleQuery;
import sk.iway.iwcm.doc.DocDB;
import sk.iway.iwcm.doc.DocDetails;
import sk.iway.iwcm.doc.GroupDetails;
import sk.iway.iwcm.doc.GroupsDB;
import sk.iway.iwcm.editor.service.EditorService;
import sk.iway.iwcm.editor.service.GroupsService;
import sk.iway.iwcm.i18n.Prop;
import sk.iway.iwcm.system.spring.NullAwareBeanUtils;
import sk.iway.iwcm.system.spring.events.WebjetEventType;
import sk.iway.iwcm.system.translation.TranslationService;
/**
* Zabezpecuje zrkadlenie web stranky podla sync_id v databaze
* EUSTREAMNW-84
*/
public class DocMirroringServiceV9 {
public void handleDocSave(DocDetails doc, WebjetEventType type) {
if (MirroringService.isEnabled(doc.getGroupId())==false) return;
Logger.debug(DocMirroringServiceV9.class, "handleDocSave DOC type=" + type + ", doc=" + doc + " thread="+Thread.currentThread().getName());
GroupsDB groupsDB = GroupsDB.getInstance();
DocDB docDB = DocDB.getInstance();
Prop prop = Prop.getInstance();
if ("Nový podadresár".equals(doc.getTitle()) || prop.getText("editor.dir.new_dir").equals(doc.getTitle())) return;
//editor form nema nastavene syncId, takze musime nastavit podla existujucej stranky v DB
if (doc.getDocId()>0) {
doc.setSyncId(getSyncId(doc.getDocId()));
}
if (type == WebjetEventType.ON_START) {
if (doc.getSyncId()<1) {
//jedna sa o novy adresar, vygenerujeme mu syncId
doc.setSyncId(PkeyGenerator.getNextValue("structuremirroring"));
}
} else if (type == WebjetEventType.AFTER_SAVE) {
int autoTranslatorUserId = getAutoTranslatorUserId();
if (doc.getSyncId()>1) {
//najdi k tomu mirror verziu
List<DocDetails> syncedDocs = getDocBySyncId(doc.getSyncId(), doc.getDocId());
List<GroupDetails> mappedGroupsList = MirroringService.getMappingForGroup(doc.getGroupId());
List<GroupDetails> mappedGroupsListNotExisting = new ArrayList<>();
if (mappedGroupsList.size()>syncedDocs.size()) {
//there is new mapping group created in allready synced groups, we must create missing one
for (GroupDetails mappedGroup : mappedGroupsList) {
boolean containGroup = false;
for (DocDetails syncedDoc : syncedDocs) {
if (mappedGroup.getGroupId()==syncedDoc.getGroupId()) {
//ok, this group is allready synced
containGroup = true;
break;
}
}
if (containGroup==false) mappedGroupsListNotExisting.add(mappedGroup);
}
mappedGroupsList = mappedGroupsListNotExisting;
}
if (syncedDocs.isEmpty() || mappedGroupsListNotExisting.isEmpty()==false) {
//este neexistuje mirror doc, musime vytvorit novy (kopiu)
//este neexistuje, musime vytvorit novu grupu (kopiu)
if (MirroringService.isEnabled(doc.getGroupId())==false) return;
GroupDetails group = groupsDB.getGroup(doc.getGroupId());
//vytvor kopie adresara v ostatnych mapovanych adresaroch
TranslationService translator = new TranslationService(GroupMirroringServiceV9.getLanguage(group), null);
for (GroupDetails mappedGroup : mappedGroupsList) {
translator.setToLanguage(GroupMirroringServiceV9.getLanguage(mappedGroup));
String translatedTitle = translator.translate(doc.getTitle());
DocDetails existing = docDB.getDocByTitle(translatedTitle, mappedGroup.getGroupId());
if (existing != null) {
if (existing.getSyncId()==doc.getSyncId()) {
//uz existuje, takze toto je len mirror
continue;
}
//uz existuje, nema nastavene syncId, takze ho nastavime
if (existing.getSyncId()<1) {
existing.setSyncId(doc.getSyncId());
existing.setSortPriority(doc.getSortPriority());
DocDB.saveDoc(existing, false);
continue;
}
}
DocDetails mirror = new DocDetails();
NullAwareBeanUtils.copyProperties(doc, mirror);
mirror.setDocId(-1);
if (Constants.getBoolean("structureMirroringDisabledOnCreate")) mirror.setAvailable(false);
mirror.setGroupId(mappedGroup.getGroupId());
mirror.setSyncId(doc.getSyncId());
if (autoTranslatorUserId > 0) mirror.setAuthorId(autoTranslatorUserId);
tranlateDoc(doc, mirror, translator);
//CloneStructure - keepVirtualPath
RequestBean rb = SetCharacterEncodingFilter.getCurrentRequestBean();
boolean keepVirtualPath = "true".equals(rb.getParameter("keepVirtualPath"));
if(keepVirtualPath) {
int srcGroupId = Tools.getIntValue(rb.getParameter("srcGroupId"), -1);
int destGroupId = Tools.getIntValue(rb.getParameter("destGroupId"), -1);
if (srcGroupId > 0 && destGroupId > 0) {
//get source group URL prefixes
String srcGroupPath = DocDB.getGroupDiskPath(groupsDB.getGroupsAll(), srcGroupId);
//get destination group URL prefixes
String destGroupPath = DocDB.getGroupDiskPath(groupsDB.getGroupsAll(), destGroupId);
//remove source prefix path and replace it with destination prefix path, if not found, append it
String virtualPath = doc.getVirtualPath();
if(virtualPath.startsWith(srcGroupPath)) {
virtualPath = virtualPath.substring(srcGroupPath.length());
}
virtualPath = destGroupPath + virtualPath;
//fix double slashes
virtualPath = Tools.replace(virtualPath, "//", "/");
mirror.setVirtualPath(virtualPath);
}
}
//Save created mirror DOC
DocDB.saveDoc(mirror, false);
//nastav hlavnu stranku adresara
if (mappedGroup.getDefaultDocId()<1) {
GroupDetails groupToSave = groupsDB.getGroup(mappedGroup.getGroupId());
groupToSave.setDefaultDocId(mirror.getDocId());
groupsDB.setGroup(groupToSave, false);
}
MirroringService.forceReloadTree();
}
}
if (syncedDocs.size()>0) {
//uz existuje, skontroluj ostatne kopie ci sa nepresunuli a podobne
//overenie zmeny parent adresara
GroupDetails group = groupsDB.getGroup(doc.getGroupId());
if (group != null) {
List<GroupDetails> syncedGroups = GroupMirroringServiceV9.getGroupsBySyncId(group.getSyncId(), group.getGroupId());
//ok mame zoznam parent adresarov, over ci su mapovane spravne
for (DocDetails syncedDoc : syncedDocs) {
GroupDetails syncedGroup = groupsDB.getGroup(syncedDoc.getGroupId());
GroupDetails syncedCorrectGroup = MirroringService.selectMappedGroup(syncedGroup, syncedGroups);
if (syncedCorrectGroup != null) {
//porovnaj IDecko voci aktualnemu parentu
if (syncedGroup.getGroupId()!=syncedCorrectGroup.getGroupId()) {
Logger.debug(DocMirroringServiceV9.class, "NESEDI PARENT GROUP, syncedGroup="+syncedGroup.toString()+" syncedCorrectGroup="+syncedCorrectGroup.toString());
//presun web stranku do spravneho adresara
DocDetails docToSave = docDB.getDoc(syncedDoc.getDocId());
docToSave.setGroupId(syncedCorrectGroup.getGroupId());
docToSave.setAuthorId(doc.getAuthorId());
DocDB.saveDoc(docToSave, false);
MirroringService.forceReloadTree();
}
}
}
}
//overenie sort priority
for (DocDetails syncedDoc : syncedDocs) {
if (syncedDoc.getSortPriority()!=doc.getSortPriority()) {
Logger.debug(DocMirroringServiceV9.class, "NESEDI SORT PRIORITY, syncedDoc="+syncedDoc.getTitle()+" "+syncedDoc.getDocId()+" sort="+syncedDoc.getSortPriority()+" doc="+doc.getTitle()+" "+doc.getDocId()+" sort="+doc.getSortPriority());
DocDetails docToSave = docDB.getDoc(syncedDoc.getDocId());
docToSave.setSortPriority(doc.getSortPriority());
docToSave.setAuthorId(doc.getAuthorId());
DocDB.saveDoc(docToSave, false);
MirroringService.forceReloadTree();
}
}
//Set same, but translated data text to syncedDoc's
for (DocDetails syncedDoc : syncedDocs) {
//Indicate if we will translate body (data) of doc
boolean doTranslate = false;
if(autoTranslatorUserId > 0) { //auto translator exist in DB
//Check that he is the one who made the change (do autoTranslate)
if(autoTranslatorUserId == syncedDoc.getAuthorId())
doTranslate = true;
} else { //auto translator DOES NOT exist in DB
//Decide by available status, doTranslate only if available = false
doTranslate = !syncedDoc.isAvailable();
}
if(doTranslate) {
//Get mapped group of syncedDoc
GroupDetails mappedGroup = groupsDB.getGroup(syncedDoc.getGroupId());
//Translate data of changed doc
TranslationService translator = new TranslationService(GroupMirroringServiceV9.getLanguage(group), GroupMirroringServiceV9.getLanguage(mappedGroup));
DocDetails docToSave = docDB.getDoc(syncedDoc.getDocId());
if (autoTranslatorUserId>0) docToSave.setAuthorId(autoTranslatorUserId);
tranlateDoc(doc, docToSave, translator);
DocDB.saveDoc(docToSave, false);
if(GroupsService.canSyncTitle(docToSave.getDocId(), mappedGroup.getGroupId()))
{
DocDB.changeGroupTitle(docToSave.getGroupId(), docToSave.getDocId(), docToSave.getTitle(), true);
}
MirroringService.forceReloadTree();
}
}
}
}
} else if (type == WebjetEventType.ON_DELETE) {
//musi byt ON_DELETE, pretoze AFTER je uz v kosi
if (doc.getSyncId()>1) {
//najdi k tomu mirror verzie
List<DocDetails> syncedDocs = getDocBySyncId(doc.getSyncId(), doc.getDocId());
for (DocDetails syncedDoc : syncedDocs) {
Logger.debug(DocMirroringServiceV9.class, "MAZEM, syncedDoc="+syncedDoc.getTitle()+" "+syncedDoc.getDocId()+" doc="+doc.getTitle()+" "+doc.getDocId());
EditorService editorService = Tools.getSpringBean("editorService", EditorService.class);
editorService.deleteWebpage(syncedDoc, false);
//DeleteServlet.deleteDoc(null, syncedDoc.getDocId(), false);
MirroringService.forceReloadTree();
}
}
}
}
/**
* Translate doc fields like title, navbar, data
* @param source - source doc (translated from)
* @param doc - target doc
* @param translator
*/
private static void tranlateDoc(DocDetails source, DocDetails doc, TranslationService translator) {
doc.setTitle(translator.translate(source.getTitle()));
doc.setNavbar(translator.translate(source.getNavbar()));
//regenerate URL based on title
doc.setVirtualPath("");
doc.setData(translator.translate(source.getData()));
}
/**
* Gets the userId for autotranslations (login defined in confing structureMirroringAutoTranslatorLogin)
* @return
*/
private static int getAutoTranslatorUserId() {
//Id of auto translator user
int autoTranslatorId = -1;
//Check that there is a login set up for the autoTranslator user
if(Tools.isNotEmpty( Constants.getString("structureMirroringAutoTranslatorLogin") )) {
try {
autoTranslatorId = (new SimpleQuery()).forInt("SELECT user_id FROM users WHERE login=?", Constants.getString("structureMirroringAutoTranslatorLogin"));
} catch(IllegalStateException ex) {
//User does not exist in DB
}
}
return autoTranslatorId;
}
/**
* Ziska zoznam DocDetails podla zadaneho syncId
* @param syncId
* @param skipDocId - ak je zadane docId toto bude v zozname preskocene (napr. ostatne stranky okrem aktualnej)
* @return
*/
public static List<DocDetails> getDocBySyncId(int syncId, int skipDocId)
{
StringBuilder sql = new StringBuilder();
sql.append("SELECT ").append(DocDB.getDocumentFields()).append(" FROM documents d WHERE d.sync_id=?");
if (skipDocId>0) sql.append(" AND d.doc_id!=? ");
sql.append(" ORDER BY d.doc_id ASC");
ComplexQuery cq = new ComplexQuery();
cq.setSql(sql.toString());
if (skipDocId>0) cq.setParams(syncId, skipDocId);
else cq.setParams(syncId);
List<DocDetails> docs = cq.list(new Mapper<DocDetails>()
{
public DocDetails map(ResultSet rs) throws SQLException
{
try {
return DocDB.getDocDetails(rs, true, true);
} catch (Exception ex) {
Logger.error(DocMirroringServiceV9.class, ex);
}
return null;
}
});
GroupsDB groupsDB = GroupsDB.getInstance();
//filter groups which is not synced anymore
List<DocDetails> filtered = new ArrayList<>();
for (DocDetails doc : docs) {
List<GroupDetails> parents = groupsDB.getParentGroups(doc.getGroupId(), true);
for (GroupDetails parent : parents) {
int[] rootIds = MirroringService.getRootIds(parent.getGroupId());
if (rootIds != null) {
filtered.add(doc);
break;
}
}
}
return filtered;
}
public static int getSyncId(int docId) {
int syncId = new SimpleQuery().forInt("SELECT sync_id FROM documents WHERE doc_id=?", docId);
return syncId;
}
/**
* Vrati list inych jazykov ako je aktualne zadana stranka pre zobrazenie prepinaca jazykov
* - ak je stranka v inom jazyky dostupna vrati jej URL
* - ak nie je vrati URL homepage ineho jazyka (linka na hlavnu stranku hlavneho adresara daneho jazyka)
* @param currentDoc
* @return
*/
public static List<LabelValueDetails> getOtherLanguages(DocDetails currentDoc) {
List<LabelValueDetails> languages = new ArrayList<>();
if (currentDoc == null) return languages;
List<DocDetails> syncedDocs = getDocBySyncId(currentDoc.getSyncId(), 0);
GroupsDB groupsDB = GroupsDB.getInstance();
DocDB docDB = DocDB.getInstance();
//najdi root adresar nastavenej konfiguracie pre currentDoc
//je to taky, ktoreho parent uz nema nastavene syncId
List<GroupDetails> parentDirs = groupsDB.getParentGroups(currentDoc.getGroupId(), true);
GroupDetails mirroringRootGroup = null;
for (GroupDetails parent : parentDirs) {
if (parent.getSyncId()>0) mirroringRootGroup = parent;
}
//root sa nenasiel, asi sme v inom ako zrkadlenom adresari
if (mirroringRootGroup==null) return languages;
//vygeneruj zoznam prepinaca jazykov podla ROOT adresarov,
//ak existuje v syncedDocs stranka pre dany adresar, tak sprav odkaz na nu
//ak neexistuje (je vypnuta) tak sprav odkaz na hlavnu stranku z daneho root adresara
int[] rootIds = MirroringService.getRootIds(mirroringRootGroup.getGroupId());
for (int rootId : rootIds) {
GroupDetails group = groupsDB.getGroup(rootId);
if (group != null) {
LabelValueDetails link = new LabelValueDetails();
link.setLabel(group.getNavbarName());
DocDetails groupDefaultDoc = docDB.getBasicDocDetails(group.getDefaultDocId(), false);
if (groupDefaultDoc==null || groupDefaultDoc.isAvailable()==false) continue;
link.setValue(docDB.getDocLink(groupDefaultDoc.getDocId(), groupDefaultDoc.getExternalLink(), null));
//skus overit, ci mame linku na stranku v tomto adresari namiesto odkazu na root stranku
for (DocDetails syncedDoc : syncedDocs) {
if (syncedDoc.isAvailable()==false) continue;
GroupDetails syncedDocGroup = groupsDB.getGroup(syncedDoc.getGroupId());
if (syncedDocGroup != null) {
//ak zacina cesta syncedGroup na cestu aktualneho adresara je to spravna vetva
if (syncedDocGroup.getFullPath().startsWith(group.getFullPath())) {
link.setValue(docDB.getDocLink(syncedDoc.getDocId(), syncedDoc.getExternalLink(), null));
}
}
}
languages.add(link);
}
}
return languages;
}
}