Java tutorial
//////////////////////////////////////////////////////////// // ResourceServiceImpl.java // gooru-api // Created by Gooru on 2014 // Copyright (c) 2014 Gooru. All rights reserved. // http://www.goorulearning.org/ // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ///////////////////////////////////////////////////////////// package org.ednovo.gooru.domain.service.resource; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.commons.lang.StringUtils; import org.ednovo.gooru.application.util.AsyncExecutor; import org.ednovo.gooru.application.util.CollectionUtil; import org.ednovo.gooru.application.util.GooruImageUtil; import org.ednovo.gooru.application.util.ResourceImageUtil; import org.ednovo.gooru.application.util.TaxonomyUtil; import org.ednovo.gooru.core.api.model.ActionResponseDTO; import org.ednovo.gooru.core.api.model.AssessmentQuestion; import org.ednovo.gooru.core.api.model.Code; import org.ednovo.gooru.core.api.model.Collection; import org.ednovo.gooru.core.api.model.CollectionItem; import org.ednovo.gooru.core.api.model.Content; import org.ednovo.gooru.core.api.model.ContentProvider; import org.ednovo.gooru.core.api.model.ContentProviderAssociation; import org.ednovo.gooru.core.api.model.ContentType; import org.ednovo.gooru.core.api.model.CustomTableValue; import org.ednovo.gooru.core.api.model.FileMeta; import org.ednovo.gooru.core.api.model.License; import org.ednovo.gooru.core.api.model.Resource; import org.ednovo.gooru.core.api.model.ResourceInfo; import org.ednovo.gooru.core.api.model.ResourceMetaData; import org.ednovo.gooru.core.api.model.ResourceSource; import org.ednovo.gooru.core.api.model.ResourceType; import org.ednovo.gooru.core.api.model.SessionContextSupport; import org.ednovo.gooru.core.api.model.Sharing; import org.ednovo.gooru.core.api.model.Textbook; import org.ednovo.gooru.core.api.model.User; import org.ednovo.gooru.core.api.model.UserGroupSupport; import org.ednovo.gooru.core.api.model.UserRole; import org.ednovo.gooru.core.application.util.BaseUtil; import org.ednovo.gooru.core.application.util.CustomProperties; import org.ednovo.gooru.core.application.util.ImageUtil; import org.ednovo.gooru.core.application.util.RequestUtil; import org.ednovo.gooru.core.application.util.ResourceMetaInfo; import org.ednovo.gooru.core.cassandra.model.ResourceCio; import org.ednovo.gooru.core.cassandra.model.ResourceMetadataCo; import org.ednovo.gooru.core.constant.ConfigConstants; import org.ednovo.gooru.core.constant.ConstantProperties; import org.ednovo.gooru.core.constant.ParameterProperties; import org.ednovo.gooru.core.exception.BadRequestException; import org.ednovo.gooru.core.exception.NotFoundException; import org.ednovo.gooru.domain.cassandra.service.DashboardCassandraService; import org.ednovo.gooru.domain.cassandra.service.ResourceCassandraService; import org.ednovo.gooru.domain.service.CollectionService; import org.ednovo.gooru.domain.service.assessment.AssessmentService; import org.ednovo.gooru.domain.service.eventlogs.ResourceEventLog; import org.ednovo.gooru.domain.service.partner.CustomFieldsService; import org.ednovo.gooru.domain.service.setting.SettingService; import org.ednovo.gooru.domain.service.storage.S3ResourceApiHandler; import org.ednovo.gooru.domain.service.taxonomy.TaxonomyService; import org.ednovo.gooru.domain.service.v2.ContentService; import org.ednovo.gooru.infrastructure.messenger.IndexHandler; import org.ednovo.gooru.infrastructure.messenger.IndexProcessor; import org.ednovo.gooru.infrastructure.persistence.hibernate.BaseRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.CollectionRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.ConfigSettingRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.FeedbackRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.UserRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.assessment.AssessmentRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.content.ContentRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.customTable.CustomTableRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.resource.ResourceRepository; import org.ednovo.gooru.infrastructure.persistence.hibernate.taxonomy.TaxonomyRespository; import org.ednovo.gooru.security.OperationAuthorizer; import org.ednovo.goorucore.application.serializer.JsonDeserializer; import org.json.JSONObject; import org.restlet.data.Method; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BindException; import org.springframework.validation.Errors; import com.itextpdf.text.Document; import com.itextpdf.text.pdf.PdfCopy; import com.itextpdf.text.pdf.PdfImportedPage; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.SimpleBookmark; import com.sun.pdfview.PDFFile; @Service public class ResourceServiceImpl extends OperationAuthorizer implements ResourceService, ParameterProperties, ConstantProperties { private static final Logger LOGGER = LoggerFactory.getLogger(ResourceServiceImpl.class); @Autowired private ResourceRepository resourceRepository; @Autowired private ResourceEventLog resourceEventLog; @Autowired private ResourceParser resourceParser; @Autowired private ResourceImageUtil resourceImageUtil; @Autowired private MediaService mediaService; @Autowired private BaseRepository baseRepository; @Autowired private S3ResourceApiHandler s3ResourceApiHandler; @Autowired private IndexProcessor indexProcessor; @Autowired private CollectionUtil collectionUtil; @Autowired private ContentRepository contentRepository; @Autowired private UserRepository userRepository; @Autowired @javax.annotation.Resource(name = "resourceManager") private ResourceManager resourceManager; @Autowired private AssessmentRepository assessmentRepository; @Autowired private TaxonomyService taxonomyService; @Autowired private TaxonomyRespository taxonomyRepository; @Autowired private SettingService settingService; @Autowired private ResourceCassandraService resourceCassandraService; @Autowired private ConfigSettingRepository configSettingRepository; @Autowired private CustomFieldsService customFieldService; @Autowired private FeedbackRepository feedbackRepository; @Autowired private AsyncExecutor asyncExecutor; @Autowired private CustomTableRepository customTableRepository; @Autowired private CollectionService collectionService; @Autowired private AssessmentService assessmentService; @Autowired private ContentService contentService; @Autowired private CollectionRepository collectionRepository; @Autowired private IndexHandler indexHandler; @Autowired private DashboardCassandraService dashboardCassandraService; private static final String SHORTENED_URL_STATUS = "shortenedUrlStatus"; @Override public Resource findResourceByContentGooruId(final String gooruContentId) { final Resource resource = getResourceRepository().findResourceByContentGooruId(gooruContentId); if (resource == null) { throw new NotFoundException("resource not found ", GL0056); } resource.setRatings(this.collectionService .setRatingsObj(this.getResourceRepository().getResourceSummaryById(gooruContentId))); setContentProvider(resource); return resource; } @Override @Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public Map<String, Object> getResource(final String gooruOid) { final Resource resource = this.findResourceByContentGooruId(gooruOid); if (resource == null) { throw new NotFoundException("resource not found", GL0056); } final Map<String, Object> resourceObject = new HashMap<String, Object>(); try { resource.setViews( this.dashboardCassandraService.readAsLong(ALL_ + resource.getGooruOid(), COUNT_VIEWS)); resource.setViewCount(resource.getViewCount()); } catch (Exception e) { LOGGER.error("parser error : {}", e); } if (resource.getResourceType().getName().equalsIgnoreCase(ASSESSMENT_QUESTION)) { final AssessmentQuestion question = assessmentService.getQuestion(gooruOid); question.setCustomFieldValues( customFieldService.getCustomFieldsValuesOfResource(question.getGooruOid())); resourceObject.put(RESOURCE, question); } else { resource.setCustomFieldValues( customFieldService.getCustomFieldsValuesOfResource(resource.getGooruOid())); resourceObject.put(RESOURCE, resource); } resourceObject.put(STANDARDS, this.getCollectionService().getStandards(resource.getTaxonomySet(), false, null)); resourceObject.put(SKILLS, this.getCollectionService().getSkills(resource.getTaxonomySet())); resourceObject.put(COURSE, this.getCollectionService().getCourse(resource.getTaxonomySet())); setContentProvider(resource); return resourceObject; } @Override public Resource setContentProvider(final String gooruOid) { final Resource resource = this.getResourceRepository().findResourceByContent(gooruOid); rejectIfNull(resource, GL0056, RESOURCE); return setContentProvider(resource); } @Override public Resource setContentProvider(final Resource resource) { final List<ContentProviderAssociation> contentProviderAssociations = this.getContentRepository() .getContentProviderByGooruOid(resource.getGooruOid(), null, null); if (contentProviderAssociations != null) { final List<String> aggregator = new ArrayList<String>(); final List<String> publisher = new ArrayList<String>(); final List<String> host = new ArrayList<String>(); for (final ContentProviderAssociation contentProviderAssociation : contentProviderAssociations) { if (contentProviderAssociation.getContentProvider() != null && contentProviderAssociation.getContentProvider().getType() != null && contentProviderAssociation.getContentProvider().getType().getValue().equalsIgnoreCase( CustomProperties.ContentProviderType.PUBLISHER.getContentProviderType())) { publisher.add(contentProviderAssociation.getContentProvider().getName()); } else if (contentProviderAssociation.getContentProvider() != null && contentProviderAssociation.getContentProvider().getType() != null && contentProviderAssociation.getContentProvider().getType().getValue().equalsIgnoreCase( CustomProperties.ContentProviderType.AGGREGATOR.getContentProviderType())) { aggregator.add(contentProviderAssociation.getContentProvider().getName()); } else if (contentProviderAssociation.getContentProvider() != null && contentProviderAssociation.getContentProvider().getType() != null && contentProviderAssociation.getContentProvider().getType().getValue().equalsIgnoreCase( CustomProperties.ContentProviderType.HOST.getContentProviderType())) { host.add(contentProviderAssociation.getContentProvider().getName()); } } resource.setPublisher(publisher); resource.setAggregator(aggregator); resource.setHost(host); } return resource; } @Override public void deleteResource(final Long contentId) { getResourceRepository().remove(Resource.class, contentId); } @Override public void enrichAndAddOrUpdate(final Resource resource) { if (StringUtils.isBlank(resource.getTitle())) { enrichWithTitleAndText(resource); } String title = cleanTitle(resource.getTitle()); resource.setTitle(title); getResourceRepository().saveOrUpdate(resource); } private String cleanTitle(String title) { final List<String> stringsToRemoveList = Arrays.asList("bbc", "ks2", "read", "phet", "bitesize", "maths"); Set stringsToRemoveSet = new HashSet<String>(stringsToRemoveList); while (true) { title = StringUtils.trim(title); title = StringUtils.removeStart(title, ","); title = StringUtils.removeStart(title, "."); title = StringUtils.removeStart(title, "-"); title = StringUtils.removeStart(title, ":"); title = StringUtils.removeEnd(title, ","); title = StringUtils.removeEnd(title, "."); title = StringUtils.removeEnd(title, "-"); title = StringUtils.removeEnd(title, ":"); title = StringUtils.trim(title); String[] words = StringUtils.split(title, ": "); if (words.length > 0 && stringsToRemoveSet.contains(words[0].toLowerCase())) { title = StringUtils.removeStartIgnoreCase(title, words[0]); } else if (words.length > 0 && stringsToRemoveSet.contains(words[words.length - 1].toLowerCase())) { title = StringUtils.removeEndIgnoreCase(title, words[words.length - 1]); } else { break; } } return title; } private void enrichWithTitleAndText(final Resource resource) { final String parentUrlString = resource.getParentUrl(); List<String> possibleTitles = new ArrayList<String>(); List<String> possibleTexts = new ArrayList<String>(); // get possible title and text from url ResourceParser.TitleAndText textAndTitle = this.getResourceParser().getTextAndTitle(resource.getUrl()); possibleTitles.add(textAndTitle.getTitle()); possibleTexts.add(textAndTitle.getText()); // get possible title and text from parent url if (StringUtils.isNotBlank(parentUrlString)) { ResourceParser.TitleAndText parentTextAndTitle = this.getResourceParser() .getTextAndTitle(parentUrlString); possibleTitles.add(parentTextAndTitle.getTitle()); possibleTexts.add(parentTextAndTitle.getText()); } // set the first title that is not blank. for (final String title : possibleTitles) { if (StringUtils.isNotBlank(resource.getTitle())) { break; } resource.setTitle(StringUtils.substring(title, 0, 250)); } // set the first text that is not blank. } @Override public Textbook findTextbookByContentGooruId(final String gooruContentId) { return getResourceRepository().findTextbookByContentGooruId(gooruContentId); } @Override public Resource findWebResource(final String url) { return getResourceRepository().findWebResource(url); } @Override public void saveNewResource(final Resource resource, final boolean downloadResource) throws IOException { resource.setCreatedOn(new Date(System.currentTimeMillis())); if (StringUtils.isEmpty(resource.getGooruOid())) { resource.setGooruOid(UUID.randomUUID().toString()); } resource.setLastModified(resource.getCreatedOn()); this.getResourceRepository().saveOrUpdate(resource); if (downloadResource) { final String sourceUrl = resource.getUrl(); final String fileName = StringUtils.substringAfterLast(sourceUrl, "/"); final File resourceFolder = new File( resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder()); if (!resourceFolder.exists()) { resourceFolder.mkdir(); } final String resourceFilePath = resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder() + File.separator + fileName; final boolean downloaded = ImageUtil.downloadAndSaveFile(sourceUrl, resourceFilePath); if (!downloaded) { throw new IOException(generateErrorMessage("GL0093", resource.getUrl())); } this.getAsyncExecutor().uploadResourceFolder(resource); resource.setUrl(fileName); this.getResourceRepository().saveOrUpdate(resource); if (fileName.toLowerCase().endsWith(DOT_PDF)) { final Map<String, Object> param = new HashMap<String, Object>(); param.put(RESOURCE_FILE_PATH, resourceFilePath); param.put(RESOURCE_GOORU_OID, resource.getGooruOid()); RequestUtil .executeRestAPI(param, settingService.getConfigSetting(ConfigConstants.GOORU_CONVERSION_RESTPOINT, 0, TaxonomyUtil.GOORU_ORG_UID) + "/conversion/pdf-to-image", Method.POST.getName()); } } else { // Save resource folder resourceRepository.saveOrUpdate(resource); } } @Override public Resource handleNewResource(Resource resource, final String resourceTypeForPdf, final String thumbnail) { // test if a resource with url exist, currently just skip. Errors errors = new BindException(Resource.class, RESOURCE); Resource updatedResource = updateResource(resource, true, thumbnail, errors); if (updatedResource != null) { return updatedResource; } errors = new BindException(Resource.class, RESOURCE); boolean downloadedFlag = false; // download if need and save: // FIXME /* * downloadedFlag = downloadFileIfRequiredAndUpdateUrl(resource, * StringUtils.defaultString(resourceTypeForPdf, * ResourceType.Type.HANDOUTS.getType())); */ final ResourceType resourceType = new ResourceType(); resource.setResourceType(resourceType); final String fileExtension = org.apache.commons.lang.StringUtils.substringAfterLast(resource.getUrl(), "."); if (fileExtension.equalsIgnoreCase(PDF) || fileExtension.equalsIgnoreCase(PNG)) { if (fileExtension.contains(PDF)) { resourceType.setName(ResourceType.Type.HANDOUTS.getType()); } else { resourceType.setName(ResourceType.Type.IMAGE.getType()); } } else { resourceType.setName(ResourceImageUtil.getYoutubeVideoId(resource.getUrl()) != null ? ResourceType.Type.VIDEO.getType() : ResourceType.Type.RESOURCE.getType()); } resource = saveResource(resource, errors, false); if (resource == null || errors.hasErrors()) { LOGGER.error("save resource failed" + errors.toString()); } if (downloadedFlag) { // Move the resource to the right folder File resourceFile = new File(resource.getUrl()); if (resourceFile.exists()) { final File resourceFolder = new File( resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder()); if (!resourceFolder.exists()) { resourceFolder.mkdir(); } final String fileName = StringUtils.substringAfterLast(resource.getUrl(), "/"); resourceFile.renameTo(new File(resourceFolder.getPath(), fileName)); resource.setUrl(fileName); this.getResourceRepository().saveOrUpdate(resource); String resourceFilePath = resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder() + resource.getUrl(); resourceFilePath = resourceFilePath.trim(); if (fileName.toLowerCase().endsWith(DOT_PDF)) { final Map<String, Object> param = new HashMap<String, Object>(); param.put(RESOURCE_FILE_PATH, resourceFilePath); param.put(RESOURCE_GOORU_OID, resource.getGooruOid()); RequestUtil.executeRestAPI(param, settingService.getConfigSetting(ConfigConstants.GOORU_CONVERSION_RESTPOINT, 0, TaxonomyUtil.GOORU_ORG_UID) + "/conversion/pdf-to-image", Method.POST.getName()); } } } else { // Save resource folder this.getResourceRepository().saveOrUpdate(resource); } enrichAndAddOrUpdate(resource); // if handouts, split and save chapters as resources: if (resource.getResourceType().getName().equalsIgnoreCase(ResourceType.Type.HANDOUTS.getType())) { final List<Resource> chapterResources = splitToChaptersResources(resource); for (final Resource chapterResource : chapterResources) { enrichAndAddOrUpdate(chapterResource); } } indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); return resource; } private Resource updateResource(final Resource resource, final boolean findByURL, final String thumbnail, final Errors errors) { Resource existingResource = null; if (findByURL) { existingResource = this.getResourceRepository().getResourceByUrl(resource.getUrl()); } else { existingResource = this.getResourceRepository().findResourceByContentGooruId(resource.getGooruOid()); } if (existingResource == null) { errors.reject(GET_GOORU_OID, "Invalid or non-existant record"); } else { boolean saveResource = false; // Check if meta-data is added in new resource Set<ResourceMetaData> resourceMetaData = resource.getResourceMetaData(); if ((existingResource.getResourceMetaData() == null && resourceMetaData != null) || existingResource.getResourceMetaData().size() == 0) { saveResource = true; existingResource.setResourceMetaData(resourceMetaData); } if (StringUtils.isEmpty(existingResource.getThumbnail()) && resourceMetaData != null) { for (final ResourceMetaData resourceMetaData2 : resourceMetaData) { if (resourceMetaData2.getMetaKey().equalsIgnoreCase(RESOURCE_IMAGE) && !StringUtils.isEmpty(resourceMetaData2.getMetaContent())) { final String imageURL = resourceMetaData2.getMetaContent(); final String fileName = existingResource.getGooruOid(); saveResource = true; final boolean downloaded = downloadThumbnail(fileName, imageURL, existingResource); if (downloaded) { break; } } } } if (resource.getTitle() != null) { saveResource = true; existingResource.setTitle(resource.getTitle()); } if (resource.getDescription() != null) { saveResource = true; existingResource.setDescription(resource.getDescription()); } if (StringUtils.isEmpty(existingResource.getThumbnail()) && thumbnail != null && thumbnail.startsWith("http://")) { saveResource = true; downloadThumbnail(existingResource.getGooruOid(), thumbnail, existingResource); } if (saveResource) { this.getResourceRepository().saveOrUpdate(existingResource); indexHandler.setReIndexRequest(existingResource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } } return existingResource; } public boolean downloadThumbnail(final String fileName, final String imageURL, final Resource resource) { try { FileMeta fileMeta = this.getMediaService().handleFileUpload(fileName, imageURL, null, false, 0, 0); this.getResourceImageUtil().moveFileAndSendMsgToGenerateThumbnails(resource, fileMeta.getName(), false); return true; } catch (FileNotFoundException e) { LOGGER.error("Error saving crawled resource image", e); } catch (IOException e) { LOGGER.error("Error saving crawled resource image", e); } return false; } // chapter spliting @Override public List<Resource> splitToChaptersResources(final Resource resource) { // split to chapters and return new chapter files: final List<String> newLocalChaptersUrls = splitToChaptersAndSaveFiles(resource.getUrl()); // save in db and index. List<Resource> chapterResources = new ArrayList<Resource>(); for (final String newLocalUrl : newLocalChaptersUrls) { final Resource chapterResource = new Resource(); chapterResource.setUrl(newLocalUrl); chapterResource.setUser(resource.getUser()); chapterResource.setResourceTypeByString(ResourceType.Type.HANDOUTS.getType()); chapterResource.setParentUrl(newLocalUrl); chapterResources.add(chapterResource); } return chapterResources; } private static List<String> splitToChaptersAndSaveFiles(final String newLocalUrl) { try { HashMap<Integer, String> chapters = new HashMap<Integer, String>(); ArrayList<Integer> pages = new ArrayList<Integer>(); /** Call the split method with filename and page size as params **/ PdfReader reader = new PdfReader(newLocalUrl); reader.consolidateNamedDestinations(); final List<HashMap<String, Object>> list = SimpleBookmark.getBookmark(reader); for (final HashMap<String, Object> test : list) { final String page = test.get(PAGE).toString(); final Integer num = Integer.parseInt(page.substring(0, page.indexOf(' '))); chapters.put(num, (String) test.get(_TITLE)); pages.add(num); } int index = 1; List<String> chaptersUrls = new ArrayList<String>(); for (final Integer i : pages) { String chapterUrl = null; if (pages.size() != index) { chapterUrl = splitAndSaveChapter(newLocalUrl, i, pages.get(index), chapters.get(i)); } else { chapterUrl = splitAndSaveChapter(newLocalUrl, i, reader.getNumberOfPages(), chapters.get(i)); } index++; if (chapterUrl != null) { chaptersUrls.add(chapterUrl); } } return chaptersUrls; } catch (Exception ex) { return new ArrayList<String>(); } } /** * @param mainFileUrl * : PDF file that has to be splitted * @param splittedPageSize * : Page size of each splitted files */ private static String splitAndSaveChapter(final String mainFileUrl, final int pageBeginNum, final int pageEndNum, final String name) { try { final PdfReader reader = new PdfReader(mainFileUrl); int splittedPageSize = pageEndNum - pageBeginNum + 1; int pageNum = pageBeginNum; final String chapterUrl = mainFileUrl.substring(0, mainFileUrl.indexOf(DOT_PDF)) + "-" + name + DOT_PDF; final Document document = new Document(reader.getPageSizeWithRotation(1)); final FileOutputStream fos = new FileOutputStream(chapterUrl); final PdfCopy writer = new PdfCopy(document, fos); final Map<String, String> info = reader.getInfo(); document.open(); if ((info != null) && (info.get(_AUTHOR) != null)) { document.addAuthor(info.get(_AUTHOR)); } document.addTitle(name); for (int offset = 0; offset < splittedPageSize && (pageNum + offset) < pageEndNum; offset++) { final PdfImportedPage page = writer.getImportedPage(reader, pageNum + offset); writer.addPage(page); } document.close(); writer.close(); return chapterUrl; } catch (Exception e) { e.printStackTrace(); return null; } } @Override public Resource saveResource(final Resource resource, final Errors errors, final boolean findByURL) { if (resource.getUser() == null) { errors.reject(USER, "User is required"); } if (errors.hasErrors()) { return null; } if (resource.getContentId() == null) { resource.setGooruOid(UUID.randomUUID().toString()); } if (resource.getSharing() == null) { resource.setSharing(Sharing.PRIVATE.getSharing()); } if (resource.getContentType() == null) { final ContentType contentTypeResource = (ContentType) this.getBaseRepository().get(ContentType.class, ContentType.RESOURCE); resource.setContentType(contentTypeResource); } if (resource.getResourceType() == null) { final ResourceType resourceType = (ResourceType) this.getBaseRepository().get(ResourceType.class, ResourceType.Type.RESOURCE.getType()); resource.setResourceType(resourceType); } if (resource.getCreatedOn() == null) { resource.setCreatedOn(new Date()); } resource.setLastModified(new Date()); this.getResourceRepository().saveOrUpdate(resource); return resource; } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public String updateResourceImage(final String gooruContentId, final String fileName) throws IOException { final Resource resource = this.getResourceRepository().findResourceByContentGooruId(gooruContentId); if (resource == null) { throw new NotFoundException(generateErrorMessage(GL0056, RESOURCE), GL0056); } this.getResourceImageUtil().moveFileAndSendMsgToGenerateThumbnails(resource, fileName, true); try { this.getAsyncExecutor().updateResourceFileInS3(resource.getFolder(), resource.getOrganization().getNfsStorageArea().getInternalPath(), gooruContentId, UserGroupSupport.getSessionToken()); } catch (Exception e) { LOGGER.error(e.getMessage()); } return resource.getOrganization().getNfsStorageArea().getAreaPath() + resource.getFolder() + "/" + resource.getThumbnail(); } @Override public void deleteResourceImage(final String gooruContentId) { final Resource resource = this.getResourceRepository().findResourceByContentGooruId(gooruContentId); final String repositoryPath = resource.getOrganization().getNfsStorageArea().getInternalPath(); final File classplanDir = new File(repositoryPath + resource.getFolder()); if (classplanDir.exists()) { final String prevFileName = resource.getThumbnail(); if (prevFileName != null && !prevFileName.equalsIgnoreCase("")) { final File prevFile = new File(classplanDir.getPath() + "/" + prevFileName); if (prevFile.exists()) { prevFile.delete(); this.getAsyncExecutor().deleteResourceFile(resource, resource.getThumbnail()); } } resource.setThumbnail(null); this.getResourceRepository().save(resource); indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } } @Override public void deleteResourceBulk(final String contentIds) { this.getResourceRepository().deleteResourceBulk(contentIds); indexHandler.setReIndexRequest(contentIds, IndexProcessor.DELETE, RESOURCE, null, false, false); } @Override public void deleteBulkResource(final String contentIds) { final List<Resource> resources = resourceRepository.findAllResourcesByGooruOId(contentIds); final List<Resource> removeList = new ArrayList<Resource>(); if (resources.size() > 0) { String removeContentIds = ""; int count = 0; for (final Resource resource : resources) { if (count > 0) { removeContentIds += ","; } removeContentIds += resource.getGooruOid(); removeList.add(resource); count++; } if (removeList.size() > 0) { this.baseRepository.removeAll(removeList); indexHandler.setReIndexRequest(removeContentIds, IndexProcessor.DELETE, RESOURCE, null, false, false); } } } public ResourceRepository getResourceRepository() { return resourceRepository; } public ResourceParser getResourceParser() { return resourceParser; } public ResourceImageUtil getResourceImageUtil() { return resourceImageUtil; } public S3ResourceApiHandler getS3ResourceApiHandler() { return s3ResourceApiHandler; } public IndexProcessor getIndexerMessenger() { return indexProcessor; } public CollectionUtil getCollectionUtil() { return collectionUtil; } public MediaService getMediaService() { return mediaService; } public BaseRepository getBaseRepository() { return baseRepository; } public ResourceManager getResourceManager() { return resourceManager; } public void setResourceManager(final ResourceManager resourceManager) { this.resourceManager = resourceManager; } public AssessmentRepository getAssessmentRepository() { return assessmentRepository; } @Override public ResourceSource updateSuggestAttribution(final String gooruContentId, final String attribution) { ResourceSource resourceSource = (ResourceSource) this.getBaseRepository().get(ResourceSource.class, contentRepository.findContentByGooruId(gooruContentId).getContentId()); if (resourceSource != null) { resourceSource.setAttribution(attribution); this.getBaseRepository().save(resourceSource); } return resourceSource; } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void deleteResource(final String gooruContentId, final User apiCaller) { final Resource resource = resourceRepository.findResourceByContentGooruId(gooruContentId); if (resource == null || resource.getResourceType().getName().equalsIgnoreCase(APPLICATION) || resource.getResourceType().getName().equalsIgnoreCase(SCOLLECTION) || resource.getResourceType().getName().equalsIgnoreCase(FOLDER) || resource.getResourceType().getName().equalsIgnoreCase(CLASSPAGE)) { throw new NotFoundException(generateErrorMessage(GL0056, RESOURCE), GL0056); } else { List<CollectionItem> collectionitems = this.getCollectionRepository() .getCollectionItemsByResource(gooruContentId); for (CollectionItem collectionItem : collectionitems) { collectionItem.getCollection().setLastModified(new Date(System.currentTimeMillis())); List<CollectionItem> resetCollectionItems = this.getCollectionRepository() .getResetSequenceCollectionItems(collectionItem.getCollection().getGooruOid(), collectionItem.getItemSequence()); int itemSequence = collectionItem.getItemSequence(); for (CollectionItem resetCollectionItem : resetCollectionItems) { resetCollectionItem.setItemSequence(itemSequence++); } this.getCollectionRepository().saveAll(resetCollectionItems); getAsyncExecutor().deleteFromCache( V2_ORGANIZE_DATA + collectionItem.getCollection().getUser().getPartyUid() + "*"); } this.getCollectionRepository().saveAll(collectionitems); if ((resource.getUser() != null && resource.getUser().getPartyUid().equalsIgnoreCase(apiCaller.getPartyUid())) || getUserService().isContentAdmin(apiCaller)) { this.getContentService().deleteContentTagAssoc(resource.getGooruOid(), apiCaller); this.getBaseRepository().remove(resource); indexHandler.setReIndexRequest(gooruContentId, IndexProcessor.DELETE, RESOURCE, null, false, false); } else { throw new BadRequestException(generateErrorMessage(GL0099, RESOURCE)); } } } @Override public void deleteAttribution(final Resource resource, final String gooruAttributionId, final User apiCaller) { // if (resource == null) { // resource = // resourceRepository.findResourceByAttributionGooruId(gooruAttributionId); if (resource == null) { LOGGER.warn("invalid resource passed to deleteResource:" + gooruAttributionId); return; } // } final UserRole contentAdmin = new UserRole(); contentAdmin.setRoleId(UserRole.ROLE_CONTENT_ADMIN); final User systemUser = this.getUserRepository().findByRole(contentAdmin).get(0); resource.setUser(systemUser); this.getBaseRepository().removeAll(resource.getContentPermissions()); resource.setContentPermissions(null); resource.setLastModified(new Date(System.currentTimeMillis())); resourceRepository.saveOrUpdate(resource); LOGGER.warn("Deleted resource from deleteResource:" + gooruAttributionId); /* Step 4 - Send the message to reindex the resource */ indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } @Override public ResourceSource findResourceSource(final String domainName) { return resourceRepository.findResourceSource(domainName); } @Override public ResourceInfo findResourceInfo(final String resourceGooruOid) { return resourceRepository.findResourceInfo(resourceGooruOid); } @Override public Resource findResourceByUrl(final String resourceUrl, final String sharing, final String userUid) { return resourceRepository.findResourceByUrl(resourceUrl, sharing, userUid); } @Override public List<Resource> findWebResourcesForBlacklisting() { return resourceRepository.findWebResourcesForBlacklisting(); } @Override public Resource addNewResource(final String url, final String title, final String text, final String category, final String sharing, final String typeName, final String licenseName, final Integer brokenStatus, final Boolean hasFrameBreaker, final String description, final Integer isFeatured, final String tags, final boolean isReturnJson, final User apiCaller, final String mediaType, final String resourceFormat, final String resourceInstructional) { User user = null; // construct resource: Resource resource = new Resource(); ResourceSource resourceSource = new ResourceSource(); String domainName = null; resource.setUrl(url); resource.setTitle(title); resource.setCategory(category); resource.setIsFeatured(isFeatured); resource.setDescription(description); resource.setMediaType(mediaType); user = apiCaller; resource.setUser(user); if (resourceFormat != null) { final CustomTableValue customTableValue = this.getCustomTableRepository() .getCustomTableValue(RESOURCE_CATEGORY_FORMAT, resourceFormat); resource.setResourceFormat(customTableValue); } if (resourceInstructional != null) { final CustomTableValue customTableValue = this.getCustomTableRepository() .getCustomTableValue(RESOURCE_INSTRUCTIONAL_USE, resourceInstructional); resource.setInstructional(customTableValue); } // FIXME Use the appropriate record source here. the api method may be // called from elsewhere as well resource.setRecordSource(Resource.RecordSource.GAT.getRecordSource()); if (typeName != null) { resource.setResourceTypeByString(ResourceType.Type.valueOf(typeName).getType()); } resource.setSharing(sharing); /* * if (licenseName != null) { resource.setLicense(licenseName); } */ if (brokenStatus == null) { resource.setBrokenStatus(0); } else { resource.setBrokenStatus(brokenStatus); } domainName = BaseUtil.getDomainName(url); if (domainName != null) { resourceSource = this.getResourceRepository().findResourceSource(domainName); } if (resourceSource != null && resourceSource.getFrameBreaker() != null && resourceSource.getFrameBreaker() == 1) { resource.setHasFrameBreaker(true); } else { resource.setHasFrameBreaker(false); } // add to db and index. resource = handleNewResource(resource, null, null); ResourceInfo resourceInfo = new ResourceInfo(); resourceInfo.setTags(tags); resourceInfo.setLastUpdated(new Date()); resource.setTags(tags); resourceInfo.setResource(resource); resource.setResourceInfo(resourceInfo); resourceRepository.save(resourceInfo); s3ResourceApiHandler.updateOrganization(resource); this.mapSourceToResource(resource); indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); return resource; } @Override public List<ResourceSource> getSuggestAttribution(final String keyword) { return resourceRepository.getSuggestAttribution(keyword); } @Override public Map<String, Object> findAllResourcesSource(final Map<String, String> filters) { return resourceRepository.findAllResourcesSource(filters); } @Override public Resource updateResource(final String resourceGooruOid, final String title, final String description, final String mediaFilename, final String mediaType) throws IOException { final Resource resource = getResourceRepository().findResourceByContentGooruId(resourceGooruOid); if (resource != null) { if (mediaFilename != null) { resourceImageUtil.moveFileAndSendMsgToGenerateThumbnails(resource, mediaFilename, false); } if (title != null) { resource.setTitle(title); } if (description != null) { resource.setDescription(description); } if (mediaType != null) { resource.setMediaType(mediaType); } getResourceRepository().save(resource); indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } return resource; } @Override public Resource updateResourceByGooruContentId(final String gooruContentId, final String resourceTitle, final String distinguish, final Integer isFeatured, final String description, final Boolean hasFrameBreaker, final String tags, final String sharing, final Integer resourceSourceId, final User user, final String mediaType, final String attribution, final String category, final String mediaFileName, final Boolean isBlacklisted, final String grade, final String resourceFormat, final String licenseName, final String url) { final Resource existingResource = resourceRepository.findResourceByContentGooruId(gooruContentId); if (resourceTitle != null) { existingResource.setTitle(resourceTitle); } if (description != null) { existingResource.setDescription(description); } if (hasFrameBreaker != null) { existingResource.setHasFrameBreaker(hasFrameBreaker); } if (isFeatured != null) { existingResource.setIsFeatured(isFeatured); } if (getUserService().isContentAdmin(user)) { ResourceSource resourceSource = null; String domainName = null; if (url != null) { existingResource.setUrl(url); domainName = BaseUtil.getDomainName(url); if (domainName != null) { resourceSource = this.getResourceRepository().findResourceSource(domainName); } if (resourceSource != null && resourceSource.getFrameBreaker() != null && resourceSource.getFrameBreaker() == 1) { existingResource.setHasFrameBreaker(true); } else { existingResource.setHasFrameBreaker(false); } this.mapSourceToResource(existingResource); } } if (category != null) { existingResource.setCategory(category); } if (resourceFormat != null) { final CustomTableValue customTableValue = this.getCustomTableRepository() .getCustomTableValue(RESOURCE_CATEGORY_FORMAT, resourceFormat); existingResource.setResourceFormat(customTableValue); } if (!StringUtils.isEmpty(mediaType)) { existingResource.setMediaType(mediaType); } if (resourceSourceId != null && resourceSourceId != 0) { if (existingResource.getResourceSource() == null) { ResourceSource resourceSource = new ResourceSource(); resourceSource.setResourceSourceId(resourceSourceId); if (attribution != null) { resourceSource.setAttribution(attribution); } existingResource.setResourceSource(resourceSource); existingResource.setDistinguish(Short.valueOf(distinguish)); } else { existingResource.getResourceSource().setResourceSourceId(resourceSourceId); } } else if (attribution != null) { ResourceSource resourceSource = new ResourceSource(); resourceSource = createResourcesourceAttribution(null, attribution); existingResource.setResourceSource(resourceSource); } if (sharing != null && !sharing.isEmpty()) { SessionContextSupport.putLogParameter("sharing-" + existingResource.getGooruOid(), existingResource.getSharing() + " to " + sharing); existingResource.setSharing(sharing); } if (tags != null && !tags.isEmpty()) { existingResource.setTags(tags); } if (mediaFileName != null) { this.getResourceImageUtil().downloadAndSendMsgToGenerateThumbnails(existingResource, mediaFileName); } if (getUserService().isContentAdmin(user)) { if (isBlacklisted != null && isBlacklisted == true) { existingResource.setSharing(PRIVATE); existingResource.setBatchId(DEL_FROM_SEARCH_INDEX); } } if (getUserService().isContentAdmin(user) && grade != null) { existingResource.setGrade(grade); } if (licenseName != null) { final License licenseData = this.getResourceRepository().getLicenseByLicenseName(licenseName); if (licenseData != null) { existingResource.setLicense(licenseData); } } resourceRepository.save(existingResource); if (tags != null && !tags.isEmpty()) { ResourceInfo resourceInfo = resourceRepository.findResourceInfo(gooruContentId); if (resourceInfo == null) { resourceInfo = new ResourceInfo(); } resourceInfo.setTags(tags); resourceInfo.setResource(existingResource); resourceInfo.setLastUpdated(new Date()); resourceRepository.save(resourceInfo); } if (isBlacklisted != null && isBlacklisted == true) { if (getUserService().isContentAdmin(user)) { indexHandler.setReIndexRequest(existingResource.getGooruOid(), IndexProcessor.DELETE, RESOURCE, null, false, false); } } else { indexHandler.setReIndexRequest(existingResource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } return existingResource; } @Override public void updateResourceSourceAttribution(final Integer resourceSourceId, final String domainName, final String attribution, final Integer frameBreaker, final User user, final Boolean isBlacklisted) throws Exception { final ResourceSource resourceSource = resourceRepository.findResourceByresourceSourceId(resourceSourceId); rejectIfNull(resourceSource, GL0056, 404, RESOURCE); if (domainName != null) { resourceSource.setDomainName(domainName); } if (attribution != null) { resourceSource.setAttribution(attribution); } if (frameBreaker != null) { resourceSource.setFrameBreaker(frameBreaker); } if (isBlacklisted != null) { if (isBlacklisted == false) { resourceSource.setIsBlacklisted(0); } else { resourceSource.setIsBlacklisted(1); } } this.resourceRepository.save(resourceSource); if (domainName != null && isBlacklisted != null && isBlacklisted) { if (getUserService().isContentAdmin(user)) { final List<Resource> resources = resourceRepository.findAllResourceBySourceId(resourceSourceId); resourceSource.setIsBlacklisted(1); String sharingType = null; String gooruOids = ""; int count = 0; if (resources != null && resources.size() <= 5000) { for (final Resource resource : resources) { sharingType = resource.getSharing(); if (sharingType.equalsIgnoreCase(PUBLIC)) { resource.setSharing(PRIVATE); } resource.setBatchId(DEL_FROM_SEARCH_INDEX); if (count > 0) { gooruOids += ","; } gooruOids += resource.getGooruOid(); count++; } indexHandler.setReIndexRequest(gooruOids, IndexProcessor.INDEX, RESOURCE, null, false, false); this.resourceRepository.saveAll(resources); } else if (resources != null && resources.size() > 5000) { throw new BadRequestException(generateErrorMessage(GL0001)); } } else { throw new AccessDeniedException(generateErrorMessage("GL0002")); } } if (domainName != null && frameBreaker != null && getUserService().isContentAdmin(user)) { List<Resource> resources = resourceRepository.findAllResourceBySourceId(resourceSourceId); int count = 0; String gooruOIds = ""; if (resources != null && resources.size() <= 5000) { for (Resource resource : resources) { boolean hasFrameBreaker = false; if (frameBreaker == null || frameBreaker == 0) { hasFrameBreaker = false; resourceSource.setFrameBreaker(0); } else if (frameBreaker == 1) { hasFrameBreaker = true; resourceSource.setFrameBreaker(1); } resource.setHasFrameBreaker(hasFrameBreaker); if (count > 0) { gooruOIds += ","; } gooruOIds += resource.getGooruOid(); count++; } indexHandler.setReIndexRequest(gooruOIds, IndexProcessor.INDEX, RESOURCE, null, false, false); this.resourceRepository.saveAll(resources); } else if (resources != null && resources.size() > 5000) { throw new BadRequestException(generateErrorMessage(GL0004)); } } } @Override public ResourceSource createResourcesourceAttribution(final String domainName, final String attribution) { final ResourceSource resourceSource = new ResourceSource(); resourceSource.setDomainName(domainName); resourceSource.setAttribution(attribution); resourceSource.setActiveStatus(1); if (BaseUtil.checkUrlHasHttpSupport(domainName)) { resourceSource.setHasHttpsSupport(1); } else { resourceSource.setHasHttpsSupport(0); } resourceRepository.save(resourceSource); return resourceSource; } @Override public Resource updateResourceThumbnail(final String gooruContentId, final String fileName, final Map<String, Object> formField) throws IOException { final Resource resource = this.findResourceByContentGooruId(gooruContentId); final File collectionDir = new File( resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder()); if (!collectionDir.exists()) { collectionDir.mkdirs(); } final Map<String, byte[]> files = (Map<String, byte[]>) formField.get(RequestUtil.UPLOADED_FILE_KEY); byte[] fileData = null; // expecting only one file in the request right now for (byte[] fileContent : files.values()) { fileData = fileContent; } if (fileData != null && fileData.length > 0) { String prevFileName = resource.getThumbnail(); if (prevFileName != null && !prevFileName.equalsIgnoreCase("")) { File prevFile = new File(resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder() + "/" + prevFileName); if (prevFile.exists()) { prevFile.delete(); } } final File file = new File(resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder() + "/" + fileName); OutputStream out = new FileOutputStream(file); out.write(fileData); out.close(); resource.setThumbnail(fileName); resourceRepository.save(resource); resourceImageUtil.sendMsgToGenerateThumbnails(resource); indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } return resource; } @Override public void mapSourceToResource(final Resource resource) { if (resource != null && resource.getResourceSource() == null) { if (ResourceType.Type.RESOURCE.getType().equalsIgnoreCase(resource.getResourceType().getName()) || ResourceType.Type.VIDEO.getType().equalsIgnoreCase(resource.getResourceType().getName())) { final String domainName = BaseUtil.getDomainName(resource.getUrl()); if (domainName != null) { final ResourceSource resourceSource = this.getResourceRepository() .findResourceSource(domainName); if (resourceSource != null) { resource.setResourceSource(resourceSource); } else { resource.setResourceSource(createResourcesourceAttribution(domainName, StringUtils.substringBeforeLast(domainName, "."))); } this.getResourceRepository().save(resource); } } } } public ContentService getContentService() { return contentService; } public void setContentService(final ContentService contentService) { this.contentService = contentService; } @Override public ResourceInfo getResourcePageCount(final String resourceId) { return resourceRepository.getResourcePageCount(resourceId); } @Override public boolean shortenedUrlResourceCheck(String url) { boolean isShortenedUrl = false; String domainName = BaseUtil.getDomainName(url); final String domainType = ResourceSource.ResourceSourceType.SHORTENDED_DOMAIN.getResourceSourceType(); if (domainName != null) { final String type = resourceRepository.shortenedUrlResourceCheck(domainName, domainType); if (type != null && type.equalsIgnoreCase( ResourceSource.ResourceSourceType.SHORTENDED_DOMAIN.getResourceSourceType())) { isShortenedUrl = true; } } return isShortenedUrl; } @Override public List<Resource> listResourcesUsedInCollections(final Map<String, String> filters) { return this.getResourceRepository().listResourcesUsedInCollections(filters); } public ResourceMetadataCo updateYoutubeResourceFeeds(final Resource resource) { return updateYoutubeResourceFeeds(resource, false); } public ResourceMetadataCo updateYoutubeResourceFeeds(final Resource resource, final boolean isUpdate) { ResourceMetadataCo resourceFeeds = null; final ResourceCio resourceCio = getResourceCassandraService().read(resource.getGooruOid()); if (resourceCio != null) { resourceFeeds = resourceCio.getResourceMetadata(); } if (resource.getResourceType().getName().equals(ResourceType.Type.VIDEO.getType())) { resourceFeeds = ResourceImageUtil.getYoutubeResourceFeeds(resource.getUrl(), resourceFeeds); if (resourceFeeds != null) { resourceFeeds.setId(resource.getGooruOid()); if (resourceCio != null) { resourceCio.setResourceMetadata(resourceFeeds); getResourceCassandraService().save(resourceCio); } return resourceFeeds; } } return resourceFeeds; } @Override public Resource updateResourceInfo(final Resource resource) { final String filePath = resource.getOrganization().getNfsStorageArea().getInternalPath() + resource.getFolder() + resource.getUrl(); final PDFFile pdfFile = GooruImageUtil.getPDFFile(filePath); if (pdfFile != null) { boolean isResourceInfoNull = false; ResourceInfo resourceInfo = this.findResourceInfo(resource.getGooruOid()); if (resourceInfo == null) { resourceInfo = new ResourceInfo(); resourceInfo.setResource(resource); isResourceInfoNull = true; } resourceInfo.setNumOfPages(pdfFile.getNumPages()); resourceInfo.setLastUpdated(new Date()); resourceRepository.save(resourceInfo); if (isResourceInfoNull) { resource.setResourceInfo(resourceInfo); this.resourceRepository.save(resource); } } return resource; } @Override @Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public Map<String, Object> getSuggestedResourceMetaData(final String url, final String title, final boolean fetchThumbnail) { return getResourceImageUtil().getResourceMetaData(url, title, fetchThumbnail); } @Override @Transactional(readOnly = false, propagation = Propagation.NOT_SUPPORTED, noRollbackFor = Exception.class) public Resource createResource(final Resource newResource, final List<String> tags, final User user, boolean updateIfExist) throws Exception { Resource resource = null; if (newResource.getUrl() != null && !newResource.getUrl().isEmpty() && newResource.getAttach() == null) { resource = this.getResourceRepository().findResourceByUrl(newResource.getUrl(), updateIfExist ? null : Sharing.PUBLIC.getSharing(), null); } if (updateIfExist && !hasUnrestrictedContentAccess() && resource != null && resource.getSharing() != null && resource.getSharing().equalsIgnoreCase(Sharing.PUBLIC.getSharing())) { throw new AccessDeniedException(generateErrorMessage("GL0012")); } final String title = newResource.getTitle().length() > 1000 ? newResource.getTitle().substring(0, 1000) : newResource.getTitle(); if (resource == null) { resource = new Resource(); resource.setGooruOid(UUID.randomUUID().toString()); resource.setUser(user); resource.setTitle(title); if (newResource.getCategory() != null) { resource.setCategory(newResource.getCategory().toLowerCase()); } if (newResource.getInstructional() != null) { final CustomTableValue resourceCategory = this.getCustomTableRepository() .getCustomTableValue(RESOURCE_INSTRUCTIONAL_USE, newResource.getInstructional().getValue()); resource.setInstructional(resourceCategory); } if (newResource.getResourceFormat() != null) { CustomTableValue resourcetype = this.getCustomTableRepository() .getCustomTableValue(RESOURCE_CATEGORY_FORMAT, newResource.getResourceFormat().getValue()); resource.setResourceFormat(resourcetype); } resource.setDescription(newResource.getDescription()); License license = new License(); license.setName(OTHER); resource.setRecordSource(Resource.RecordSource.COLLECTION.getRecordSource()); final ResourceType resourceTypeDo = new ResourceType(); resource.setResourceType(resourceTypeDo); String fileExtension = null; if (newResource.getAttach() != null && newResource.getAttach().getFilename() != null) { fileExtension = org.apache.commons.lang.StringUtils .substringAfterLast(newResource.getAttach().getFilename(), "."); if (fileExtension.contains(PDF) || BaseUtil.supportedDocument().containsKey(fileExtension)) { resourceTypeDo.setName(ResourceType.Type.HANDOUTS.getType()); } else { resourceTypeDo.setName(ResourceType.Type.IMAGE.getType()); } resource.setUrl(newResource.getAttach().getFilename()); resource.setIsOer(1); license.setName(CREATIVE_COMMONS); } else { resource.setUrl(newResource.getUrl()); if (ResourceImageUtil.getYoutubeVideoId(newResource.getUrl()) != null) { resourceTypeDo.setName(ResourceType.Type.VIDEO.getType()); } else if (newResource.getUrl() != null && newResource.getUrl().contains("vimeo.com")) { final String id = org.apache.commons.lang.StringUtils.substringAfterLast(newResource.getUrl(), "/"); if (org.apache.commons.lang.StringUtils.isNumeric(id)) { final ResourceMetadataCo resourceMetadataCo = ResourceImageUtil .getMetaDataFromVimeoVideo(newResource.getUrl()); resourceTypeDo.setName(ResourceType.Type.VIMEO_VIDEO.getType()); newResource.setThumbnail( resourceMetadataCo != null ? resourceMetadataCo.getThumbnail() : null); } else { resourceTypeDo.setName(ResourceType.Type.RESOURCE.getType()); } } else { resourceTypeDo.setName(ResourceType.Type.RESOURCE.getType()); } } resource.setLicense(license); if (newResource.getSharing() != null) { resource.setSharing(Sharing.PRIVATE.getSharing()); } else { resource.setSharing(newResource.getSharing()); } String domainName = BaseUtil.getDomainName(newResource.getUrl()); ResourceSource resourceSource = null; if (domainName != null) { resourceSource = this.getResourceRepository().findResourceSource(domainName); } if (resourceSource != null && resourceSource.getFrameBreaker() != null && resourceSource.getFrameBreaker() == 1) { resource.setHasFrameBreaker(true); } else if ((newResource.getUrl() != null && newResource.getUrl().contains(YOUTUBE_URL) && ResourceImageUtil.getYoutubeVideoId(newResource.getUrl()) == null)) { resource.setHasFrameBreaker(true); } else { resource.setHasFrameBreaker(false); } resourceRepository.saveOrUpdate(resource); saveOrUpdateResourceTaxonomy(resource, newResource.getTaxonomySet()); updateYoutubeResourceFeeds(resource, false); resourceRepository.saveOrUpdate(resource); mapSourceToResource(resource); if (newResource.getHost() != null && newResource.getHost().size() > 0) { resource.setHost( updateContentProvider(resource.getGooruOid(), newResource.getHost(), user, "host")); } if (tags != null && tags.size() > 0) { resource.setResourceTags( this.getContentService().createTagAssoc(resource.getGooruOid(), tags, user)); } try { if (newResource.getThumbnail() != null || fileExtension != null && fileExtension.contains(PDF)) { this.getResourceImageUtil().downloadAndSendMsgToGenerateThumbnails(resource, newResource.getThumbnail()); } } catch (Exception e) { LOGGER.error(_ERROR, e); } if (resource != null && resource.getContentId() != null) { try { indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } catch (Exception e) { LOGGER.error(_ERROR, e); } } if (newResource.getAttach() != null) { this.getResourceImageUtil().moveAttachment(newResource, resource); } } else if (updateIfExist) { if (!resource.getSharing().equalsIgnoreCase(PUBLIC)) { updateResource(resource.getGooruOid(), newResource, tags, user); } } return resource; } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public ActionResponseDTO<Resource> updateResource(final String resourceId, final Resource newResource, final List<String> resourceTags, final User user) throws Exception { final Resource resource = this.resourceRepository.findResourceByContentGooruId(resourceId); rejectIfNull(resource, GL0056, 404, RESOURCE); final Errors errors = validateUpdateResource(newResource, resource); final JSONObject itemData = new JSONObject(); if (!errors.hasErrors()) { if (getUserService().isContentAdmin(user)) { ResourceSource resourceSource = null; String domainName = null; if (newResource.getUrl() != null && !newResource.getUrl().isEmpty()) { if (!(resource.getSharing().equalsIgnoreCase(PUBLIC)) && resource.getUrl().equalsIgnoreCase(newResource.getUrl())) { itemData.put("url", newResource.getUrl()); resource.setUrl(newResource.getUrl()); domainName = BaseUtil.getDomainName(newResource.getUrl()); if (domainName != null) { resourceSource = this.getResourceRepository().findResourceSource(domainName); } if (resourceSource != null && resourceSource.getFrameBreaker() != null && resourceSource.getFrameBreaker() == 1) { resource.setHasFrameBreaker(true); } else { resource.setHasFrameBreaker(false); } this.mapSourceToResource(resource); } else { throw new BadRequestException(generateErrorMessage("GL0005")); } } } if (newResource.getTitle() != null) { itemData.put(TITLE, newResource.getTitle()); resource.setTitle(newResource.getTitle()); } if (newResource.getS3UploadFlag() != null) { resource.setS3UploadFlag(newResource.getS3UploadFlag()); } if (newResource.getDescription() != null) { itemData.put(DESCRIPTION, newResource.getDescription()); resource.setDescription(newResource.getDescription()); } if (newResource.getHasFrameBreaker() != null) { itemData.put(HAS_FRAME_BREAKER, newResource.getHasFrameBreaker()); resource.setHasFrameBreaker(newResource.getHasFrameBreaker()); } else { resource.setHasFrameBreaker(false); } if (newResource.getIsFeatured() != null) { itemData.put(IS_FEATURED, newResource.getIsFeatured()); resource.setIsFeatured(newResource.getIsFeatured()); } if (!resource.getSharing().equalsIgnoreCase(Sharing.PUBLIC.getSharing()) && resource.getUser().getGooruUId().equalsIgnoreCase(user.getGooruUId()) && (resource.getResourceType().getName().equalsIgnoreCase(ResourceType.Type.HANDOUTS.getType()) || resource.getResourceType().getName() .equalsIgnoreCase(ResourceType.Type.IMAGE.getType()) || resource.getResourceType().getName() .equalsIgnoreCase(ResourceType.Type.PRESENTATION.getType()))) { if (newResource.getAttach() != null && newResource.getAttach().getFilename() != null) { resource.setUrl(newResource.getAttach().getFilename()); } } if (newResource.getResourceFormat() != null) { itemData.put(RESOURCEFORMAT, newResource.getResourceFormat().getValue()); final CustomTableValue customTableValue = this.getCustomTableRepository() .getCustomTableValue(RESOURCE_CATEGORY_FORMAT, newResource.getResourceFormat().getValue()); resource.setResourceFormat(customTableValue); } if (newResource.getGrade() != null) { resource.setGrade(newResource.getGrade()); } if (newResource.getCategory() != null) { itemData.put(CATEGORY, newResource.getCategory()); resource.setCategory(newResource.getCategory().toLowerCase()); } if (!StringUtils.isEmpty(newResource.getMediaType())) { resource.setMediaType(newResource.getMediaType()); } if (newResource.getSharing() != null && !newResource.getSharing().isEmpty()) { itemData.put(SHARING, newResource.getSharing()); SessionContextSupport.putLogParameter("sharing-" + resource.getGooruOid(), resource.getSharing() + " to " + newResource.getSharing()); resource.setSharing(newResource.getSharing()); } if (newResource.getTags() != null && !newResource.getTags().isEmpty()) { itemData.put(TAGS, newResource.getTags()); resource.setTags(newResource.getTags()); } if (newResource.getLicense() != null) { itemData.put(LICENSE, newResource.getLicense().getName()); License licenseData = this.getResourceRepository() .getLicenseByLicenseName(newResource.getLicense().getName()); if (licenseData != null) { resource.setLicense(licenseData); } } if (newResource.getPublisher() != null && newResource.getPublisher().size() > 0) { updateContentProvider(resource.getGooruOid(), newResource.getPublisher(), user, CustomProperties.ContentProviderType.PUBLISHER.getContentProviderType()); } if (newResource.getAggregator() != null && newResource.getAggregator().size() > 0) { updateContentProvider(resource.getGooruOid(), newResource.getAggregator(), user, CustomProperties.ContentProviderType.AGGREGATOR.getContentProviderType()); } if (newResource.getHost() != null && newResource.getHost().size() > 0) { updateContentProvider(resource.getGooruOid(), newResource.getHost(), user, CustomProperties.ContentProviderType.HOST.getContentProviderType()); } if (resourceTags != null && resourceTags.size() > 0) { resource.setResourceTags( this.getContentService().createTagAssoc(resource.getGooruOid(), resourceTags, user)); } saveOrUpdateResourceTaxonomy(resource, newResource.getTaxonomySet()); if (newResource.getResourceSource() != null) { ResourceSource resourceSource = null; if (newResource.getResourceSource().getResourceSourceId() != null && newResource.getResourceSource().getResourceSourceId() != 0) { resourceSource = this.getResourceRepository() .findResourceByresourceSourceId(newResource.getResourceSource().getResourceSourceId()); } else if (newResource.getResourceSource().getAttribution() != null) { resourceSource = this.getResourceRepository() .getAttribution(newResource.getResourceSource().getAttribution()); if (resourceSource == null) { resourceSource = new ResourceSource(); resourceSource = createResourcesourceAttribution(null, newResource.getResourceSource().getAttribution()); } } resource.setResourceSource(resourceSource); } resourceRepository.save(resource); if (newResource.getThumbnail() != null) { this.getResourceImageUtil().downloadAndSendMsgToGenerateThumbnails(resource, newResource.getThumbnail()); } setContentProvider(resource); if (newResource.getTags() != null && !newResource.getTags().isEmpty()) { ResourceInfo resourceInfo = resourceRepository.findResourceInfo(resourceId); if (resourceInfo == null) { resourceInfo = new ResourceInfo(); } resourceInfo.setTags(newResource.getTags()); resourceInfo.setResource(resource); resourceInfo.setLastUpdated(new Date()); resourceRepository.save(resourceInfo); } indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } if (newResource.getAttach() != null) { this.getResourceImageUtil().moveAttachment(newResource, resource); } getAsyncExecutor().deleteFromCache(V2_ORGANIZE_DATA + resource.getUser().getPartyUid() + "*"); try { this.getResourceEventLog().getEventLogs(resource, itemData, user); } catch (Exception e) { LOGGER.debug("error" + e.getMessage()); } return new ActionResponseDTO<Resource>(resource, errors); } @Override public List<String> updateContentProvider(final String gooruOid, final List<String> providerList, final User user, final String providerType) { final CustomTableValue customTableValue = this.getCustomTableRepository() .getCustomTableValue(_CONTENT_PROVIDER_TYPE, providerType); final List<ContentProviderAssociation> contentProviderAssociationList = this.getContentRepository() .getContentProviderByGooruOid(gooruOid, null, providerType); if (contentProviderAssociationList.size() > 0) { this.getContentRepository().removeAll(contentProviderAssociationList); } for (final String provider : providerList) { ContentProvider contentProvider = this.getContentRepository().getContentProviderByName(provider, CONTENT_PROVIDER_TYPE + providerType); if (contentProvider == null) { contentProvider = new ContentProvider(); contentProvider.setName(provider); contentProvider.setActiveFlag(true); contentProvider.setType(customTableValue); this.getContentRepository().save(contentProvider); } final ContentProviderAssociation contentProviderAssociation = new ContentProviderAssociation(); contentProviderAssociation.setContentProvider(contentProvider); final ResourceSource resourceSource = new ResourceSource(); resourceSource.setDomainName(provider); resourceSource.setActiveStatus(0); this.getResourceRepository().save(resourceSource); contentProviderAssociation.setResourceSource(resourceSource); contentProviderAssociation.setGooruOid(gooruOid); contentProviderAssociation.setAssociatedDate(new Date(System.currentTimeMillis())); contentProviderAssociation.setAssociatedBy(user); this.getContentRepository().save(contentProviderAssociation); } return providerList; } @Override @Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public List<Resource> listResourcesUsedInCollections(final String limit, final String offset, final User user) { return this.getResourceRepository().listResourcesUsedInCollections(Integer.parseInt(limit), Integer.parseInt(offset)); } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public Resource deleteTaxonomyResource(final String resourceId, final Resource newResource, final User user) { Resource resource = resourceRepository.findResourceByContentGooruId(resourceId); rejectIfNull(resource, GL0056, RESOURCE); deleteResourceTaxonomy(resource, newResource.getTaxonomySet()); return resource; } @Override public void saveOrUpdateResourceTaxonomy(final Content content, final Set<Code> taxonomySet) { Set<Code> codes = content.getTaxonomySet(); if (taxonomySet != null) { for (Code newCode : taxonomySet) { if (newCode.getCodeId() != null) { newCode = (Code) this.getTaxonomyRepository().findCodeByCodeId(newCode.getCodeId()); } else { newCode = (Code) this.getTaxonomyRepository().findCodeByTaxCode(newCode.getCode()); } if (newCode != null) { if (codes != null && codes.size() > 0) { boolean isExisting = false; for (Code code : codes) { if (code.getCodeId().equals(newCode.getCodeId())) { isExisting = true; break; } } if (!isExisting) { codes.add(newCode); } } else { codes = new HashSet<Code>(); codes.add(newCode); } } } } content.setTaxonomySet(codes); this.getResourceRepository().save(content); } @Override public void deleteResourceTaxonomy(final Resource resource, final Set<Code> taxonomySet) { final Set<Code> codes = resource.getTaxonomySet(); final Set<Code> removeCodes = new HashSet<Code>(); for (Code removeCode : taxonomySet) { removeCode = (Code) (this.getTaxonomyRepository().findCodeByTaxCode( removeCode.getCodeId() != null ? removeCode.getCodeId().toString() : removeCode.getCode())); if (removeCode != null) { for (Code code : codes) { if (code.getCodeId().equals(removeCode.getCodeId())) { removeCodes.add(removeCode); } } } if (removeCodes != null && removeCodes.size() > 0) { codes.removeAll(removeCodes); } else { throw new NotFoundException(generateErrorMessage(GL0056, _TAXONOMY), GL0056); } } resource.setTaxonomySet(codes); this.getResourceRepository().save(resource); indexHandler.setReIndexRequest(resource.getGooruOid(), IndexProcessor.INDEX, RESOURCE, null, false, false); } public Resource buildResourceFromInputParameters(final String data, final User user) { final Resource resource = JsonDeserializer.deserialize(data, Resource.class); resource.setGooruOid(UUID.randomUUID().toString()); final ContentType contentType = getContentType(ContentType.RESOURCE); resource.setContentType(contentType); resource.setLastModified(new Date(System.currentTimeMillis())); resource.setCreatedOn(new Date(System.currentTimeMillis())); if (!hasUnrestrictedContentAccess()) { resource.setSharing(Sharing.PUBLIC.getSharing()); } else { resource.setSharing(resource.getSharing() != null && (resource.getSharing().equalsIgnoreCase(Sharing.PRIVATE.getSharing()) || resource.getSharing().equalsIgnoreCase(Sharing.PUBLIC.getSharing()) || resource.getSharing().equalsIgnoreCase(Sharing.ANYONEWITHLINK.getSharing())) ? resource.getSharing() : Sharing.PUBLIC.getSharing()); } resource.setUser(user); resource.setOrganization(user.getPrimaryOrganization()); resource.setCreator(user); resource.setDistinguish(Short.valueOf("0")); resource.setRecordSource(NOT_ADDED); resource.setIsFeatured(0); resource.setLastUpdatedUserUid(user.getGooruUId()); return resource; } @Override public void saveOrUpdateGrade(final Resource resource, final Resource newResource) { if (newResource.getGrade() != null) { String grade = newResource.getGrade(); String resourceGrade = resource.getGrade(); List<String> newResourceGrades = Arrays.asList(grade.split(",")); if (resourceGrade != null) { List<String> resourceGrades = Arrays.asList(resourceGrade.split(",")); if (resourceGrades != null) { for (final String newGrade : resourceGrades) { if (!newResourceGrades.contains(newGrade) && newGrade.length() > 0) { grade += "," + newGrade; } } } } newResource.setGrade(grade); } else { newResource.setGrade(resource.getGrade()); } this.getResourceRepository().save(newResource); } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public List<User> addCollaborator(final String collectionId, final User user, final String collaboratorId, final String collaboratorOperation) { final Content content = contentRepository.findContentByGooruId(collectionId); if (content == null) { throw new NotFoundException(generateErrorMessage(GL0056, _COLLECTION), GL0056); } if (collaboratorId != null) { List<String> collaboratorsList = Arrays.asList(collaboratorId.split("\\s*,\\s*")); return collectionUtil.updateNewCollaborator(content, collaboratorsList, user, COLLECTION_COLLABORATE, collaboratorOperation); } return null; } @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void deleteContentProvider(String gooruOid, String providerType, String name) { this.getContentRepository().deleteContentProvider(gooruOid, providerType, name); Collection collection = this.getCollectionRepository().getCollectionByGooruOid(gooruOid, null); if (collection != null) { indexHandler.setReIndexRequest(gooruOid, IndexProcessor.INDEX, SCOLLECTION, null, false, false); } else { indexHandler.setReIndexRequest(gooruOid, IndexProcessor.INDEX, RESOURCE, null, false, false); } } private Errors validateUpdateResource(Resource newResource, Resource resource) throws Exception { final Errors errors = new BindException(newResource, RESOURCE); rejectIfNull(errors, resource, RESOURCE_ALL, GL0056, generateErrorMessage(GL0056, RESOURCE)); return errors; } public TaxonomyRespository getTaxonomyRepository() { return taxonomyRepository; } public ResourceEventLog getResourceEventLog() { return resourceEventLog; } public TaxonomyService getTaxonomyService() { return taxonomyService; } public void setTaxonomyService(TaxonomyService taxonomyService) { this.taxonomyService = taxonomyService; } public SettingService getSettingService() { return settingService; } public ResourceCassandraService getResourceCassandraService() { return resourceCassandraService; } public void setResourceCassandraService(ResourceCassandraService resourceCassandraService) { this.resourceCassandraService = resourceCassandraService; } @Override public List<Map<String, Object>> getPartyPermissions(long contentId) { return resourceRepository.getPartyPermissions(contentId); } public UserRepository getUserRepository() { return userRepository; } @Override public Resource resourcePlay(String gooruContentId, User apiCaller, boolean more) throws Exception { Resource resource = this.findResourceByContentGooruId(gooruContentId); if (resource == null) { throw new NotFoundException(generateErrorMessage("GL0003"), "GL0003"); } resource.setViews(this.resourceCassandraService.getLong(resource.getGooruOid(), STATISTICS_VIEW_COUNT)); resource.setViewCount(resource.getViews()); resource.setCustomFieldValues(customFieldService.getCustomFieldsValuesOfResource(resource.getGooruOid())); if (more) { String category = CustomProperties.Table.FEEDBACK_CATEGORY.getTable() + "_" + RATING; Map<String, Object> map = new HashMap<String, Object>(); map.put(FEEDBACK, feedbackRepository.getContentFeedbackAggregate(gooruContentId, category, true)); resource.setMeta(map); } return resource; } public AsyncExecutor getAsyncExecutor() { return asyncExecutor; } public CustomTableRepository getCustomTableRepository() { return customTableRepository; } @Override public Resource findLtiResourceByContentGooruId(String gooruContentId) { return resourceRepository.findLtiResourceByContentGooruId(gooruContentId); } public CollectionService getCollectionService() { return collectionService; } @Override public Map<String, Object> checkResourceUrlExists(String url, boolean checkShortenedUrl) throws Exception { Resource resource = findResourceByUrl(url, Sharing.PUBLIC.getSharing(), null); Map<String, Object> response = new HashMap<String, Object>(); if (resource != null) { response.put(RESOURCE, resource); } if (checkShortenedUrl) { response.put(SHORTENED_URL_STATUS, shortenedUrlResourceCheck(url)); } return response; } @Override @Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public List<Collection> getCollectionsByResourceId(String resourceId, String sharing, Integer limit, Integer offset) { List<Collection> collections = this.getResourceRepository().getCollectionsByResourceId(resourceId, sharing, limit, offset); final CustomTableValue type = this.getCustomTableRepository().getCustomTableValue( CustomProperties.Table.USER_CLASSIFICATION_TYPE.getTable(), CustomProperties.UserClassificationType.COURSE.getUserClassificationType()); final CustomTableValue gradeType = this.getCustomTableRepository().getCustomTableValue( CustomProperties.Table.USER_CLASSIFICATION_TYPE.getTable(), CustomProperties.UserClassificationType.GRADE.getUserClassificationType()); for (Collection collection : collections) { final ResourceMetaInfo collectionMetaInfo = new ResourceMetaInfo(); this.getCollectionService().setCollectionTaxonomyMetaInfo(collection.getTaxonomySet(), collectionMetaInfo); collectionMetaInfo.setStandards( this.getCollectionService().getStandards(collection.getTaxonomySet(), false, null)); collection.setMetaInfo(collectionMetaInfo); Map<String, Object> meta = new HashMap<String, Object>(); meta.put(GRADE, this.getUserRepository().getUserGrade(collection.getUser().getPartyUid(), gradeType.getCustomTableValueId(), 1)); meta.put(COURSE, this.getUserRepository().getUserClassifications(collection.getUser().getPartyUid(), type.getCustomTableValueId(), 1)); collection.getUser().setMeta(meta); } return collections; } public CollectionRepository getCollectionRepository() { return collectionRepository; } }