package edu.asu.spring.quadriga.rest; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.security.Principal; import java.util.Iterator; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.stream.StreamSource; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.exception.MethodInvocationException; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.xml.sax.SAXException; import edu.asu.spring.quadriga.accesschecks.IWSSecurityChecker; import edu.asu.spring.quadriga.aspects.annotations.AccessPolicies; import edu.asu.spring.quadriga.aspects.annotations.CheckedElementType; import edu.asu.spring.quadriga.aspects.annotations.ElementAccessPolicy; import edu.asu.spring.quadriga.aspects.annotations.RestAccessPolicies; import edu.asu.spring.quadriga.domain.IUser; import edu.asu.spring.quadriga.domain.dictionary.IDictionary; import edu.asu.spring.quadriga.domain.dictionary.IDictionaryItems; import edu.asu.spring.quadriga.domain.factories.IRestVelocityFactory; import edu.asu.spring.quadriga.domain.factory.dictionary.IDictionaryFactory; import edu.asu.spring.quadriga.domain.impl.dictionarylist.DictionaryItem; import edu.asu.spring.quadriga.domain.impl.dictionarylist.DictionaryItemList; import edu.asu.spring.quadriga.domain.impl.dictionarylist.QuadrigaDictDetailsReply; import edu.asu.spring.quadriga.domain.workbench.IProjectDictionary; import edu.asu.spring.quadriga.domain.workspace.IWorkspaceDictionary; import edu.asu.spring.quadriga.exceptions.QuadrigaAccessException; import edu.asu.spring.quadriga.exceptions.QuadrigaException; import edu.asu.spring.quadriga.exceptions.QuadrigaStorageException; import edu.asu.spring.quadriga.exceptions.RestException; import edu.asu.spring.quadriga.service.IRestMessage; import edu.asu.spring.quadriga.service.IUserManager; import edu.asu.spring.quadriga.service.dictionary.IDictionaryManager; import edu.asu.spring.quadriga.service.workbench.IProjectDictionaryManager; import edu.asu.spring.quadriga.service.workspace.IWorkspaceDictionaryManager; import edu.asu.spring.quadriga.web.login.RoleNames; /** * Controller for dictionary related rest apis exposed to other clients * * @author SatyaSwaroop Boddu * @author LohithDwaraka * */ @Controller public class DictionaryRestController { private static final Logger logger = LoggerFactory.getLogger(DictionaryRestController.class); @Autowired private IWorkspaceDictionaryManager workspaceDictionaryManager; @Autowired private IWSSecurityChecker checkWSSecurity; @Autowired private IUserManager usermanager; @Autowired private IRestMessage errorMessageRest; @Autowired private IDictionaryManager dictionaryManager; @Autowired private IDictionaryFactory dictionaryFactory; @Autowired private IRestVelocityFactory restVelocityFactory; @Autowired @Qualifier("updateFromWordPowerURLPath") private String updateFromWordPowerURLPath; @Autowired @Qualifier("wordPowerURL") private String wordPowerURL; @Autowired private IProjectDictionaryManager projectDictionaryManager; /** * Rest interface for the List Dictionary for the userId * http://<<URL>:<PORT>>/quadriga/rest/dictionaries * http://localhost:8080/quadriga/rest/dictionaries * * @author Lohith Dwaraka * @param userId * @param model * @return * @throws RestException */ @RequestMapping(value = "rest/dictionaries", method = RequestMethod.GET, produces = "application/xml") public ResponseEntity<String> listDictionaries(ModelMap model, Principal principal, HttpServletRequest req) throws RestException { UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); try { VelocityEngine engine = restVelocityFactory.getVelocityEngine(); engine.init(); List<IDictionary> dictionaryList = dictionaryManager.getDictionariesList(user.getUsername()); Template template = engine.getTemplate("velocitytemplates/dictionarylist.vm"); VelocityContext context = new VelocityContext(); context.put("list", dictionaryList); context.put("url", ServletUriComponentsBuilder.fromContextPath(req).toUriString()); StringWriter writer = new StringWriter(); template.merge(context, writer); return new ResponseEntity<String>(writer.toString(), HttpStatus.OK); } catch (ResourceNotFoundException e) { throw new RestException(404, e); } catch (ParseErrorException e) { throw new RestException(500, e); } catch (MethodInvocationException e) { throw new RestException(500, e); } catch (Exception e) { throw new RestException(500, e); } } /** * Rest interface for the List Dictionary for the userId * http://<<URL>:<PORT>>/quadriga/rest/workspace/<workspaceID>/dictionaries * http://localhost:8080/quadriga/rest/workspace/WS_23048829469196290/ * dictionaries * * @author Lohith Dwaraka * @param userId * @param model * @return * @throws RestException */ @RequestMapping(value = "rest/workspace/{workspaceId}/dictionaries", method = RequestMethod.GET, produces = "application/xml") public ResponseEntity<String> listWorkspaceDictionaries(@PathVariable("workspaceId") String workspaceId, ModelMap model, Principal principal, HttpServletRequest req) throws RestException { UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); try { VelocityEngine engine = restVelocityFactory.getVelocityEngine(); engine.init(); List<IWorkspaceDictionary> dictionaryList = workspaceDictionaryManager.listWorkspaceDictionary(workspaceId, user.getUsername()); Template template = engine.getTemplate("velocitytemplates/workspacedictionarylist.vm"); VelocityContext context = new VelocityContext(); context.put("url", ServletUriComponentsBuilder.fromContextPath(req).toUriString()); context.put("list", dictionaryList); StringWriter writer = new StringWriter(); template.merge(context, writer); return new ResponseEntity<String>(writer.toString(), HttpStatus.OK); } catch (ResourceNotFoundException e) { throw new RestException(404, e); } catch (ParseErrorException e) { throw new RestException(500, e); } catch (MethodInvocationException e) { throw new RestException(500, e); } catch (Exception e) { throw new RestException(500, e); } } /** * Rest interface to get dictionaries related to workspace * http://<<URL>:<PORT * >>/quadriga/auth/rest/workspace/<workspaceid>/dictionaries.json * http://<<URL>:<PORT>>/quadriga/auth/rest/workspace/e23a8585-20bc- * 458e-ab7d-c758962b11aa/dictionaries.json * * * @author Ajay Modi & Bharath Srikantan * @param req * @param model * @param principal * @return */ @AccessPolicies({ @ElementAccessPolicy(type = CheckedElementType.WORKSPACE, paramIndex = 2, userRole = { RoleNames.ROLE_WORKSPACE_COLLABORATOR_ADMIN, RoleNames.ROLE_WORKSPACE_COLLABORATOR_CONTRIBUTOR }) }) @RequestMapping(value = "auth/rest/workspace/{workspaceid}/dictionaries.json", method = RequestMethod.GET, produces = "application/json") public ResponseEntity<String> listWorkspaceDictionaryJson(HttpServletRequest req, @PathVariable("workspaceid") String workspaceId, Model model, Principal principal) { String userId = principal.getName(); List<IWorkspaceDictionary> dicitonaryList = null; try { dicitonaryList = workspaceDictionaryManager.listWorkspaceDictionary(workspaceId, userId); } catch (QuadrigaStorageException e) { logger.error("QuadrigaStorageException:", e); return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } JSONArray ja = new JSONArray(); if (dicitonaryList != null) { for (IWorkspaceDictionary dictionary : dicitonaryList) { JSONObject j = new JSONObject(); try { j.put("id", dictionary.getDictionary().getDictionaryId()); j.put("name", dictionary.getDictionary().getDictionaryName()); ja.put(j); } catch (JSONException e) { logger.error("JSONException:", e); return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } } return new ResponseEntity<String>(ja.toString(), HttpStatus.OK); } /** * Rest interface for the List Dictionary items for the dictionary Id * http://<<URL>:<PORT>>/quadriga/rest/dictionaryDetails/{DictionaryID} * http://localhost:8080/quadriga/rest/dictionaryDetails/68 * * @author Lohith Dwaraka * @param dictionaryId * @param model * @return * @throws RestException */ @RequestMapping(value = "rest/dictionaryDetails/{dictionaryId}", method = RequestMethod.GET, produces = "application/xml") public ResponseEntity<String> listDictionaryItems(@PathVariable("dictionaryId") String dictionaryId, ModelMap model, HttpServletRequest req) throws RestException { UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); // TODO details not getting retrieved try { VelocityEngine engine = restVelocityFactory.getVelocityEngine(); engine.init(); logger.debug("Getting dictionary items list for dictionary id : " + dictionaryId); List<IDictionaryItems> dictionaryItemsList = dictionaryManager.getDictionaryItems(dictionaryId); if (dictionaryItemsList == null) { throw new RestException(404); } Template template = engine.getTemplate("velocitytemplates/dictionaryitemslist.vm"); VelocityContext context = new VelocityContext(); context.put("url", ServletUriComponentsBuilder.fromContextPath(req).toUriString()); String updateFromWordPowerURL = wordPowerURL; context.put("list", dictionaryItemsList); context.put("wordPowerURL", updateFromWordPowerURL); context.put("path", updateFromWordPowerURLPath); StringWriter writer = new StringWriter(); template.merge(context, writer); return new ResponseEntity<String>(writer.toString(), HttpStatus.OK); } catch (ResourceNotFoundException e) { throw new RestException(404, e); } catch (ParseErrorException e) { throw new RestException(500, e); } catch (MethodInvocationException e) { throw new RestException(500, e); } catch (Exception e) { throw new RestException(500, e); } } /** * Rest interface add a new dictionary with a list of dictionary * http://<<URL>:<PORT>>/quadriga/rest/workspace/<workspaceid>/createdict * http://localhost:8080/quadriga/rest/workspace/WS_22992652874022949/ * createdict * * @author Lohith Dwaraka * @param userId * @param model * @return * @throws RestException * @throws QuadrigaStorageException * @throws QuadrigaAccessException * @throws Exception */ @RestAccessPolicies({ @ElementAccessPolicy(type = CheckedElementType.WORKSPACE_REST, paramIndex = 1, userRole = { RoleNames.ROLE_WORKSPACE_COLLABORATOR_ADMIN, RoleNames.ROLE_PROJ_COLLABORATOR_CONTRIBUTOR }) }) @RequestMapping(value = "rest/workspace/{workspaceId}/createdict", method = RequestMethod.POST) public ResponseEntity<String> addConceptCollectionsToWorkspace(@PathVariable("workspaceId") String workspaceId, HttpServletRequest request, HttpServletResponse response, @RequestBody String xml, @RequestHeader("Accept") String accept, ModelMap model, Principal principal) throws RestException, QuadrigaStorageException, QuadrigaAccessException { IUser user = usermanager.getUser(principal.getName()); if (!checkWSSecurity.checkIsWorkspaceExists(workspaceId)) { String errorMsg = errorMessageRest.getErrorMsg("Workspace ID : " + workspaceId + " doesn't exist", request); return new ResponseEntity<String>(errorMsg, HttpStatus.NOT_FOUND); } String dictName = request.getParameter("name"); String desc = request.getParameter("desc"); if (dictName == null || dictName.isEmpty()) { String errorMsg = errorMessageRest.getErrorMsg("Please provide dictionary name", request); return new ResponseEntity<String>(errorMsg, HttpStatus.BAD_REQUEST); } if (desc == null || desc.isEmpty()) { String errorMsg = errorMessageRest.getErrorMsg("Please provide dictionary description", request); return new ResponseEntity<String>(errorMsg, HttpStatus.BAD_REQUEST); } logger.debug("XML : " + xml); JAXBElement<QuadrigaDictDetailsReply> response1 = null; try { JAXBContext context = JAXBContext.newInstance(QuadrigaDictDetailsReply.class); Unmarshaller unmarshaller = context.createUnmarshaller(); unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); InputStream is = new ByteArrayInputStream(xml.getBytes()); response1 = unmarshaller.unmarshal(new StreamSource(is), QuadrigaDictDetailsReply.class); } catch (JAXBException e) { logger.error("Error in unmarshalling", e); String errorMsg = errorMessageRest.getErrorMsg("Error in unmarshalling", request); return new ResponseEntity<String>(errorMsg, HttpStatus.BAD_REQUEST); } QuadrigaDictDetailsReply qReply = response1.getValue(); DictionaryItemList dictList = qReply.getDictionaryItemsList(); List<DictionaryItem> dictionaryList = dictList.getDictionaryItems(); if (dictionaryList.size() < 1) { String errorMsg = errorMessageRest.getErrorMsg("Dictionary XML is not valid", request); return new ResponseEntity<String>(errorMsg, HttpStatus.BAD_REQUEST); } IDictionary dictionary = dictionaryFactory.createDictionaryObject(); dictionary.setDescription(desc); dictionary.setOwner(user); dictionary.setDictionaryName(dictName); dictionaryManager.addNewDictionary(dictionary); String dictId = dictionaryManager.getDictionaryId(dictName); Iterator<DictionaryItem> iter = dictionaryList.iterator(); while (iter.hasNext()) { DictionaryItem dicItem = iter.next(); try { dictionaryManager.addNewDictionariesItems(dictId, dicItem.getTerm(), dicItem.getUri(), dicItem.getPos(), user.getUserName()); dictionaryManager .updateDictionariesItems(dictId, dicItem.getUri(), dicItem.getTerm(), dicItem.getPos()); } catch (QuadrigaStorageException e) { logger.error("Errors in adding items", e); String errorMsg = errorMessageRest.getErrorMsg("Failed to add due to DB Error", request); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.valueOf(accept)); return new ResponseEntity<String>(errorMsg, httpHeaders, HttpStatus.INTERNAL_SERVER_ERROR); } } workspaceDictionaryManager.addWorkspaceDictionary(workspaceId, dictId, user.getUserName()); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.valueOf(accept)); return new ResponseEntity<String>(dictId, httpHeaders, HttpStatus.OK); } /** * Rest interface for uploading XML for concept collection http://<<URL>: * <PORT>>/quadriga/rest/syncdictionary/{dictionaryID} * hhttp://localhost:8080/quadriga/rest/syncdictionary/ * * @author Lohith Dwaraka * @param request * @param response * @param xml * @param accept * @return * @throws QuadrigaException * @throws IOException * @throws SAXException * @throws ParserConfigurationException * @throws JAXBException * @throws QuadrigaAccessException * @throws QuadrigaStorageException * @throws RestException */ @RestAccessPolicies({ @ElementAccessPolicy(type = CheckedElementType.DICTIONARY, paramIndex = 1, userRole = { RoleNames.ROLE_WORKSPACE_COLLABORATOR_ADMIN, RoleNames.ROLE_PROJ_COLLABORATOR_CONTRIBUTOR }) }) @RequestMapping(value = "rest/syncdictionary/{dictionaryID}", method = RequestMethod.POST) public ResponseEntity<String> syncDictionary(@PathVariable("dictionaryID") String dictionaryID, HttpServletRequest request, HttpServletResponse response, @RequestBody String xml, @RequestHeader("Accept") String accept, Principal principal) throws QuadrigaException, ParserConfigurationException, SAXException, IOException, JAXBException, QuadrigaAccessException, QuadrigaStorageException, RestException { IUser user = usermanager.getUser(principal.getName()); if (xml.equals("")) { String errorMsg = errorMessageRest.getErrorMsg("Please provide XML in body of the post request."); return new ResponseEntity<String>(errorMsg, HttpStatus.BAD_REQUEST); } logger.debug("XML : " + xml); JAXBElement<QuadrigaDictDetailsReply> response1 = null; try { JAXBContext context = JAXBContext.newInstance(QuadrigaDictDetailsReply.class); Unmarshaller unmarshaller = context.createUnmarshaller(); unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); InputStream is = new ByteArrayInputStream(xml.getBytes()); response1 = unmarshaller.unmarshal(new StreamSource(is), QuadrigaDictDetailsReply.class); } catch (JAXBException e) { logger.error("Error in unmarshalling", e); String errorMsg = errorMessageRest.getErrorMsg("Error in unmarshalling", request); return new ResponseEntity<String>(errorMsg, HttpStatus.BAD_REQUEST); } QuadrigaDictDetailsReply qReply = response1.getValue(); DictionaryItemList dictList = qReply.getDictionaryItemsList(); List<DictionaryItem> dictionaryList = dictList.getDictionaryItems(); if (dictionaryList.size() < 1) { String errorMsg = errorMessageRest.getErrorMsg("Dictionary XML is not valid", request); return new ResponseEntity<String>(errorMsg, HttpStatus.BAD_REQUEST); } Iterator<DictionaryItem> iter = dictionaryList.iterator(); while (iter.hasNext()) { DictionaryItem dicItem = iter.next(); try { dictionaryManager.addNewDictionariesItems(dictionaryID, dicItem.getTerm().trim(), dicItem.getUri() .trim(), dicItem.getPos().trim(), user.getUserName()); dictionaryManager.updateDictionariesItems(dictionaryID, dicItem.getUri(), dicItem.getTerm(), dicItem.getPos()); } catch (QuadrigaStorageException e) { logger.error("Errors in adding items", e); String errorMsg = errorMessageRest.getErrorMsg("Failed to add due to DB Error", request); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.valueOf(accept)); return new ResponseEntity<String>(errorMsg, httpHeaders, HttpStatus.INTERNAL_SERVER_ERROR); } } HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.valueOf(accept)); return new ResponseEntity<String>("Success", httpHeaders, HttpStatus.OK); } /** * Rest interface to get dictionaries related to project * http://<<URL>:<PORT>>/quadriga/auth/rest/<projectid>/dictionaries.json * http://localhost:8080/quadriga/auth/rest/PROJ_bb7ad41b-3e85-4309-b2ff-47d * 644307b9b/dictionaries.json * * * @author Ajay Modi & Bharath Srikantan * @param projectid * @param model * @param principal * @return */ @RequestMapping(value = "auth/rest/{projectid}/dictionaries.json", method = RequestMethod.GET, produces = "application/json") public ResponseEntity<String> listProjectDictionaryJson(HttpServletRequest req, @PathVariable("projectid") String projectid, Model model, Principal principal) { String userId = principal.getName(); List<IProjectDictionary> dictionaryList = null; // TODO: listProjectDictionary() is to be changed according to // mapper try { dictionaryList = projectDictionaryManager.listProjectDictionary(projectid); } catch (QuadrigaStorageException e) { // TODO Auto-generated catch block logger.error("QuadrigaStorageException:", e); return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } JSONArray ja = new JSONArray(); if (dictionaryList != null) { for (IProjectDictionary dictionary : dictionaryList) { JSONObject j = new JSONObject(); try { j.put("id", dictionary.getDictionary().getDictionaryId()); j.put("name", dictionary.getDictionary().getDictionaryName()); ja.put(j); } catch (JSONException e) { // TODO Auto-generated catch block logger.error("JSONException:", e); return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } } return new ResponseEntity<String>(ja.toString(), HttpStatus.OK); } }