/**
* <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.modules.webFeed.models;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.olat.basesecurity.BaseSecurityManager;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles;
import org.olat.core.util.resource.OresHelper;
import org.olat.modules.webFeed.FeedSecurityCallback;
/**
* This is an OLAT feed (or web/news feed) model. It stores all necessary
* information of a feed including items. Implements Serializable for caching.
*
* <P>
* Initial Date: Feb 16, 2009 <br>
*
* @author Gregor Wassmann
*/
public class Feed implements OLATResourceable, Serializable {
// Identification
private Long id;
private String type;
// Properties
private String title;
private String description;
private String author;
private String imageName;
private String externalFeedURL;
private String externalImageURL;
private Date lastModified;
// String copyright;
// String language;
// Data model versioning
public static final int CURRENT_MODEL_VERSION = 2;
// Default is that model version is set to the initial value 1. This is
// necessary to detect models previous to the introduction of this model
// version flag which was with version 2.
private int modelVersion = 0;
// A feed can either be internal, external or unspecified.
// Internal means that items are created within OLAT. External implies
// that the feed is read from an external URL.
private Boolean isExternal;
// The items (saved separately from feed)
// @XStreamOmitField : didn't work
transient private List<Item> items = new ArrayList<Item>();
// This list enables us to save items separately and refer to them by id.
private List<String> itemIds = new ArrayList<String>();
/**
* Constructor
*
* @param resource
*/
public Feed(OLATResourceable resource) {
this.id = resource.getResourceableId();
this.type = resource.getResourceableTypeName();
// new model constructor, set to current version
this.modelVersion = CURRENT_MODEL_VERSION;
}
public OLATResourceable getResource() {
return OresHelper.createOLATResourceableInstanceWithoutCheck(type, id);
}
/**
* Setter for title
*
* @param title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Setter for description
*
* @param description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Setter for name
*
* @param name
*/
public void setImageName(String name) {
this.imageName = name;
}
/**
* Getter for title
*
* @return title
*/
public String getTitle() {
return title;
}
/**
* Getter for description
*
* @return description
*/
public String getDescription() {
return description;
}
/**
* Getter for imageName
*
* @return imageName
*/
public String getImageName() {
return imageName;
}
/**
* @param id The id to set.
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return The id
*/
public Long getId() {
return getResourceableId();
}
/**
* @return <tt>true</tt> if the current object is an external feed.
*/
public boolean isExternal() {
return isExternal != null && isExternal.booleanValue();
}
/**
* @return <tt>true</tt> if the current object is an internal feed.
*/
public boolean isInternal() {
return isExternal != null && !this.isExternal.booleanValue();
}
/**
* @return <tt>true</tt> if the current object is an external feed.
*/
public boolean isUndefined() {
return isExternal == null;
}
/**
* @param isExternal The isExternal to set. (Valid argument values are true,
* false (their corresponding boolean object) or null)
*/
public void setExternal(Boolean isExternal) {
// Clear all items
items.clear();
// Initializes item id's store
if (isExternal == null) {
// undefined state
this.itemIds = null;
} else if (isExternal.booleanValue()){
// external feed
this.itemIds = null;
} else {
this.itemIds = new ArrayList<String>();
}
// Set new state
this.isExternal = isExternal;
}
/**
* @return All items
*/
public List<Item> getItems() {
return items;
}
/**
* Return a copy of the list of items, but the items
* are not copied. Use this method to mitigate concurrent
* modifications issues.
*
* @return
*/
public List<Item> getCopiedListOfItems() {
return items == null ? null : new ArrayList<>(items);
}
/**
* @param identity
* @return The filtered Items
*/
public List<Item> getFilteredItems(FeedSecurityCallback callback, Identity identity) {
final Roles roles = BaseSecurityManager.getInstance().getRoles(identity);
if (roles != null) {
boolean admin = roles.isOLATAdmin();
if (admin || isExternal()) {
// An admin can see all items and everybody can see all items of
// external feeds
return items;
}
}
List<Item> filteredItems = new ArrayList<Item>();
for (Item item : items) {
if (item.isPublished()) {
// everybody can see published items
filteredItems.add(item);
} else if (item.isScheduled() && callback.mayEditItems()) {
// scheduled items can be seen by everybody who can edit items
// (moderators)
filteredItems.add(item);
} else if (identity.getKey() == item.getAuthorKey()) {
// scheduled items and drafts of oneself are shown
filteredItems.add(item);
} else if (item.isDraft()) {
if(callback.mayViewAllDrafts()) {
filteredItems.add(item);
} else if (identity.getKey() == item.getModifierKey()) {
filteredItems.add(item);
}
}
}
return filteredItems;
}
/**
* @return A list of all published items
*/
public List<Item> getPublishedItems() {
List<Item> publishedItems = new ArrayList<Item>();
for (Item item : items) {
if (item.isPublished()) {
publishedItems.add(item);
}
}
return publishedItems;
}
/**
* Sorts the items by publish date in reverse chronological order
*/
public void sortItems() {
Collections.sort(items, new ItemPublishDateComparator());
// reset the itemIds
setItems(items);
}
/**
* @return All items in an array
*/
public Item[] getItemsArray() {
Item[] itemsArray = null;
if (items != null) {
int size = items.size();
itemsArray = new Item[size];
for (int i = 0; i < size; i++) {
itemsArray[i] = items.get(i);
}
}
return itemsArray;
}
/**
* @return All item ids
*/
public List<String> getItemIds() {
return itemIds;
}
/**
* Add an item to the feed.<br>
*
* @param item
*/
public void add(Item item) {
items.add(0, item);
if (isInternal()) {
itemIds.add(0, item.getGuid());
}
}
/**
* Remove an item from the feed
*
* @param item
* @return <tt>true</tt> if this list contained the specified element.
*/
public boolean remove(Item item) {
itemIds.remove(item.getGuid());
// Remove below works also when object identity is not the same as
// item.equals has been overwritten to match on the GUID
return items.remove(item);
}
/**
* @param items
*/
public void setItems(List<Item> items) {
this.items = items;
this.itemIds = new ArrayList<String>(items.size());
for (Item item : items) {
itemIds.add(item.getGuid());
}
}
/**
* @param author The author to set.
*/
public void setAuthor(String author) {
this.author = author;
}
/**
* @return Returns the author.
*/
public String getAuthor() {
return author;
}
/**
* @param feedUrl The external feed URL to set.
*/
public void setExternalFeedUrl(String feedUrl) {
this.externalFeedURL = feedUrl;
}
/**
* @return Returns the externalFeedURL.
*/
public String getExternalFeedUrl() {
return externalFeedURL;
}
/**
* @param externalImageURL The externalImageURL to set.
*/
public void setExternalImageURL(String externalImageURL) {
this.externalImageURL = externalImageURL;
}
/**
* @return Returns the externalImageURL.
*/
public String getExternalImageURL() {
return externalImageURL;
}
/**
* @return True if there are items
*/
public boolean hasItems() {
boolean hasItems = false;
if (items != null && items.size() > 0) {
hasItems = true;
}
return hasItems;
}
/**
* @param lastModified The lastModified to set.
*/
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
/**
* @return Returns the lastModified.
*/
public Date getLastModified() {
return lastModified;
}
/**
* @see org.olat.core.id.OLATResourceable#getResourceableId()
*/
public Long getResourceableId() {
return id;
}
/**
* @see org.olat.core.id.OLATResourceable#getResourceableTypeName()
*/
public String getResourceableTypeName() {
return type;
}
/**
* Set the resourcable type name. (Sometimes needed on reload, just to make
* sure.)
*
* @param type The resourcable type name
*/
public void setType(String type) {
this.type = type;
}
/**
* Set the model version to the specific value;
* @param modelVersion
*/
public void setModelVersion(int modelVersion) {
this.modelVersion = modelVersion;
}
/**
* Get the version of the datamodel
*
* @return
*/
public int getModelVersion() {
return modelVersion;
}
}