/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.celements.navigation.cmd; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xwiki.model.EntityType; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.EntityReference; import com.celements.navigation.INavigationClassConfig; import com.celements.sajson.AbstractEventHandler; import com.celements.web.service.IWebUtilsService; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.objects.BaseObject; import com.xpn.xwiki.web.Utils; public class ReorderSaveHandler extends AbstractEventHandler<EReorderLiteral> { private static Log LOGGER = LogFactory.getFactory().getInstance(ReorderSaveHandler.class); private XWikiContext context; private DocumentReference parentRef; private EReorderLiteral currentCommand; private Integer currentPos; private Set<EntityReference> dirtyParents; public ReorderSaveHandler(XWikiContext context) { this.context = context; } public void closeEvent(EReorderLiteral literal) { LOGGER.debug("close event: " + literal.name()); } public void openEvent(EReorderLiteral literal) { LOGGER.debug("open event: " + literal.name()); currentCommand = literal; } public void readPropertyKey(String key) { LOGGER.debug("read property key: " + key); if (currentCommand == EReorderLiteral.PARENT_CHILDREN_PROPERTY) { String newParentFN = extractDocFN(key); DocumentReference newParentRef = convertToDocRef(newParentFN); if ((newParentRef != null) && context.getWiki().exists(newParentRef, context)) { parentRef = newParentRef; } else { parentRef = null; LOGGER.error("readPropertyKey: cannot load parentDocument [" + newParentFN + "]."); } currentPos = 0; } else { throw new IllegalStateException("readPropertyKey: expecting ParentChildren but" + " found " + currentCommand); } } DocumentReference convertToDocRef(String docFN) { if (!StringUtils.isEmpty(docFN)) { return getWebUtils().resolveDocumentReference(docFN); } return null; } String extractDocFN(String param) { if (param.split(":").length > 2) { return param.split(":")[2]; } else { return ""; } } DocumentReference getParentReference() { return parentRef; } String getParentFN() { if (parentRef != null) { return getWebUtils().getRefLocalSerializer().serialize(parentRef); } return ""; } Integer getCurrentPos() { if (currentPos != null) { return currentPos; } return 0; } /** * FOR TESTS ONLY!!! * * @param object */ void inject_ParentRef(DocumentReference newParent) { parentRef = newParent; } /** * FOR TESTS ONLY!!! * * @param object */ void inject_current(EReorderLiteral newCurrentCommand) { currentCommand = newCurrentCommand; } public void stringEvent(String value) { LOGGER.debug("string event: " + value + " with parent " + getParentFN()); if (currentCommand == EReorderLiteral.ELEMENT_ID) { String docFN = extractDocFN(value); DocumentReference docRef = convertToDocRef(docFN); if ((docRef != null) && context.getWiki().exists(docRef, context)) { try { boolean updateNeeded = false; XWikiDocument xdoc = context.getWiki().getDocument(docRef, context); if (hasDiffParentReferences(xdoc.getParentReference())) { markParentDirty(xdoc.getParentReference()); xdoc.setParentReference(getRelativeParentReference()); markParentDirty(getParentReference()); updateNeeded = true; } BaseObject menuItemObj = xdoc.getXObject(getNavClassConfig().getMenuItemClassRef( context.getDatabase())); if ((menuItemObj != null) && (menuItemObj.getIntValue( "menu_position") != getCurrentPos())) { menuItemObj.setIntValue("menu_position", getCurrentPos()); markParentDirty(xdoc.getParentReference()); updateNeeded = true; } if (updateNeeded) { context.getWiki().saveDocument(xdoc, "Restructuring", context); } } catch (XWikiException e) { LOGGER.error("readPropertyKey: cannot load document [" + docFN + "]."); } currentPos = getCurrentPos() + 1; } else { LOGGER.error("readPropertyKey: cannot load parentDocument [" + docFN + "]."); } } else { throw new IllegalStateException("stringEvent: expecting element_id but" + " found [" + currentCommand + "] with parent [" + getParentFN() + "]."); } } EntityReference getRelativeParentReference() { return getWebUtils().resolveRelativeEntityReference(getParentFN(), EntityType.DOCUMENT); } boolean hasDiffParentReferences(EntityReference parentReference) { if (getParentReference() != null) { return !getParentReference().equals(parentReference); } else if (parentReference != null) { return true; } else { return false; } } void markParentDirty(EntityReference parentRef) { getDirtyParents().add(parentRef); } public Set<EntityReference> getDirtyParents() { if (dirtyParents == null) { dirtyParents = new HashSet<EntityReference>(); } return dirtyParents; } private IWebUtilsService getWebUtils() { return Utils.getComponent(IWebUtilsService.class); } private INavigationClassConfig getNavClassConfig() { return Utils.getComponent(INavigationClassConfig.class); } }