diff --git a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java index 438f03d38f8064c98500454ce1ce07fed76ddfce..cb332f2e17f7678b831edf43018ed834f1ac61b0 100644 --- a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java +++ b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java @@ -38,7 +38,22 @@ public class CourseAccessAndProperties { private boolean canReference; private boolean canDownload; - private List<OfferAccess> offerAccess; + private List<OfferAccess> offerAccess; + + public CourseAccessAndProperties(RepositoryEntry re) { + this.repoEntry = re; + } + + public CourseAccessAndProperties(RepositoryEntry re, RepositoryEntryAllowToLeaveOptions setting, int access, + boolean membersOnly, boolean canCopy, boolean canReference, boolean canDownload) { + this.repoEntry = re; + this.setting = setting; + this.access = access; + this.membersOnly = membersOnly; + this.canCopy = canCopy; + this.canReference = canReference; + this.canDownload = canDownload; + } public List<OfferAccess> getOfferAccess() { return offerAccess; @@ -103,23 +118,4 @@ public class CourseAccessAndProperties { public void setCanDownload(boolean canDownload) { this.canDownload = canDownload; } - - public CourseAccessAndProperties(RepositoryEntry re) { - super(); - this.repoEntry = re; - } - - public CourseAccessAndProperties(RepositoryEntry re, RepositoryEntryAllowToLeaveOptions setting, int access, - boolean membersOnly, boolean canCopy, boolean canReference, boolean canDownload) { - super(); - this.repoEntry = re; - this.setting = setting; - this.access = access; - this.membersOnly = membersOnly; - this.canCopy = canCopy; - this.canReference = canReference; - this.canDownload = canDownload; - } - - } \ No newline at end of file diff --git a/src/main/java/org/olat/course/editor/CourseCatalog.java b/src/main/java/org/olat/course/editor/CourseCatalog.java new file mode 100644 index 0000000000000000000000000000000000000000..15449573e314326c4601da76ff07baaa06c80b26 --- /dev/null +++ b/src/main/java/org/olat/course/editor/CourseCatalog.java @@ -0,0 +1,53 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.editor; + +import java.util.ArrayList; +import java.util.List; + +import org.olat.course.editor.PublishStepCatalog.CategoryLabel; + +/** + * + * Initial date: 23 juin 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CourseCatalog { + + private String choiceValue; + private final List<CategoryLabel> categories = new ArrayList<>(); + + public CourseCatalog() { + // + } + + public String getChoiceValue() { + return choiceValue; + } + + public void setChoiceValue(String choiceValue) { + this.choiceValue = choiceValue; + } + + public List<CategoryLabel> getCategoryLabels() { + return categories; + } +} diff --git a/src/main/java/org/olat/course/editor/EditorMainController.java b/src/main/java/org/olat/course/editor/EditorMainController.java index 92d19d4f86c4df60e6e943ae2f9eb78616c26500..76d2151926da05fc97dc7430579c3c33c1a31098 100644 --- a/src/main/java/org/olat/course/editor/EditorMainController.java +++ b/src/main/java/org/olat/course/editor/EditorMainController.java @@ -92,7 +92,6 @@ import org.olat.course.CourseFactory; import org.olat.course.DisposedCourseRestartController; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentModeManager; -import org.olat.course.editor.PublishStepCatalog.CategoryLabel; import org.olat.course.groupsandrights.CourseGroupManager; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.CourseNodeConfiguration; @@ -1074,7 +1073,7 @@ public class EditorMainController extends MainLayoutBasicController implements G * callback executed in case wizard is finished. */ StepRunnerCallback finish = new StepRunnerCallback(){ - + @Override public Step execute(UserRequest ureq1, WindowControl wControl1, StepsRunContext runContext) { //all information to do now is within the runContext saved boolean hasChanges = false; @@ -1098,11 +1097,9 @@ public class EditorMainController extends MainLayoutBasicController implements G hasChanges = true; } - if (runContext.containsKey("catalogChoice")) { - String choice = (String) runContext.get("catalogChoice"); - @SuppressWarnings("unchecked") - List<CategoryLabel> categories = (List<CategoryLabel>)runContext.get("categories"); - publishManager.publishToCatalog(choice, categories); + CourseCatalog courseCatalog = (CourseCatalog)runContext.get("categories"); + if(courseCatalog != null) { + publishManager.publishToCatalog(courseCatalog.getChoiceValue(), courseCatalog.getCategoryLabels()); } if(publishEvents.getPostPublishingEvents().size() > 0) { diff --git a/src/main/java/org/olat/course/editor/PublishProcess.java b/src/main/java/org/olat/course/editor/PublishProcess.java index 08c895f3d0f9f650ddca5bb03ff5382bc9fa4a14..8ff9a2a80701b2b3fada5ef03d4cf48bbdb66432 100644 --- a/src/main/java/org/olat/course/editor/PublishProcess.java +++ b/src/main/java/org/olat/course/editor/PublishProcess.java @@ -598,43 +598,41 @@ public class PublishProcess { prop.setStringValue(choiceValue); cpm.updateProperty(prop); } + + CatalogManager cm = CoreSpringFactory.getImpl(CatalogManager.class); + List<CatalogEntry> refParentCategories = cm.getCatalogCategoriesFor(repositoryEntry); - if("yes".equals(choiceValue) && labels != null) { - CatalogManager cm = CoreSpringFactory.getImpl(CatalogManager.class); - List<CatalogEntry> refParentCategories = cm.getCatalogCategoriesFor(repositoryEntry); - - a_a: - for(CategoryLabel label:labels) { - CatalogEntry category = label.getCategory(); - CatalogEntry parentCategory = label.getParentCategory(); - if(label.isDeleted()) { - //test - if(category.getKey() != null) { - List<CatalogEntry> children = cm.getChildrenOf(category); - for(CatalogEntry child:children) { - if(child.getRepositoryEntry() != null && child.getRepositoryEntry().equalsByPersistableKey(repositoryEntry)) { - cm.deleteCatalogEntry(child); - } + a_a: + for(CategoryLabel label:labels) { + CatalogEntry category = label.getCategory(); + CatalogEntry parentCategory = label.getParentCategory(); + if(label.isDeleted()) { + //test + if(category.getKey() != null) { + List<CatalogEntry> children = cm.getChildrenOf(category); + for(CatalogEntry child:children) { + if(child.getRepositoryEntry() != null && child.getRepositoryEntry().equalsByPersistableKey(repositoryEntry)) { + cm.deleteCatalogEntry(child); } } - } else if(category.getKey() == null) { - //it's a new entry -> check if not already in catalog at this position - for(Iterator<CatalogEntry> refIt=refParentCategories.iterator(); refIt.hasNext(); ) { - CatalogEntry refParentCategory = refIt.next(); - if(refParentCategory.equalsByPersistableKey(parentCategory)) { - refIt.remove(); - break a_a; - } + } + } else if(category.getKey() == null) { + //it's a new entry -> check if not already in catalog at this position + for(Iterator<CatalogEntry> refIt=refParentCategories.iterator(); refIt.hasNext(); ) { + CatalogEntry refParentCategory = refIt.next(); + if(refParentCategory.equalsByPersistableKey(parentCategory)) { + refIt.remove(); + break a_a; } - - category.setOwnerGroup(BaseSecurityManager.getInstance().createAndPersistSecurityGroup()); - cm.addCatalogEntry(parentCategory, category); - } else { - for(Iterator<CatalogEntry> refIt=refParentCategories.iterator(); refIt.hasNext(); ) { - CatalogEntry refParentCategory = refIt.next(); - if(refParentCategory.equalsByPersistableKey(category)) { - refIt.remove(); - } + } + + category.setOwnerGroup(BaseSecurityManager.getInstance().createAndPersistSecurityGroup()); + cm.addCatalogEntry(parentCategory, category); + } else { + for(Iterator<CatalogEntry> refIt=refParentCategories.iterator(); refIt.hasNext(); ) { + CatalogEntry refParentCategory = refIt.next(); + if(refParentCategory.equalsByPersistableKey(category)) { + refIt.remove(); } } } diff --git a/src/main/java/org/olat/course/editor/PublishStepCatalog.java b/src/main/java/org/olat/course/editor/PublishStepCatalog.java index 7eee8c5817f430f04df2625cd16392e883615d52..464d4a86b254bae345e48a34c029b968eede285e 100644 --- a/src/main/java/org/olat/course/editor/PublishStepCatalog.java +++ b/src/main/java/org/olat/course/editor/PublishStepCatalog.java @@ -108,12 +108,14 @@ class PublishStepCatalog extends BasicStep { } static class PublishStepCatalogForm extends StepFormBasicController { + + private static final String[] keys = new String[]{"yes","no"}; private FormLink addToCatalog; private SingleSelection catalogBox; private CloseableModalController cmc; private Controller catalogAddController; - private final List<FormLink> deleteLinks = new ArrayList<FormLink>();; + private final List<FormLink> deleteLinks = new ArrayList<>(); private final RepositoryEntry repositoryEntry; private final CatalogManager catalogManager; @@ -148,7 +150,6 @@ class PublishStepCatalog extends BasicStep { fc.setRootForm(mainForm); formLayout.add("catalogSettings", fc); - final String[] keys = new String[]{"yes","no"}; final String[] values = new String[] { translate("yes"), translate("no") @@ -291,18 +292,17 @@ class PublishStepCatalog extends BasicStep { @Override protected void formOK(UserRequest ureq) { - if(catalogBox.isOneSelected()) { - String val = catalogBox.getSelectedKey(); - addToRunContext("catalogChoice", val); - - List<CategoryLabel> categories = new ArrayList<CategoryLabel>(); - for(FormLink deletedLink:deleteLinks) { - CategoryLabel cat = (CategoryLabel)deletedLink.getUserObject(); - categories.add(cat); + CourseCatalog courseCatalog = new CourseCatalog(); + courseCatalog.setChoiceValue(catalogBox.getSelectedKey()); + boolean removeAll = "no".equals(catalogBox.getSelectedKey()); + for(FormLink deletedLink:deleteLinks) { + CategoryLabel cat = (CategoryLabel)deletedLink.getUserObject(); + if(removeAll) { + cat.setDeleted(true); } - addToRunContext("categories", categories); + courseCatalog.getCategoryLabels().add(cat); } - + addToRunContext("categories", courseCatalog); fireEvent(ureq, StepsEvent.ACTIVATE_NEXT); } diff --git a/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java b/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java index 18f2a2b4e58b44df635a86c11ccdbf2f3b730bdd..cffa62aed082255927eab4bcd97bd074530075aa 100644 --- a/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java +++ b/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java @@ -36,6 +36,8 @@ import org.olat.basesecurity.SecurityGroupMembershipImpl; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.services.mark.impl.MarkImpl; import org.olat.core.id.Identity; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.group.BusinessGroup; import org.olat.modules.qpool.QuestionItem; @@ -60,6 +62,8 @@ import org.springframework.stereotype.Service; @Service("questionDao") public class QuestionItemDAO { + private static final OLog log = Tracing.createLoggerFor(QuestionItemDAO.class); + @Autowired private DB dbInstance; @Autowired @@ -222,14 +226,42 @@ public class QuestionItemDAO { return query.getResultList(); } - public void delete(List<QuestionItemShort> items) { + public void delete(List<? extends QuestionItemShort> items) { EntityManager em = dbInstance.getCurrentEntityManager(); for(QuestionItemShort item:items) { - QuestionItem refItem = em.getReference(QuestionItemImpl.class, item.getKey()); - em.remove(refItem); + QuestionItem refItem = loadLazyReferenceId(item.getKey()); + if(refItem != null) { + em.remove(refItem); + } } } + /** + * The method only load the question item and doesn't fetch + * anything. + * + * @param key The primary key of the item + * @return The question item or null if not found + */ + private QuestionItem loadLazyReferenceId(Long key) { + StringBuilder sb = new StringBuilder(); + sb.append("select item from questionitem item") + .append(" where item.key=:key"); + List<QuestionItem> items = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), QuestionItem.class) + .setParameter("key", key) + .getResultList(); + return items == null || items.isEmpty() ? null : items.get(0); + } + + /** + * The method loads the question item and fetch + * the taxonomy level, license, item type and + * educational context. + * + * @param key The primary key of the item + * @return The question item or null if not found + */ public QuestionItemImpl loadById(Long key) { StringBuilder sb = new StringBuilder(); sb.append("select item from questionitem item") diff --git a/src/test/java/org/olat/modules/qpool/manager/QuestionDAOTest.java b/src/test/java/org/olat/modules/qpool/manager/QuestionDAOTest.java index 98da047d1a674868071d6889288e833eea07e525..48d592b18c8df0185df4beec1d4f5d3a6127ee7a 100644 --- a/src/test/java/org/olat/modules/qpool/manager/QuestionDAOTest.java +++ b/src/test/java/org/olat/modules/qpool/manager/QuestionDAOTest.java @@ -20,6 +20,7 @@ package org.olat.modules.qpool.manager; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -451,4 +452,41 @@ public class QuestionDAOTest extends OlatTestCase { Assert.assertEquals(1, count); dbInstance.commit();//make sure that changes are committed } + + @Test + public void deleteQuestion() { + QItemType fibType = qItemTypeDao.loadByType(QuestionType.FIB.name()); + QuestionItem item = questionDao.createAndPersist(null, "To delete 1", QTIConstants.QTI_12_FORMAT, Locale.ENGLISH.getLanguage(), null, null, null, fibType); + dbInstance.commitAndCloseSession(); + + List<QuestionItem> itemsToDelete = Collections.singletonList(item); + questionDao.delete(itemsToDelete); + dbInstance.commitAndCloseSession(); + + QuestionItem deletedItem = questionDao.loadById(item.getKey()); + Assert.assertNull(deletedItem); + } + + @Test + public void deleteQuestion_alreadyDeletedQuestions() { + QItemType fibType = qItemTypeDao.loadByType(QuestionType.FIB.name()); + QuestionItem item1 = questionDao.createAndPersist(null, "To delete 1", QTIConstants.QTI_12_FORMAT, Locale.ENGLISH.getLanguage(), null, null, null, fibType); + QuestionItem item2 = questionDao.createAndPersist(null, "To delete 2", QTIConstants.QTI_12_FORMAT, Locale.ENGLISH.getLanguage(), null, null, null, fibType); + dbInstance.commitAndCloseSession(); + + // delete item 1 + questionDao.delete(Collections.singletonList(item1)); + dbInstance.commitAndCloseSession(); + + List<QuestionItem> itemsToDelete = new ArrayList<>(); + itemsToDelete.add(item1); + itemsToDelete.add(item2); + questionDao.delete(itemsToDelete); + dbInstance.commitAndCloseSession(); + + QuestionItem deletedItem1 = questionDao.loadById(item1.getKey()); + Assert.assertNull(deletedItem1); + QuestionItem deletedItem2 = questionDao.loadById(item2.getKey()); + Assert.assertNull(deletedItem2); + } } \ No newline at end of file