Java tutorial
/* * Copyright (c) 2009 - 2010. School of Information Technology and Electrical * Engineering, The University of Queensland. This software is being developed * for the "Phenomics Ontoogy Driven Data Management Project (PODD)" project. * PODD is a National e-Research Architecture Taskforce (NeAT) project * co-funded by ANDS and ARCS. * * PODD 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 3 of the License, or * (at your option) any later version. * * PODD 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 PODD. If not, see <http://www.gnu.org/licenses/>. */ package podd.resources.services; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.restlet.ext.fileupload.RestletFileUpload; import org.restlet.ext.json.JsonRepresentation; import org.restlet.representation.Representation; import org.restlet.representation.Variant; import org.restlet.resource.ResourceException; import org.semanticweb.owl.model.OWLClassAssertionAxiom; import org.semanticweb.owl.model.OWLDescription; import org.semanticweb.owl.model.OWLIndividual; import org.semanticweb.owl.model.OWLOntologyChangeException; import org.semanticweb.owl.model.OWLOntologyCreationException; import podd.exception.DataAccessException; import podd.exception.EntityException; import podd.exception.RawDataHandlingException; import podd.model.entity.Entity; import podd.model.entity.PoddObject; import podd.server.authz.UserAction; import java.io.IOException; import java.net.URI; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.restlet.data.Status.CLIENT_ERROR_BAD_REQUEST; import static org.restlet.data.Status.CLIENT_ERROR_UNAUTHORIZED; import static org.restlet.data.Status.SERVER_ERROR_INTERNAL; import static org.restlet.data.Status.SUCCESS_OK; import static podd.model.audit.AuditLog.ERROR; import static podd.model.audit.AuditLog.INSUFFICIENT_ACCESS; import static podd.util.common.Constants.PODD_OBJECT_NAMESPACE; /** * @author Faith Davies * @version $Id$ */ public class CreateObjectService extends ObjectService { private static final String BLANK_NODE_ID = "#genid-"; protected String objectType; protected String blankNodeId; protected String parentRelationship; protected PoddObject parentObject; @Override protected Representation doAuthenticatedPost(Representation entity, Variant variant) throws ResourceException { Representation representation = null; initalisePoddObject(); if (null != poddConcept && null != poddObject) { URI sbjUri = URI.create(sentOntology.getURI().toString() + BLANK_NODE_ID + blankNodeId); OWLIndividual anonSbj = dataFactory.getOWLAnonymousIndividual(sbjUri); URI objectUri = URI.create(PODD_OBJECT_NAMESPACE + poddObject.getPid()); if (copyOntology(objectUri, anonSbj) && participantPopulator.populateProjectParticipants(poddObject, authenticatedUser) && consolidateObject() && addParentChildRelationship() && validateObject() && saveObject()) { // return success getResponse().setStatus(SUCCESS_OK); representation = new JsonRepresentation(jsonHelper.convertPoddObjectToReference(poddObject)); } else { // an error has occurred, rollback project participant info participantPopulator.rollbackProjectParticipants(poddObject); } } if (!errorMap.isEmpty()) { representation = new JsonRepresentation(jsonHelper.convertErrorMap(errorMap)); LOGGER.debug("Error: " + errorMap.toString()); } return representation; } private void initalisePoddObject() { try { poddConcept = createObjectHelper.getFirstEntity(conceptDao.loadByLocalName(objectType)); if (null != poddConcept && null != poddObject) { poddObject.setConcept(poddConcept); } else if (null != poddObject) { getResponse().setStatus(SERVER_ERROR_INTERNAL); errorHandler.handleError(GENERAL_MESSAGE_ID, "Concept Error", "Error loading concept with type: " + objectType + "."); } else if (null != poddConcept) { getResponse().setStatus(SERVER_ERROR_INTERNAL); errorHandler.handleError(GENERAL_MESSAGE_ID, "Object Error", "Error loading object with type: " + objectType + " - " + poddConcept + ". "); } else { getResponse().setStatus(SERVER_ERROR_INTERNAL); errorHandler.handleError(GENERAL_MESSAGE_ID, "Object Error", "Error loading object and concept " + "with type: " + objectType + ". "); } } catch (DataAccessException e) { getResponse().setStatus(SERVER_ERROR_INTERNAL); final String msg = "Error loading concept with type: " + objectType + " - " + poddConcept + ". "; errorHandler.handleException(GENERAL_MESSAGE_ID, "Concept Error", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); } } private boolean addParentChildRelationship() { try { if (null != parentObject && !parentRelationship.equals("")) { parentObject = createObjectHelper.addChildObject(parentObject, poddObject, parentRelationship); } return true; } catch (OWLOntologyChangeException e) { getResponse().setStatus(SERVER_ERROR_INTERNAL); final String msg = "Error copying ontology. "; errorHandler.handleException(poddObject.getPid(), "ontologyError", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); } catch (RawDataHandlingException e) { getResponse().setStatus(SERVER_ERROR_INTERNAL); final String msg = "Error adding parent-child relationship. "; errorHandler.handleException(poddObject.getPid(), "ontologyError", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); } return false; } protected boolean saveObject() { try { String baseUrl = getRequest().getRootRef().toString(); createObjectHelper.saveObject(poddObject, parentObject, authenticatedUser); createObjectHelper.sendNotificationEmail(poddObject, authenticatedUser, baseUrl); return true; } catch (DataAccessException e) { getResponse().setStatus(SERVER_ERROR_INTERNAL); final String msg = "Error occured while saving the object: " + poddObject.getPid(); errorHandler.handleException(poddObject.getPid(), "Saving Error", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); return false; } } @Override protected boolean authoriseGet() { if (null != authenticatedUser && errorMap.isEmpty()) { try { poddObject = createObjectHelper.createObject(objectType, authenticatedUser); Class<? extends Entity> clazz = poddObject.getClass(); return manager.decide(authenticatedUser, clazz, UserAction.CREATE, parentObject); } catch (EntityException e) { getResponse().setStatus(CLIENT_ERROR_BAD_REQUEST); final String msg = "Error determining class for object type: " + objectType + ". "; errorHandler.handleException(GENERAL_MESSAGE_ID, "Object Type Error", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); } } return false; } @Override protected Representation doUnauthenticatedGet(Variant variant) throws ResourceException { // if was have encountered any errors before validation, we want to be able to send the correct response code back to the user if (null == authenticatedUser) { getResponse().setStatus(CLIENT_ERROR_UNAUTHORIZED); final String msg = "User must be authenticated to create objects"; errorHandler.handleError(GENERAL_MESSAGE_ID, "errorMessage", msg); auditLogHelper.auditAction(INSUFFICIENT_ACCESS, authenticatedUser, this.getRequest().getResourceRef().toString(), msg); } if (!errorMap.isEmpty()) { return new JsonRepresentation(jsonHelper.convertErrorMap(errorMap)); } else { return redirectErrorStatus(CLIENT_ERROR_UNAUTHORIZED); } } @Override protected void prePostAuthorisation(Representation entity) { LOGGER.debug("Create Object Service"); errorMap = new HashMap<String, Map<String, List<String>>>(); errorHandler.setAllObjectsErrorMap(errorMap); objectType = ""; poddObject = null; poddConcept = null; parentObject = null; loadFormData(entity); if (!blankNodeId.equals("") && null != sentOntology) { objectType = getObjectTypeFromOntology(); URI sbj = URI.create(sentOntology.getURI().toString() + BLANK_NODE_ID + blankNodeId); parentObject = loadParentFromOntology(sbj); if (null != parentObject && parentRelationship.equals("")) { getResponse().setStatus(CLIENT_ERROR_BAD_REQUEST); errorHandler.handleError(GENERAL_MESSAGE_ID, "Invalid Parameters", "When the containing parent is " + "specified in the ontology the parent relationship must be set with the key: parentRelationship"); } if (null == parentObject && !parentRelationship.equals("")) { getResponse().setStatus(CLIENT_ERROR_BAD_REQUEST); errorHandler.handleError(GENERAL_MESSAGE_ID, "Invalid Parameters", "Parent relationship specified but not set with in the ontology"); } } else { if (blankNodeId.equals("")) { getResponse().setStatus(CLIENT_ERROR_BAD_REQUEST); errorHandler.handleError(GENERAL_MESSAGE_ID, "Invalid Parameters", "ObjectId must be sent in request with the key: id"); } if (null == sentOntology) { getResponse().setStatus(CLIENT_ERROR_BAD_REQUEST); errorHandler.handleError(GENERAL_MESSAGE_ID, "Invalid Parameters", "Ontology for the new object must be sent in the request with the key: ontology"); } } } private void loadFormData(Representation entity) { blankNodeId = ""; parentRelationship = ""; // FIXME: Each instance of this class is used only once, why is the following required? sentOntology = null; RestletFileUpload upload = new RestletFileUpload(new DiskFileItemFactory()); try { List<FileItem> list = upload.parseRepresentation(entity); for (FileItem item : list) { if (item.getFieldName().equals("id") && item.isFormField()) { blankNodeId = item.getString().trim(); } if (item.getFieldName().equals("parentRelationship") && item.isFormField()) { parentRelationship = item.getString().trim(); } if (item.getFieldName().equals("ontology") && !item.isFormField()) { sentOntology = ontologyHelper.populateOntology(item.getInputStream()); } } } catch (FileUploadException e) { getResponse().setStatus(SERVER_ERROR_INTERNAL); final String msg = "Error reading form data. "; errorHandler.handleException(GENERAL_MESSAGE_ID, "File Intialisation Error", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); } catch (IOException e) { getResponse().setStatus(SERVER_ERROR_INTERNAL); final String msg = "Error reading file. "; errorHandler.handleException(GENERAL_MESSAGE_ID, "File Initalisation Error", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); } catch (OWLOntologyCreationException e) { getResponse().setStatus(SERVER_ERROR_INTERNAL); final String msg = "Error creating ontology. "; errorHandler.handleException(GENERAL_MESSAGE_ID, "Ontology Creation Error", msg, e); auditLogHelper.auditAction(ERROR, authenticatedUser, "Create Object Service: " + msg, e.toString()); } } private String getObjectTypeFromOntology() { // get the object type from the ontology URI sbj = URI.create(sentOntology.getURI().toString() + BLANK_NODE_ID + blankNodeId); OWLIndividual anonSbj = dataFactory.getOWLAnonymousIndividual(sbj); for (OWLClassAssertionAxiom assertion : ontologyHelper.getClassAssertions(sentOntology, anonSbj)) { OWLDescription owlDescription = assertion.getDescription(); if (!owlDescription.isOWLThing() && owlHelper.isPoddClasses(owlDescription, null)) { return owlDescription.toString(); } } getResponse().setStatus(CLIENT_ERROR_BAD_REQUEST); errorHandler.handleError(GENERAL_MESSAGE_ID, "Invalid Ontology", "Class Assertion type must be set for blank node: " + blankNodeId); return ""; } }