/**
* <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.core.commons.services.mark.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.FlushModeType;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.olat.core.commons.persistence.DB;
import org.olat.core.commons.services.mark.Mark;
import org.olat.core.commons.services.mark.MarkManager;
import org.olat.core.commons.services.mark.MarkResourceStat;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Description:<br>
* Implementation of the MarkManager
*
* <P>
* Initial Date: 9 mar. 2010 <br>
* @author srosse, stephane.rosse@frentix.com
*/
@Service
public class MarkManagerImpl implements MarkManager {
@Autowired
private DB dbInstance;
@Override
public List<Mark> getMarks(OLATResourceable ores, Identity identity, Collection<String> subPath) {
StringBuilder sb = new StringBuilder();
sb.append("select mark from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName and mark.creator=:creator");
if(subPath != null && !subPath.isEmpty()) {
sb.append(" and mark.resSubPath in (:resSubPaths)");
}
TypedQuery<Mark> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Mark.class)
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.setParameter("creator", identity);
if(subPath != null && !subPath.isEmpty()) {
query.setParameter("resSubPaths", subPath);
}
return query.getResultList();
}
@Override
public Set<Long> getMarkResourceIds(Identity identity, String resourceTypeName, Collection<String> subPaths) {
StringBuilder sb = new StringBuilder();
sb.append("select distinct(mark.resId) from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resName=:resName and mark.creator=:creator");
if(!subPaths.isEmpty()) {
sb.append(" and mark.resSubPath in (:resSubPaths)");
}
TypedQuery<Long> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Long.class)
.setParameter("resName", resourceTypeName)
.setParameter("creator", identity);
if(!subPaths.isEmpty()) {
query.setParameter("resSubPaths", subPaths);
}
List<Long> results = query.getResultList();
return new HashSet<Long>(results);
}
@Override
public List<Mark> getMarks(Identity identity, Collection<String> resourceTypeName) {
StringBuilder sb = new StringBuilder();
sb.append("select mark from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.creator=:creator ");
if(resourceTypeName != null && !resourceTypeName.isEmpty()) {
sb.append("and mark.resName in(:resName)");
}
TypedQuery<Mark> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Mark.class)
.setParameter("creator", identity);
if(resourceTypeName != null && !resourceTypeName.isEmpty()) {
query.setParameter("resName", resourceTypeName);
}
List<Mark> results = query.getResultList();
return results;
}
public List<Long> getMarksResourceId(Identity identity, String resourceTypeName) {
StringBuilder sb = new StringBuilder();
sb.append("select mark.resId from ").append(MarkImpl.class.getName()).append(" mark ")
.append(" where mark.creator=:creator and mark.resName =:resName");
return dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Long.class)
.setParameter("creator", identity)
.setParameter("resName", resourceTypeName)
.getResultList();
}
@Override
public void filterMarks(Identity identity, String resourceTypeName, Collection<Long> resIds) {
if(resIds == null || resIds.isEmpty()) return;
StringBuilder sb = new StringBuilder();
sb.append("select mark.resId from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resName=:resName and mark.creator=:creator");
if(resIds.size() < 50) {//if there is too much resource to filter, retrieve all the mark
sb.append(" and mark.resId in(:resIds)");
}
TypedQuery<Long> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Long.class)
.setParameter("resName", resourceTypeName)
.setParameter("creator", identity);
if(resIds.size() < 50) {
query.setParameter("resIds", resIds);
}
List<Long> markedResIds = query.getResultList();
resIds.retainAll(markedResIds);
}
@Override
public boolean isMarked(OLATResourceable ores, Identity identity, String resSubPath) {
StringBuilder sb = new StringBuilder();
sb.append("select mark.key from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName and mark.creator=:creator");
if(resSubPath != null) {
sb.append(" and mark.resSubPath=:resSubPath");
}
TypedQuery<Long> query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Long.class)
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.setParameter("creator", identity);
if(resSubPath != null) {
query.setParameter("resSubPath", resSubPath);
}
List<Long> results = query.getResultList();
return results != null && results.size() > 0 && results.get(0) != null && results.get(0).longValue() > 0;
}
@Override
public Mark setMark(OLATResourceable ores, Identity identity, String subPath, String businessPath) {
MarkImpl mark = loadMark(ores, identity, subPath);
if(mark == null) {
mark = new MarkImpl();
mark.setResName(ores.getResourceableTypeName());
mark.setResId(ores.getResourceableId());
mark.setResSubPath(subPath);
mark.setBusinessPath(businessPath);
mark.setCreator(identity);
dbInstance.saveObject(mark);
}
return mark;
}
@Override
public void moveMarks(OLATResourceable ores, String oldSubPath, String newSubPath) {
//can be a lot of marks to move around
StringBuilder sb = new StringBuilder();
sb.append("update ").append(MarkImpl.class.getName()).append(" mark set mark.resSubPath=:newSubPath ")
.append("where mark.resId=:resId and mark.resName=:resName and mark.resSubPath=:oldSubPath");
dbInstance.getCurrentEntityManager().createQuery(sb.toString())
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.setParameter("oldSubPath", oldSubPath)
.setParameter("newSubPath", newSubPath)
.setFlushMode(FlushModeType.AUTO)
.executeUpdate();
}
@Override
public void removeMark(OLATResourceable ores, Identity identity, String subPath) {
MarkImpl mark = loadMark(ores, identity, subPath);
if(mark != null) {
dbInstance.deleteObject(mark);
}
}
@Override
public void removeMark(Mark mark) {
removeMark(mark.getOLATResourceable(), mark.getCreator(), mark.getResSubPath());
}
private MarkImpl loadMark(OLATResourceable ores, Identity identity, String resSubPath) {
StringBuilder sb = new StringBuilder();
sb.append("select mark from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName and mark.creator=:creator");
if(resSubPath != null) {
sb.append(" and mark.resSubPath=:resSubPath");
}
TypedQuery<MarkImpl> query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), MarkImpl.class)
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.setParameter("creator", identity);
if(resSubPath != null) {
query.setParameter("resSubPath", resSubPath);
}
List<MarkImpl> results = query.getResultList();
if(results.isEmpty()) {
return null;
}
return results.get(0);
}
@Override
public void deleteMarks(OLATResourceable ores) {
StringBuilder sb = new StringBuilder();
sb.append("delete from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName");
dbInstance.getCurrentEntityManager().createQuery(sb.toString())
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.setFlushMode(FlushModeType.AUTO)
.executeUpdate();
}
/**
* Exact match
*/
@Override
public void deleteMarks(OLATResourceable ores, String subPath) {
StringBuilder sb = new StringBuilder();
sb.append("delete from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName");
if(subPath == null) {
sb.append(" and mark.resSubPath is null");
} else {
sb.append(" and mark.resSubPath=:resSubPath");
}
Query query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString())
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId());
if(subPath != null) {
query.setParameter("resSubPath", subPath);
}
query.setFlushMode(FlushModeType.AUTO).executeUpdate();
}
@Override
public List<MarkResourceStat> getStats(OLATResourceable ores, List<String> subPaths, Identity identity) {
if(subPaths == null || subPaths.isEmpty()) {
//these stats are optimized
if(identity == null) {
return getStats(ores);
} else {
return getStats(ores, identity);
}
} else {
StringBuilder sb = new StringBuilder();
sb.append("select count(mark.resSubPath), mark.resSubPath from ").append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName and mark.resSubPath in (:resSubPath)");
if(identity != null) {
sb.append(" and mark.creator=:creator");
}
sb.append(" group by mark.resSubPath");
TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Object[].class)
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.setParameter("resSubPath", subPaths);
if(identity != null) {
query.setParameter("creator", identity);
}
List<Object[]> rawStats = query.getResultList();
List<MarkResourceStat> stats = new ArrayList<MarkResourceStat>(rawStats.size());
for(Object[] rawStat:rawStats) {
stats.add(new MarkResourceStat(ores,(String)rawStat[1],((Number)rawStat[0]).intValue()));
}
return stats;
}
}
private List<MarkResourceStat> getStats(OLATResourceable ores) {
StringBuilder sb = new StringBuilder();
sb.append("select count(mark.resSubPath), mark.resSubPath from ")
.append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName")
.append(" group by mark.resSubPath");
List<Object[]> rawStats = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Object[].class)
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.getResultList();
List<MarkResourceStat> stats = new ArrayList<MarkResourceStat>(rawStats.size());
for(Object[] rawStat:rawStats) {
stats.add(new MarkResourceStat(ores,(String)rawStat[1],((Number)rawStat[0]).intValue()));
}
return stats;
}
private List<MarkResourceStat> getStats(OLATResourceable ores, Identity identity) {
StringBuilder sb = new StringBuilder();
sb.append("select mark.resSubPath from ")
.append(MarkImpl.class.getName()).append(" mark where ")
.append("mark.resId=:resId and mark.resName=:resName")
.append(" and mark.creator=:creator");
List<String> markedSubPaths = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), String.class)
.setParameter("resName", ores.getResourceableTypeName())
.setParameter("resId", ores.getResourceableId())
.setParameter("creator", identity)
.getResultList();
List<MarkResourceStat> stats = new ArrayList<MarkResourceStat>(markedSubPaths.size());
for(String markedSubPath:markedSubPaths) {
stats.add(new MarkResourceStat(ores,markedSubPath,1));
}
return stats;
}
}