/**
* OpenKM, Open Document Management System (http://www.openkm.com)
* Copyright (c) 2006-2011 Paco Avila & Josep Llort
*
* No bytes were intentionally harmed during the development of this application.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.openkm.module.direct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.PropertyDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.openkm.bean.PropertyGroup;
import com.openkm.bean.form.CheckBox;
import com.openkm.bean.form.FormElement;
import com.openkm.bean.form.Input;
import com.openkm.bean.form.Option;
import com.openkm.bean.form.Select;
import com.openkm.bean.form.SuggestBox;
import com.openkm.bean.form.TextArea;
import com.openkm.core.AccessDeniedException;
import com.openkm.core.Config;
import com.openkm.core.DatabaseException;
import com.openkm.core.JcrSessionManager;
import com.openkm.core.LockException;
import com.openkm.core.NoSuchGroupException;
import com.openkm.core.NoSuchPropertyException;
import com.openkm.core.ParseException;
import com.openkm.core.PathNotFoundException;
import com.openkm.core.RepositoryException;
import com.openkm.jcr.JCRUtils;
import com.openkm.module.PropertyGroupModule;
import com.openkm.module.base.BasePropertyGroupModule;
import com.openkm.util.FormUtils;
import com.openkm.util.UserActivity;
public class DirectPropertyGroupModule implements PropertyGroupModule {
private static Logger log = LoggerFactory.getLogger(DirectPropertyGroupModule.class);
@Override
public void addGroup(String token, String nodePath, String grpName) throws NoSuchGroupException,
LockException, PathNotFoundException, AccessDeniedException, RepositoryException,
DatabaseException {
log.debug("addGroup({}, {}, {})", new Object[] { token, nodePath, grpName });
Node documentNode = null;
Session session = null;
if (Config.SYSTEM_READONLY) {
throw new AccessDeniedException("System is in read-only mode");
}
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
documentNode = session.getRootNode().getNode(nodePath.substring(1));
BasePropertyGroupModule.addGroup(session, documentNode, grpName);
// Activity log
UserActivity.log(session.getUserID(), "ADD_PROPERTY_GROUP", documentNode.getUUID(), grpName+", "+nodePath);
} catch (javax.jcr.nodetype.NoSuchNodeTypeException e) {
log.error(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new NoSuchGroupException(e.getMessage(), e);
} catch (javax.jcr.lock.LockException e) {
log.error(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new LockException(e.getMessage(), e);
} catch (javax.jcr.PathNotFoundException e) {
log.warn(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new PathNotFoundException(e.getMessage(), e);
} catch (javax.jcr.AccessDeniedException e) {
log.warn(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new AccessDeniedException(e.getMessage(), e);
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
log.debug("addGroup: void");
}
@Override
public void removeGroup(String token, String nodePath, String grpName) throws AccessDeniedException,
NoSuchGroupException, LockException, PathNotFoundException, RepositoryException,
DatabaseException {
log.debug("removeGroup({}, {}, {})", new Object[] { token, nodePath, grpName });
Node documentNode = null;
Session session = null;
if (Config.SYSTEM_READONLY) {
throw new AccessDeniedException("System is in read-only mode");
}
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
documentNode = session.getRootNode().getNode(nodePath.substring(1));
synchronized (documentNode) {
documentNode.removeMixin(grpName);
documentNode.save();
}
// Activity log
UserActivity.log(session.getUserID(), "REMOVE_PROPERTY_GROUP", documentNode.getUUID(), grpName+", "+nodePath);
} catch (javax.jcr.nodetype.NoSuchNodeTypeException e) {
log.error(e.getMessage(), e);
throw new NoSuchGroupException(e.getMessage(), e);
} catch (javax.jcr.lock.LockException e) {
log.error(e.getMessage(), e);
throw new LockException(e.getMessage(), e);
} catch (javax.jcr.PathNotFoundException e) {
log.warn(e.getMessage(), e);
throw new PathNotFoundException(e.getMessage(), e);
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
log.debug("removeGroup: void");
}
@Override
public List<PropertyGroup> getGroups(String token, String nodePath) throws IOException, ParseException,
PathNotFoundException, RepositoryException, DatabaseException {
log.debug("getGroups({}, {})", token, nodePath);
ArrayList<PropertyGroup> ret = new ArrayList<PropertyGroup>();
Session session = null;
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
Node documentNode = session.getRootNode().getNode(nodePath.substring(1));
NodeType[] nt = documentNode.getMixinNodeTypes();
Map<PropertyGroup, List<FormElement>> pgf = FormUtils.parsePropertyGroupsForms(Config.PROPERTY_GROUPS_XML);
// Only return registered property definitions
for (int i=0; i<nt.length; i++) {
if (nt[i].getName().startsWith(PropertyGroup.GROUP+":")) {
for (Iterator<PropertyGroup> it = pgf.keySet().iterator(); it.hasNext(); ) {
PropertyGroup pg = it.next();
if (pg.getName().equals(nt[i].getName())) {
ret.add(pg);
}
}
}
}
} catch (javax.jcr.PathNotFoundException e) {
log.warn(e.getMessage(), e);
throw new PathNotFoundException(e.getMessage(), e);
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
log.debug("getGroups: {}", ret);
return ret;
}
@Override
public List<PropertyGroup> getAllGroups(String token) throws IOException, ParseException,
RepositoryException, DatabaseException {
log.debug("getAllGroups({})", token);
ArrayList<PropertyGroup> ret = new ArrayList<PropertyGroup>();
Session session = null;
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
NodeTypeManager ntm = session.getWorkspace().getNodeTypeManager();
Map<PropertyGroup, List<FormElement>> pgf = FormUtils.parsePropertyGroupsForms(Config.PROPERTY_GROUPS_XML);
// Only return registered property definitions
for (NodeTypeIterator nti = ntm.getMixinNodeTypes(); nti.hasNext();) {
NodeType nt = nti.nextNodeType();
if (nt.getName().startsWith(PropertyGroup.GROUP + ":")) {
for (Iterator<PropertyGroup> it = pgf.keySet().iterator(); it.hasNext(); ) {
PropertyGroup pg = it.next();
if (pg.getName().equals(nt.getName())) {
ret.add(pg);
}
}
}
}
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
log.debug("getAllGroups: {}", ret);
return ret;
}
@Override
public List<FormElement> getProperties(String token, String nodePath, String grpName) throws IOException,
ParseException, NoSuchGroupException, PathNotFoundException, RepositoryException,
DatabaseException {
log.debug("getProperties({}, {}, {})", new Object[] { token, nodePath, grpName });
Session session = null;
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
Map<PropertyGroup, List<FormElement>> pgfs = FormUtils.parsePropertyGroupsForms(Config.PROPERTY_GROUPS_XML);
List<FormElement> pgf = FormUtils.getPropertyGroupForms(pgfs, grpName);
Node documentNode = session.getRootNode().getNode(nodePath.substring(1));
NodeTypeManager ntm = session.getWorkspace().getNodeTypeManager();
NodeType nt = ntm.getNodeType(grpName);
PropertyDefinition[] pd = nt.getDeclaredPropertyDefinitions();
for (FormElement fe : pgf) {
for (int i=0; i < pd.length; i++) {
// Only return registered property definitions
if (fe.getName().equals(pd[i].getName())) {
try {
Property prop = documentNode.getProperty(pd[i].getName());
if (fe instanceof Select && ((Select) fe).getType().equals(Select.TYPE_MULTIPLE)
&& pd[i].isMultiple()) {
Value[] values = prop.getValues();
for (int j=0; j<values.length; j++) {
for (Option opt : ((Select) fe).getOptions()) {
if (opt.getValue().equals(values[j].getString())) {
opt.setSelected(true);
}
}
}
} else if (!pd[i].isMultiple()) {
Value value = prop.getValue();
if (fe instanceof Input) {
((Input) fe).setValue(value.getString());
} else if (fe instanceof SuggestBox) {
((SuggestBox) fe).setValue(value.getString());
} else if (fe instanceof CheckBox) {
((CheckBox) fe).setValue(Boolean.parseBoolean(value.getString()));
} else if (fe instanceof TextArea) {
((TextArea) fe).setValue(value.getString());
} else if (fe instanceof Select) {
for (Option opt : ((Select) fe).getOptions()) {
if (opt.getValue().equals(value.getString())) {
opt.setSelected(true);
}
}
} else {
throw new ParseException("Unknown property definition: " + pd[i].getName());
}
} else {
throw new ParseException("Inconsistent property definition: " + pd[i].getName());
}
} catch (javax.jcr.PathNotFoundException e) {
// Maybe the property is not found because was added after the assignment
// throw new RepositoryException("Requested property not found: "+e.getMessage());
}
}
}
}
// Activity log
UserActivity.log(session.getUserID(), "GET_PROPERTY_GROUP_PROPERTIES", documentNode.getUUID(), grpName+", "+pgf+", "+nodePath);
log.debug("getProperties: {}", pgf);
return pgf;
} catch (javax.jcr.nodetype.NoSuchNodeTypeException e) {
log.error(e.getMessage(), e);
throw new NoSuchGroupException(e.getMessage(), e);
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
}
@Override
public void setProperties(String token, String nodePath, String grpName, List<FormElement> properties)
throws IOException, ParseException, NoSuchPropertyException, NoSuchGroupException, LockException,
PathNotFoundException, AccessDeniedException, RepositoryException, DatabaseException {
log.debug("setProperties({}, {}, {}, {})", new Object[] { token, nodePath, grpName, properties });
Node documentNode = null;
Session session = null;
if (Config.SYSTEM_READONLY) {
throw new AccessDeniedException("System is in read-only mode");
}
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
NodeTypeManager ntm = session.getWorkspace().getNodeTypeManager();
NodeType nt = ntm.getNodeType(grpName);
PropertyDefinition[] pd = nt.getDeclaredPropertyDefinitions();
documentNode = session.getRootNode().getNode(nodePath.substring(1));
synchronized (documentNode) {
// Maybe the property is not found because was added after the assignment,
// so we check if there are any missing node property, and then will remove
// and add the mixing again
for (FormElement fe : properties) {
for (int i=0; i < pd.length; i++) {
if (fe.getName().equals(pd[i].getName())) {
if (documentNode.isNodeType(grpName) && !documentNode.hasProperty(pd[i].getName())) {
documentNode.removeMixin(grpName);
documentNode.addMixin(grpName);
}
}
}
}
// Now we can safely set all property values.
for (FormElement fe : properties) {
for (int i=0; i < pd.length; i++) {
// Only return registered property definitions
if (fe.getName().equals(pd[i].getName())) {
try {
BasePropertyGroupModule.setPropertyValue(documentNode, pd[i], fe);
} catch (javax.jcr.PathNotFoundException e) {
throw new RepositoryException("Requested property not found: "+e.getMessage());
}
}
}
}
}
documentNode.save();
// Activity log
UserActivity.log(session.getUserID(), "SET_PROPERTY_GROUP_PROPERTIES", documentNode.getUUID(), grpName+", "+properties+", "+nodePath);
} catch (javax.jcr.nodetype.NoSuchNodeTypeException e) {
log.error(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new NoSuchPropertyException(e.getMessage(), e);
} catch (javax.jcr.lock.LockException e) {
log.error(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new LockException(e.getMessage(), e);
} catch (javax.jcr.PathNotFoundException e) {
log.warn(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new PathNotFoundException(e.getMessage(), e);
} catch (javax.jcr.AccessDeniedException e) {
log.warn(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new AccessDeniedException(e.getMessage(), e);
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
JCRUtils.discardsPendingChanges(documentNode);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
log.debug("setProperties: void");
}
@Override
public List<FormElement> getPropertyGroupForm(String token, String grpName) throws IOException,
ParseException, RepositoryException, DatabaseException {
log.debug("getPropertyGroupForm({}, {})", token, grpName);
List<FormElement> ret = new ArrayList<FormElement>();
Session session = null;
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
NodeTypeManager ntm = session.getWorkspace().getNodeTypeManager();
NodeType nt = ntm.getNodeType(grpName);
PropertyDefinition[] pd = nt.getDeclaredPropertyDefinitions();
Map<PropertyGroup, List<FormElement>> pgf = FormUtils.parsePropertyGroupsForms(Config.PROPERTY_GROUPS_XML);
List<FormElement> tmp = FormUtils.getPropertyGroupForms(pgf, grpName);
// Only return registered property definitions
for (FormElement fe : tmp) {
for (int i=0; i < pd.length; i++) {
if (fe.getName().equals(pd[i].getName())) {
ret.add(fe);
}
}
}
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
log.debug("getPropertyGroupForm: {}", ret);
return ret;
}
@Override
public boolean hasGroup(String token, String nodePath, String grpName) throws IOException,
ParseException, PathNotFoundException, RepositoryException, DatabaseException {
log.debug("hasGroup({}, {}, {})", new Object[] { token, nodePath, grpName });
boolean ret = false;
Session session = null;
try {
if (token == null) {
session = JCRUtils.getSession();
} else {
session = JcrSessionManager.getInstance().get(token);
}
Node documentNode = session.getRootNode().getNode(nodePath.substring(1));
NodeType[] nt = documentNode.getMixinNodeTypes();
Map<PropertyGroup, List<FormElement>> pgf = FormUtils.parsePropertyGroupsForms(Config.PROPERTY_GROUPS_XML);
// Only return registered property definitions
for (int i=0; i<nt.length; i++) {
if (nt[i].getName().startsWith(PropertyGroup.GROUP+":")) {
for (Iterator<PropertyGroup> it = pgf.keySet().iterator(); it.hasNext(); ) {
PropertyGroup pg = it.next();
if (pg.getName().equals(nt[i].getName())) {
ret = true;
break;
}
}
}
}
} catch (javax.jcr.PathNotFoundException e) {
log.warn(e.getMessage(), e);
throw new PathNotFoundException(e.getMessage(), e);
} catch (javax.jcr.RepositoryException e) {
log.error(e.getMessage(), e);
throw new RepositoryException(e.getMessage(), e);
} finally {
if (token == null) JCRUtils.logout(session);
}
log.debug("hasGroup: {}", ret);
return ret;
}
}