You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by ja...@apache.org on 2011/08/24 14:25:30 UTC
svn commit: r1161066 - in /incubator/rave/trunk: ./ rave-portal/
rave-portal/src/main/java/org/apache/rave/portal/model/
rave-portal/src/main/java/org/apache/rave/portal/repository/
rave-portal/src/main/java/org/apache/rave/portal/repository/impl/ rave...
Author: jasha
Date: Wed Aug 24 12:25:29 2011
New Revision: 1161066
URL: http://svn.apache.org/viewvc?rev=1161066&view=rev
Log:
RAVE-76 Users can submit a Widget for inclusion in the Widget Repository
Added:
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/validator/NewWidgetValidator.java
incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/addwidget.jsp
incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/validator/NewWidgetValidatorTest.java
Modified:
incubator/rave/trunk/pom.xml
incubator/rave/trunk/rave-portal/pom.xml
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/model/Widget.java
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/WidgetRepository.java
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/WidgetService.java
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java
incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/util/ViewNames.java
incubator/rave/trunk/rave-portal/src/main/resources/initial_data.sql
incubator/rave/trunk/rave-portal/src/main/resources/messages.properties
incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/applicationContext.xml
incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/store.jsp
incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/widget.jsp
incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css
incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/repository/JpaWidgetRepositoryTest.java
incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/WidgetServiceTest.java
incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java
incubator/rave/trunk/rave-portal/src/test/resources/portal-test-applicationContext.xml
Modified: incubator/rave/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/pom.xml?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/pom.xml (original)
+++ incubator/rave/trunk/pom.xml Wed Aug 24 12:25:29 2011
@@ -54,6 +54,8 @@
<log4j.version>1.2.16</log4j.version>
<junit.version>4.7</junit.version>
<commons-lang.version>2.6</commons-lang.version>
+ <!-- Don't update to commons-validator 1.3.1, it misses a dependency -->
+ <commons-validator.version>1.3.0</commons-validator.version>
<icu4j.version>4.6.1</icu4j.version>
<easymock.version>3.0</easymock.version>
<com.h2database.version>1.3.154</com.h2database.version>
@@ -254,6 +256,13 @@
<version>${commons-lang.version}</version>
</dependency>
+ <!-- Validation -->
+ <dependency>
+ <groupId>commons-validator</groupId>
+ <artifactId>commons-validator</artifactId>
+ <version>${commons-validator.version}</version>
+ </dependency>
+
<!-- Rave artifacts -->
<dependency>
<groupId>org.apache.rave</groupId>
Modified: incubator/rave/trunk/rave-portal/pom.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/pom.xml?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/pom.xml (original)
+++ incubator/rave/trunk/rave-portal/pom.xml Wed Aug 24 12:25:29 2011
@@ -150,6 +150,12 @@
<artifactId>h2</artifactId>
</dependency>
+ <!-- Validation -->
+ <dependency>
+ <groupId>commons-validator</groupId>
+ <artifactId>commons-validator</artifactId>
+ </dependency>
+
<!-- JSTL -->
<dependency>
<groupId>org.glassfish.web</groupId>
Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/model/Widget.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/model/Widget.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/model/Widget.java (original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/model/Widget.java Wed Aug 24 12:25:29 2011
@@ -56,14 +56,16 @@ import org.apache.rave.persistence.Basic
@NamedQuery(name = Widget.WIDGET_GET_BY_STATUS_AND_FREE_TEXT,
query = "SELECT w FROM Widget w WHERE w.widgetStatus = :widgetStatus AND lower(w.title) LIKE :searchTerm OR w.description LIKE :description"),
@NamedQuery(name = Widget.WIDGET_COUNT_BY_STATUS_AND_FREE_TEXT,
- query = "SELECT count(w) FROM Widget w WHERE w.widgetStatus = :widgetStatus AND lower(w.title) LIKE :searchTerm OR w.description LIKE :description")
+ query = "SELECT count(w) FROM Widget w WHERE w.widgetStatus = :widgetStatus AND lower(w.title) LIKE :searchTerm OR w.description LIKE :description"),
+ @NamedQuery(name = Widget.WIDGET_GET_BY_URL, query = "SELECT w FROM Widget w WHERE w.url = :url")
})
public class Widget implements BasicEntity, Serializable {
private static final long serialVersionUID = 1L;
public static final String PARAM_SEARCH_TERM = "searchTerm";
public static final String PARAM_STATUS = "widgetStatus";
+ public static final String PARAM_URL = "url";
public static final String WIDGET_GET_ALL = "Widget.getAll";
public static final String WIDGET_COUNT_ALL = "Widget.countAll";
@@ -75,6 +77,7 @@ public class Widget implements BasicEnti
"Widget.getByStatusAndFreeText";
public static final String WIDGET_COUNT_BY_STATUS_AND_FREE_TEXT =
"Widget.countByStatusAndFreeText";
+ public static final String WIDGET_GET_BY_URL = "Widget.getByUrl";
@Id @Column(name="id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "widgetIdSeq")
@@ -88,7 +91,7 @@ public class Widget implements BasicEnti
private String title;
//private InternationalString title;
- @Basic @Column(name="url")
+ @Basic @Column(name="url", unique = true)
private String url;
@Basic @Column(name="thumbnail_url")
Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/WidgetRepository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/WidgetRepository.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/WidgetRepository.java (original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/WidgetRepository.java Wed Aug 24 12:25:29 2011
@@ -105,4 +105,12 @@ public interface WidgetRepository extend
* @return total number of {@link Widget}'s that match the search criteria
*/
int getCountByStatusAndFreeText(WidgetStatus widgetStatus, String searchTerm);
+
+ /**
+ * Searches for a Widget by its url
+ *
+ * @param widgetUrl (unique) url of the Widget
+ * @return {@link Widget} if it can be found, otherwise {@literal null}
+ */
+ Widget getByUrl(String widgetUrl);
}
\ No newline at end of file
Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java (original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java Wed Aug 24 12:25:29 2011
@@ -25,6 +25,7 @@ import java.util.List;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
+import org.apache.commons.lang.StringUtils;
import org.apache.rave.persistence.jpa.AbstractJpaRepository;
import org.apache.rave.portal.model.Widget;
import org.apache.rave.portal.model.WidgetStatus;
@@ -115,6 +116,21 @@ public class JpaWidgetRepository extends
return countResult.intValue();
}
+ @Override
+ public Widget getByUrl(String widgetUrl) {
+ if (StringUtils.isBlank(widgetUrl)) {
+ throw new IllegalArgumentException("Widget URL must not be empty");
+ }
+
+ TypedQuery<Widget> query = manager.createNamedQuery(Widget.WIDGET_GET_BY_URL, Widget.class);
+ // url is a unique field, so no paging needed
+ query.setParameter(Widget.PARAM_URL, widgetUrl);
+ final List<Widget> resultList = query.getResultList();
+ if (resultList.isEmpty()) {
+ return null;
+ }
+ return resultList.get(0);
+ }
/**
* Performs a query with a limit and offset
Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/WidgetService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/WidgetService.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/WidgetService.java (original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/WidgetService.java Wed Aug 24 12:25:29 2011
@@ -84,4 +84,21 @@ public interface WidgetService {
*/
SearchResult<Widget> getPublishedWidgetsByFreeTextSearch(String searchTerm,
int offset, int pageSize);
+
+ /**
+ * Gets a Widget by its (unique) url
+ *
+ * @param widgetUrl url of the Widget
+ * @return {@link Widget} if it exists, otherwise {@literal null}
+ */
+ Widget getWidgetByUrl(String widgetUrl);
+
+
+ /**
+ * Persists a new {@link Widget} if it is not already present in the store
+ *
+ * @param widget new Widget to store
+ * @return Widget if it is new and can be stored, otherwise {@literal null}
+ */
+ Widget registerNewWidget(Widget widget);
}
Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java (original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java Wed Aug 24 12:25:29 2011
@@ -27,12 +27,16 @@ import org.apache.rave.portal.model.Widg
import org.apache.rave.portal.model.util.SearchResult;
import org.apache.rave.portal.repository.WidgetRepository;
import org.apache.rave.portal.service.WidgetService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DefaultWidgetService implements WidgetService {
+ private static Logger logger = LoggerFactory.getLogger(DefaultWidgetService.class);
+
private final WidgetRepository widgetRepository;
@Autowired
@@ -104,4 +108,18 @@ public class DefaultWidgetService implem
searchResult.setPageSize(pageSize);
return searchResult;
}
+
+ @Override
+ public Widget getWidgetByUrl(String widgetUrl) {
+ return widgetRepository.getByUrl(widgetUrl);
+ }
+
+ @Override
+ public Widget registerNewWidget(Widget widget) {
+ if (getWidgetByUrl(widget.getUrl()) != null) {
+ logger.debug("Trying to add an existing widget for url {}", widget.getUrl());
+ return null;
+ }
+ return widgetRepository.save(widget);
+ }
}
Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java (original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java Wed Aug 24 12:25:29 2011
@@ -19,12 +19,17 @@
package org.apache.rave.portal.web.controller;
+import org.apache.rave.portal.model.Widget;
+import org.apache.rave.portal.model.WidgetStatus;
import org.apache.rave.portal.service.WidgetService;
import org.apache.rave.portal.web.util.ModelKeys;
import org.apache.rave.portal.web.util.ViewNames;
+import org.apache.rave.portal.web.validator.NewWidgetValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -39,9 +44,12 @@ public class WidgetStoreController {
private final WidgetService widgetService;
+ private final NewWidgetValidator widgetValidator;
+
@Autowired
- public WidgetStoreController(WidgetService widgetService) {
+ public WidgetStoreController(WidgetService widgetService, NewWidgetValidator validator) {
this.widgetService = widgetService;
+ this.widgetValidator = validator;
}
/**
@@ -85,7 +93,7 @@ public class WidgetStoreController {
* @param offset offset within the total amount of results (to enable paging)
* @return the view name of the main store page
*/
- @RequestMapping(method = RequestMethod.GET, value = "/store/search")
+ @RequestMapping(method = RequestMethod.GET, value = "search")
public String viewSearchResult(Model model, @RequestParam long referringPageId,
@RequestParam String searchTerm,
@RequestParam(required = false, defaultValue = "0") int offset) {
@@ -97,4 +105,46 @@ public class WidgetStoreController {
model.addAttribute(ModelKeys.OFFSET, offset);
return ViewNames.STORE;
}
+
+ /**
+ * Shows the Add new Widget form
+ *
+ * @param model {@link Model}
+ * @return the view name of the Add new Widget form
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "addwidget")
+ public String viewAddWidgetForm(Model model) {
+ final Widget widget = new Widget();
+ model.addAttribute(ModelKeys.WIDGET, widget);
+ return ViewNames.ADD_WIDGET_FORM;
+ }
+
+ /**
+ * Validates the form input, if valid, tries to store the Widget data
+ *
+ * @param widget {@link Widget} as submitted by the user
+ * @param results {@link BindingResult}
+ * @param model {@link Model}
+ * @return if successful the view name of the widget, otherwise the form
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "doaddwidget")
+ public String viewAddWidgetResult(@ModelAttribute Widget widget, BindingResult results,
+ Model model) {
+ widgetValidator.validate(widget, results);
+ if (results.hasErrors()) {
+ model.addAttribute(ModelKeys.WIDGET, widget);
+ return ViewNames.ADD_WIDGET_FORM;
+ }
+ widget.setWidgetStatus(WidgetStatus.PREVIEW);
+
+ final Widget storedWidget = widgetService.registerNewWidget(widget);
+ if (storedWidget == null) {
+ results.reject("page.addwidget.result.exists");
+ model.addAttribute(ModelKeys.WIDGET, widget);
+ return ViewNames.ADD_WIDGET_FORM;
+ }
+
+ model.addAttribute(ModelKeys.WIDGET, storedWidget);
+ return ViewNames.WIDGET;
+ }
}
Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/util/ViewNames.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/util/ViewNames.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/util/ViewNames.java (original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/util/ViewNames.java Wed Aug 24 12:25:29 2011
@@ -27,6 +27,7 @@ public class ViewNames {
public static final String HOME = "home";
public static final String STORE = "store";
public static final String WIDGET = "widget";
+ public static final String ADD_WIDGET_FORM = "addwidget";
public static final String NEW_ACCOUNT = "newaccount";
public static final String USER_PROFILE = "userProfile";
public static final String REDIRECT = "redirect:/";
Added: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/validator/NewWidgetValidator.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/validator/NewWidgetValidator.java?rev=1161066&view=auto
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/validator/NewWidgetValidator.java (added)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/validator/NewWidgetValidator.java Wed Aug 24 12:25:29 2011
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.rave.portal.web.validator;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.validator.UrlValidator;
+import org.apache.rave.portal.model.Widget;
+import org.springframework.validation.Errors;
+import org.springframework.validation.ValidationUtils;
+import org.springframework.validation.Validator;
+
+/**
+ * Validator for adding a new {@link Widget}
+ */
+public class NewWidgetValidator implements Validator {
+ private static final String FIELD_URL = "url";
+
+ private UrlValidator validator;
+
+ public NewWidgetValidator() {
+ super();
+ String[] allowedSchemes = {"http", "https"};
+ validator = new UrlValidator(allowedSchemes);
+ }
+
+ /**
+ * Supports {@link Widget}
+ * <p/>
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean supports(Class<?> clazz) {
+ return Widget.class.isAssignableFrom(clazz);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void validate(Object target, Errors errors) {
+ Widget widget = (Widget) target;
+
+ validateRequiredFields(errors);
+ validateUrlFields(widget, errors);
+ }
+
+ /**
+ * Checks if the required fields contain a value
+ *
+ * @param errors {@link Errors}
+ */
+ private void validateRequiredFields(Errors errors) {
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "widget.title.required");
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, FIELD_URL, "widget.url.required");
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "type", "widget.type.required");
+ }
+
+ /**
+ * Validates fields that may contain a URL
+ *
+ * @param widget {@link Widget} to validate
+ * @param errors {@link org.springframework.validation.Errors}
+ */
+ private void validateUrlFields(Widget widget, Errors errors) {
+ String url = widget.getUrl();
+ if (StringUtils.isNotBlank(url) && !validator.isValid(url)) {
+ errors.rejectValue(FIELD_URL, "widget.url.malformed");
+ }
+
+ String screenshotUrl = widget.getScreenshotUrl();
+ if (StringUtils.isNotBlank(screenshotUrl) && !validator.isValid(screenshotUrl)) {
+ errors.rejectValue("screenshotUrl", "widget.screenshotUrl.malformed");
+ }
+
+ String thumbnailUrl = widget.getThumbnailUrl();
+ if (StringUtils.isNotBlank(thumbnailUrl) && !validator.isValid(thumbnailUrl)) {
+ errors.rejectValue("thumbnailUrl", "widget.screenshotUrl.malformed");
+ }
+ }
+}
Modified: incubator/rave/trunk/rave-portal/src/main/resources/initial_data.sql
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/resources/initial_data.sql?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/resources/initial_data.sql (original)
+++ incubator/rave/trunk/rave-portal/src/main/resources/initial_data.sql Wed Aug 24 12:25:29 2011
@@ -75,8 +75,12 @@ values(set(@tabnews_widget_id, next valu
-- end widget data ----
-- hamster widget
-insert into widget (id, title, url, type, widget_status)
-values(set(@hamster_widget_id, next value for widget_id_seq), 'Pet Hamster', 'http://hosting.gmodules.com/ig/gadgets/file/112581010116074801021/hamster.xml', 'OpenSocial', 'PUBLISHED');
+insert into widget (id, title, url, type, widget_status, thumbnail_url)
+values(set(@hamster_widget_id, next value for widget_id_seq), 'Pet Hamster', 'http://hosting.gmodules.com/ig/gadgets/file/112581010116074801021/hamster.xml', 'OpenSocial', 'PUBLISHED', 'http://hosting.gmodules.com/ig/gadgets/file/112581010116074801021/hamsterThumb.png');
+
+-- another hamster widget
+insert into widget (id, title, url, type, description, author, widget_status, thumbnail_url, screenshot_url)
+values(set(@another_hamster_widget_id, next value for widget_id_seq), 'Herbie Hamster Virtual Pet', 'http://hosting.gmodules.com/ig/gadgets/file/109548057311228444554/hamster.xml', 'OpenSocial', 'A cute little hamster for you to feed and look after. Watch him follow your cursor around. Click on the more tab to treat him to a strawberry. Click him then put him on the wheel and watch him play! ***NEW: make Herbie hamster your very own!', 'Naj', 'PUBLISHED', 'http://sites.google.com/site/najartsist/pets-1/herbiet.png', 'http://sites.google.com/site/najartsist/herbie-hamster/herbie.png');
-- slideshare widget
insert into widget (id, title, url, type, widget_status)
Modified: incubator/rave/trunk/rave-portal/src/main/resources/messages.properties
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/resources/messages.properties?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/resources/messages.properties (original)
+++ incubator/rave/trunk/rave-portal/src/main/resources/messages.properties Wed Aug 24 12:25:29 2011
@@ -27,4 +27,40 @@ password.required=Password required
password.invalid.lenght=Password must be atleast 4 characters long
confirmPassword.required=Confirm Password required
-confirmPassword.mismatch=Password mismatch
\ No newline at end of file
+confirmPassword.mismatch=Password mismatch
+
+form.some.fields.required=Field marked with * are required
+
+page.general.back=Back to Rave
+page.general.titlesuffix= - Rave
+page.general.screenshot=screenshot
+page.general.thumbnail=thumbnail
+
+page.widget.addToPage=Add to Page
+page.widget.backToStore=Back to Store
+page.widget.widgetPreview=Widget Preview
+
+page.addwidget.pagetitle=Add new widget
+page.addwidget.form.header=Widget
+page.addwidget.form.submit=Add widget
+page.addwidget.result.exists=The widget you submitted already exists.
+page.addwidget.result.success=The widget was successfully added.
+
+widget.author=Author
+widget.description=Description
+widget.screenshotUrl=Screenshot
+widget.screenshotUrl.malformed=URL is malformed
+widget.thumbnailUrl=Thumbnail
+widget.thumbnailUrl.malformed=URL is malformed
+widget.title=Title
+widget.title.required=Title is required
+widget.type=Type
+widget.type.OpenSocial=OpenSocial
+widget.type.W3C=W3C Widget
+widget.type.required=Choose a widget type
+widget.url=Location (URL)
+widget.url.malformed=URL is malformed
+widget.url.required=URL is required
+widget.widgetStatus.PREVIEW=This widget is waiting for approval by the site administrator.
+widget.widgetStatus.PUBLISHED=
+
Modified: incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/applicationContext.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/applicationContext.xml?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/applicationContext.xml (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/applicationContext.xml Wed Aug 24 12:25:29 2011
@@ -111,7 +111,8 @@
<!-- Validators -->
<bean id="newAccountValidator" class="org.apache.rave.portal.web.validator.NewAccountValidator"/>
<bean id="userProfileValidator" class="org.apache.rave.portal.web.validator.UserProfileValidator"/>
-
+ <bean id="newWidgetValidator" class="org.apache.rave.portal.web.validator.NewWidgetValidator"/>
+
<!-- Configuring messages.properties file -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" p:basename="messages" />
Added: incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/addwidget.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/addwidget.jsp?rev=1161066&view=auto
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/addwidget.jsp (added)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/addwidget.jsp Wed Aug 24 12:25:29 2011
@@ -0,0 +1,109 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ --%>
+
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib tagdir="/WEB-INF/tags" prefix="rave" %>
+
+<fmt:bundle basename="messages"/>
+<fmt:message key="page.addwidget.pagetitle" var="pagetitle"/>
+<fmt:message key="page.general.titlesuffix" var="titlesuffix"/>
+<rave:rave_generic_page pageTitle="${pagetitle}${titlesuffix}">
+ <div id="header">
+ <div class="header-a">
+ <span class="backToPage">
+ <a href="<spring:url value="/index.html" />"><fmt:message key="page.general.back"/></a>
+ </span>
+ </div>
+ <h1><fmt:message key="page.addwidget.pagetitle"/></h1>
+ </div>
+
+ <div id="content">
+ <h2><fmt:message key="page.addwidget.form.header"/></h2>
+ <form:errors path="widget" cssClass="error" element="p"/>
+ <form:form id="newWidgetForm" action="doaddwidget" commandName="widget" method="POST">
+ <fieldset>
+ <p><fmt:message key="form.some.fields.required"/></p>
+
+ <p>
+ <form:label path="title"><fmt:message key="widget.title"/> *</form:label>
+ <form:input path="title" cssClass="long" required="required" autofocus="autofocus" />
+ <form:errors path="title" cssClass="error"/>
+ </p>
+
+ <p>
+ <spring:bind path="url">
+ <label for="url"><fmt:message key="widget.url"/> *</label>
+ <input type="url" name="url" id="url"
+ placeholder="http://example.com/widget.xml" required="required"
+ class="long" value="<c:out value="${widget.url}"/>"/>
+ </spring:bind>
+ <form:errors path="url" cssClass="error"/>
+ </p>
+
+ <p>
+ <label for="type1"><fmt:message key="widget.type"/> *</label>
+ <label for="type1" class="formradio"><form:radiobutton path="type" value="OpenSocial"/>
+ <fmt:message key="widget.type.OpenSocial"/></label>
+ <label for="type2" class="formradio"><form:radiobutton path="type" value="W3C"/>
+ <fmt:message key="widget.type.W3C"/></label>
+ <form:errors path="type" cssClass="error"/>
+ </p>
+
+ <p>
+ <form:label path="description"><fmt:message key="widget.description"/></form:label>
+ <form:input path="description" cssClass="long"/>
+ <form:errors path="description" cssClass="error"/>
+ </p>
+
+ <p>
+ <spring:bind path="thumbnailUrl">
+ <label for="thumbnailUrl"><fmt:message key="widget.thumbnailUrl"/></label>
+ <input type="url" name="thumbnailUrl" id="thumbnailUrl"
+ placeholder="http://example.com/thumbnail.png" class="long"
+ value="<c:out value="${widget.thumbnailUrl}"/>"/>
+ </spring:bind>
+ <form:errors path="thumbnailUrl" cssClass="error"/>
+ </p>
+
+ <p>
+ <spring:bind path="screenshotUrl">
+ <label for="screenshotUrl"><fmt:message key="widget.screenshotUrl"/></label>
+ <input type="url" name="screenshotUrl" id="screenshotUrl"
+ placeholder="http://example.com/screenshot.png" class="long"
+ value="<c:out value="${widget.screenshotUrl}"/>"/>
+ </spring:bind>
+ <form:errors path="screenshotUrl" cssClass="error"/>
+ </p>
+
+ <p>
+ <form:label path="author"><fmt:message key="widget.author"/></form:label>
+ <form:input path="author" cssClass="long"/>
+ <form:errors path="author" cssClass="error"/>
+ </p>
+ </fieldset>
+ <fieldset>
+ <fmt:message key="page.addwidget.form.submit" var="submit"/>
+ <input type="submit" value="${submit}"/>
+ </fieldset>
+ </form:form>
+ </div>
+</rave:rave_generic_page>
\ No newline at end of file
Modified: incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/store.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/store.jsp?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/store.jsp (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/store.jsp Wed Aug 24 12:25:29 2011
@@ -30,6 +30,11 @@
<a href="<spring:url value="/index.html" />">Back to Rave</a>
</span>
</div>
+ <div class="widget-a">
+ <span>
+ <a href="<spring:url value="store/addwidget"/>">Add widget</a>
+ </span>
+ </div>
<h1>Widget Store</h1>
</div>
Modified: incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/widget.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/widget.jsp?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/widget.jsp (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/widget.jsp Wed Aug 24 12:25:29 2011
@@ -20,87 +20,100 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib tagdir="/WEB-INF/tags" prefix="rave"%>
-<jsp:useBean id="widget" scope="request" class="org.apache.rave.portal.model.Widget" />
-
-<rave:rave_generic_page pageTitle="${widget.title} - Rave">
-<div id="header">
- <div class="header-a" >
+<%@ taglib tagdir="/WEB-INF/tags" prefix="rave" %>
+<jsp:useBean id="widget" scope="request" class="org.apache.rave.portal.model.Widget"/>
+<fmt:bundle basename="messages"/>
+<fmt:message var="titlesuffix" key="page.general.titlesuffix"/>
+<rave:rave_generic_page pageTitle="${widget.title}${titlesuffix}">
+ <div id="header">
+ <div class="header-a">
<span class="backToPage">
- <a href="<spring:url value="/index.html" />">Back to Rave</a>
- </span>
- </div>
- <div class="widget-a">
- <span>
- <a href="<spring:url value="/app/store?referringPageId=${referringPageId}" />">Back to Store</a>
+ <a href="<spring:url value="/index.html" />"><fmt:message key="page.general.back"/></a>
</span>
+ </div>
+ <c:if test="${not empty referringPageId}">
+ <div class="widget-a">
+ <span>
+ <a href="<spring:url value="/app/store?referringPageId=${referringPageId}" />">
+ <fmt:message key="page.widget.backToStore"/>
+ </a>
+ </span>
+ </div>
+ </c:if>
+ <h1><c:out value="${widget.title}"/></h1>
</div>
-</div>
-<div id="content">
- <div id="widget-content">
- <tr>
- <td class="widgetDetailLeft">
+ <div id="content">
+ <div id="widget-content">
+
+ <div class="widgetDetailLeft">
<c:if test="${not empty widget.thumbnailUrl}">
<img class="storeWidgetThumbnail"
- src="${widget.thumbnailUrl}"
- title="${widget.title}}"
- alt="thumbnail"
+ src="<c:out value="${widget.thumbnailUrl}"/>"
+ title="<c:out value="${widget.title}"/>"
+ alt="<fmt:message key="page.general.thumbnail"/>"
width="120" height="60"/>
</c:if>
+
<div class="widgetDetailMeta">
- <div class="widgetType">${widget.type}</div>
- <div class="widgetVersion"></div>
- <div class="widgetLastUpdated"></div>
+ <p><fmt:message key="widget.type.${widget.type}" /></p>
</div>
- </td>
- <td class="widgetDetailRight" style="vertical-align: top; padding-left: 10px;">
+ </div>
+
+ <div class="widgetDetailCenter">
<div class="storeWidgetDetail">
- <div class="secondaryPageItemTitle"
- style="display: inline-block; vertical-align: top; padding-top: 5px;">${widget.title}
- </div>
- <div id="widgetAdded_${widget.id}" class="storeButton">
- <button class="storeItemButton"
- id="addWidget_${widget.id}"
- onclick="rave.api.rpc.addWidgetToPage({widgetId: ${widget.id}, pageId: ${referringPageId}});">
- Add to Page
- </button>
- </div>
+ <span class="secondaryPageItemTitle"><c:out value="${widget.title}"/></span>
+ <c:choose>
+ <c:when test="${widget.widgetStatus eq 'PUBLISHED'}">
+ <div id="widgetAdded_${widget.id}" class="storeButton">
+ <button class="storeItemButton"
+ id="addWidget_${widget.id}"
+ onclick="rave.api.rpc.addWidgetToPage({widgetId: ${widget.id}, pageId: ${referringPageId}});">
+ <fmt:message key="page.widget.addToPage"/>
+ </button>
+ </div>
+ </c:when>
+ <c:when test="${widget.widgetStatus eq 'PREVIEW'}">
+ <p class="warn"><fmt:message key="widget.widgetStatus.PREVIEW"/></p>
+ </c:when>
+ </c:choose>
</div>
- <div class="storeWidgetAuthor">
- By:
- ${widget.author}
- </div>
- <div class="storeWidgetDesc" >
- ${widget.description}
- </div>
- </td>
- <td>
- <div class="widgetScreenshotTitle">Widget Preview</div>
- <div class="widgetScreenshot">
- <c:if test="${not empty widget.screenshotUrl}">
- <img src="${widget.screenshotUrl}"
- alt="screenshot"
- title="${widget.title} Screenshot"/>
- </c:if>
- </div>
- </td>
- </tr>
- </table>
+ <c:if test="${not empty widget.author}">
+ <p class="storeWidgetAuthor">
+ <fmt:message key="widget.author"/> <c:out value="${widget.author}"/>
+ </p>
+ </c:if>
+
+ <c:if test="${not empty widget.description}">
+ <p class="storeWidgetDesc"><c:out value="${widget.description}"/></p>
+ </c:if>
+ </div>
+
+ <div class="widgetDetailRight">
+ <c:if test="${not empty widget.screenshotUrl}">
+ <div class="widgetScreenshotTitle"><fmt:message key="page.widget.widgetPreview"/></div>
+ <div class="widgetScreenshot">
+ <img src="${widget.screenshotUrl}"
+ alt="<fmt:message key="page.general.screenshot"/>"
+ title="<c:out value="${widget.title}"/> <fmt:message key="page.general.screenshot"/>"/>
+ </div>
+ </c:if>
+ </div>
+ <div class="clear-float" > </div>
+ </div>
</div>
-</div>
-<script>
- var rave = rave || {
- getContext : function() {
- return "<spring:url value="/app/" />";
+ <script>
+ var rave = rave || {
+ getContext : function() {
+ return "<spring:url value="/app/" />";
+ }
}
- }
-</script>
-<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
-<script src="<spring:url value="/script/rave_api.js"/>"></script>
+ </script>
+ <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js"></script>
+ <script src="<spring:url value="/script/rave_api.js"/>"></script>
</rave:rave_generic_page>
Modified: incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css Wed Aug 24 12:25:29 2011
@@ -277,16 +277,31 @@ h1, h2, h3, h4, h5, h6 {
}
.widgetDetailLeft {
- width: 150px;
+ padding-left: 10px;
+ padding-right: 10px;
+ vertical-align: top;
+ width: 150px;
+ float: left;
+}
+
+.widgetDetailCenter {
+ padding-left: 10px;
+ padding-right: 10px;
vertical-align: top;
+ float: left;
+ width: 50%;
}
.widgetDetailRight {
- width: 60%;
- vertical-align: top;
- padding-left: 10px;
+ padding: 0 10px;
+ width: 300px;
+ vertical-align: top;
+ float: left;
}
+.widgetScreenshot img {
+ max-width: 280px;
+}
ul.storeItems {
padding: 0;
}
@@ -424,6 +439,8 @@ button.widget-toolbar-btn-prefs {
display: none;
}
+/* Form fields */
+
fieldset{
margin: 0;
border:none
@@ -432,23 +449,43 @@ p label {
width: 120px;
float: left;
display: block;
+ position: relative;
+}
+
+label.formradio {
+ float: none;
+ left: 0;
+ margin-left: 120px;
+ margin-bottom: 0.4em;
+ margin-right: 0;
+ position: static;
+ top: auto;
+ width: auto;
}
input.long {
width:400px;
}
+
/* Associated with JQuery validation CSS */
.error {
color: #ff0000;
}
-label.error {
+span.error, label.error {
font-size: 10px;
display: block;
float: none;
margin: 0.5em 0 auto 120px;
}
+
+.warn {
+ font-weight: bold;
+}
+
+/* End of form fields */
+
/*
.rave-ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: #F2F2F2; height: 800px; }
.rave-ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; background: #666666}
Modified: incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/repository/JpaWidgetRepositoryTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/repository/JpaWidgetRepositoryTest.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/repository/JpaWidgetRepositoryTest.java (original)
+++ incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/repository/JpaWidgetRepositoryTest.java Wed Aug 24 12:25:29 2011
@@ -29,6 +29,8 @@ import org.apache.rave.portal.model.Widg
import org.apache.rave.portal.model.WidgetStatus;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -37,6 +39,7 @@ import org.springframework.transaction.a
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
@@ -52,6 +55,8 @@ import static org.junit.Assert.assertTha
"classpath:portal-test-applicationContext.xml"})
public class JpaWidgetRepositoryTest {
+ private static Logger logger = LoggerFactory.getLogger(JpaWidgetRepositoryTest.class);
+
@PersistenceContext
private EntityManager sharedManager;
@@ -72,6 +77,25 @@ public class JpaWidgetRepositoryTest {
}
@Test
+ public void getByUrl_valid() {
+ final String widgetUrl =
+ "http://hosting.gmodules.com/ig/gadgets/file/112581010116074801021/hamster.xml";
+ final Widget widget = repository.getByUrl(widgetUrl);
+ assertNotNull(widget);
+ assertEquals(widgetUrl, widget.getUrl());
+ }
+
+ @Test
+ public void getByUrl_empty() {
+ try{
+ repository.getByUrl("");
+ fail();
+ } catch (IllegalArgumentException e) {
+ logger.debug("Expected to fail on empty URL", e.getMessage());
+ }
+ }
+
+ @Test
public void getByFreeTextSearch() {
List<Widget> widgets = repository.getByFreeTextSearch("gAdGet", 1, 1);
assertEquals(1, widgets.size());
Modified: incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/WidgetServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/WidgetServiceTest.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/WidgetServiceTest.java (original)
+++ incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/WidgetServiceTest.java Wed Aug 24 12:25:29 2011
@@ -37,6 +37,8 @@ import static org.hamcrest.CoreMatchers.
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
@@ -167,4 +169,45 @@ public class WidgetServiceTest {
}
+ @Test
+ public void getWidgetByUrl() {
+ final String widgetUrl =
+ "http://hosting.gmodules.com/ig/gadgets/file/112581010116074801021/hamster.xml";
+ Widget widget = new Widget();
+ widget.setUrl(widgetUrl);
+ expect(repository.getByUrl(widgetUrl)).andReturn(widget);
+ replay(repository);
+
+ Widget result = service.getWidgetByUrl(widgetUrl);
+ assertNotNull(result);
+ assertEquals(result.getUrl(), widgetUrl);
+ }
+
+ @Test
+ public void registerNewWidget() {
+ final String widgetUrl =
+ "http://example.com/newwidget.xml";
+ Widget widget = new Widget();
+ widget.setUrl(widgetUrl);
+ expect(repository.getByUrl(widgetUrl)).andReturn(null);
+ expect(repository.save(widget)).andReturn(widget);
+ replay(repository);
+
+ Widget savedWidget = service.registerNewWidget(widget);
+ assertNotNull(savedWidget);
+ assertEquals(widget.getId(), savedWidget.getId());
+ }
+
+ @Test
+ public void registerExistingWidgetAsNew() {
+ final String widgetUrl =
+ "http://hosting.gmodules.com/ig/gadgets/file/112581010116074801021/hamster.xml";
+ Widget widget = new Widget();
+ widget.setUrl(widgetUrl);
+ expect(repository.getByUrl(widgetUrl)).andReturn(widget);
+ replay(repository);
+
+ Widget noWidget = service.registerNewWidget(widget);
+ assertNull("Widget already exists", noWidget);
+ }
}
Modified: incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java (original)
+++ incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java Wed Aug 24 12:25:29 2011
@@ -19,20 +19,29 @@
package org.apache.rave.portal.web.controller;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.rave.portal.model.Widget;
+import org.apache.rave.portal.model.WidgetStatus;
import org.apache.rave.portal.model.util.SearchResult;
import org.apache.rave.portal.service.WidgetService;
import org.apache.rave.portal.web.util.ModelKeys;
import org.apache.rave.portal.web.util.ViewNames;
+import org.apache.rave.portal.web.validator.NewWidgetValidator;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
+import org.springframework.validation.BeanPropertyBindingResult;
+import org.springframework.validation.BindingResult;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
@@ -40,9 +49,8 @@ import static org.easymock.EasyMock.veri
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.sameInstance;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+
/**
* Test class for {@link WidgetStoreController}
@@ -57,7 +65,8 @@ public class WidgetStoreControllerTest {
@Before
public void setup() {
widgetService = createNiceMock(WidgetService.class);
- controller = new WidgetStoreController(widgetService);
+ NewWidgetValidator widgetValidator = new NewWidgetValidator();
+ controller = new WidgetStoreController(widgetService, widgetValidator);
}
@Test
@@ -100,7 +109,7 @@ public class WidgetStoreControllerTest {
Model model = new ExtendedModelMap();
String searchTerm = "gAdGet";
-
+
int offset = 0;
int pagesize = 10;
int totalResults = 2;
@@ -115,14 +124,77 @@ public class WidgetStoreControllerTest {
.andReturn(result);
replay(widgetService);
- String view = controller.viewSearchResult(model,REFERRER_ID, searchTerm, offset);
+ String view = controller.viewSearchResult(model, REFERRER_ID, searchTerm, offset);
verify(widgetService);
assertEquals(ViewNames.STORE, view);
- final Map<String,Object> modelMap = model.asMap();
+ final Map<String, Object> modelMap = model.asMap();
assertEquals(searchTerm, modelMap.get(ModelKeys.SEARCH_TERM));
assertTrue(model.containsAttribute(ModelKeys.WIDGETS));
assertEquals(offset, modelMap.get(ModelKeys.OFFSET));
assertEquals(result, modelMap.get(ModelKeys.WIDGETS));
}
+
+ @Test
+ public void startAddWidget() {
+ final Model model = new ExtendedModelMap();
+ final String view = controller.viewAddWidgetForm(model);
+ assertEquals("View for add widget form", ViewNames.ADD_WIDGET_FORM, view);
+ final Widget widget = (Widget) model.asMap().get(ModelKeys.WIDGET);
+ assertNotNull("New widget in Model", widget);
+ }
+
+ @Test
+ public void doAddWidget() {
+ final String widgetUrl = "http://example.com/newwidget.xml";
+ final Model model = new ExtendedModelMap();
+ final Widget widget = new Widget();
+ widget.setTitle("Widget title");
+ widget.setUrl(widgetUrl);
+ widget.setType("OpenSocial");
+ final BindingResult errors = new BeanPropertyBindingResult(widget, "widget");
+
+ expect(widgetService.registerNewWidget(widget)).andReturn(widget);
+ replay(widgetService);
+ String view = controller.viewAddWidgetResult(widget, errors, model);
+ verify(widgetService);
+
+ assertEquals(ViewNames.WIDGET, view);
+ assertFalse("Valid widget data", errors.hasErrors());
+ final Widget fromModel = (Widget) model.asMap().get(ModelKeys.WIDGET);
+ assertEquals(widget, fromModel);
+ assertEquals("New widget has state preview", WidgetStatus.PREVIEW, fromModel.getWidgetStatus());
+ }
+
+ @Test
+ public void doAddWidget_existing() {
+ final String widgetUrl = "http://example.com/existingwidget.xml";
+ final Model model = new ExtendedModelMap();
+ final Widget widget = new Widget();
+ widget.setTitle("Widget title");
+ widget.setUrl(widgetUrl);
+ widget.setType("OpenSocial");
+ final BindingResult errors = new BeanPropertyBindingResult(widget, "widget");
+
+ expect(widgetService.registerNewWidget(widget)).andReturn(null);
+ replay(widgetService);
+ String view = controller.viewAddWidgetResult(widget, errors, model);
+ verify(widgetService);
+
+ assertEquals(ViewNames.ADD_WIDGET_FORM, view);
+ assertTrue("Valid widget data", errors.hasErrors());
+ assertNotNull(model.asMap().get(ModelKeys.WIDGET));
+ }
+
+ @Test
+ public void doAddWidget_invalid() {
+ final Widget widget = new Widget();
+ widget.setTitle("Not enough data");
+ final Model model = new ExtendedModelMap();
+ final BindingResult errors = new BeanPropertyBindingResult(widget, "widget");
+ String view = controller.viewAddWidgetResult(widget, errors, model);
+ assertTrue("Invalid widget data", errors.hasErrors());
+ assertEquals(ViewNames.ADD_WIDGET_FORM, view);
+ assertEquals(widget, model.asMap().get(ModelKeys.WIDGET));
+ }
}
Added: incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/validator/NewWidgetValidatorTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/validator/NewWidgetValidatorTest.java?rev=1161066&view=auto
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/validator/NewWidgetValidatorTest.java (added)
+++ incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/validator/NewWidgetValidatorTest.java Wed Aug 24 12:25:29 2011
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.rave.portal.web.validator;
+
+import org.apache.rave.portal.model.Widget;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.validation.BindException;
+import org.springframework.validation.Errors;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * Test class for {@link NewWidgetValidator}
+ */
+public class NewWidgetValidatorTest {
+
+ private static final String VALID_TITLE = "My widget";
+ private static final String VALID_URL = "http://example.com/widget.xml";
+ private static final String VALID_TYPE = "OpenSocial";
+ private static final String WIDGET = "widget";
+
+ private NewWidgetValidator newWidgetValidator;
+
+ @Test
+ public void testSupports() throws Exception {
+ assertTrue("Supports org.apache.rave.portal.model.Widget", newWidgetValidator.supports(Widget.class));
+ }
+
+ @Test
+ public void testValidateValidFormData() throws Exception {
+ Widget widget = new Widget();
+ widget.setTitle(VALID_TITLE);
+ widget.setUrl(VALID_URL);
+ widget.setType(VALID_TYPE);
+ Errors errors = new BindException(widget, WIDGET);
+
+ newWidgetValidator.validate(widget, errors);
+ assertFalse("No validation errors", errors.hasErrors());
+ }
+
+ @Test
+ public void testValidationFailsOnEmptyValues() {
+ Widget widget = new Widget();
+ Errors errors = new BindException(widget, WIDGET);
+
+ newWidgetValidator.validate(widget, errors);
+
+ assertEquals(3, errors.getErrorCount());
+ }
+
+ @Test
+ public void testValidationFailsOnInvalidUrl() {
+ Widget widget = new Widget();
+ widget.setTitle(VALID_TITLE);
+ widget.setType(VALID_TYPE);
+ widget.setUrl("http:/this.is/invalid?url=true&reject=true");
+ widget.setScreenshotUrl("https://///invalid/screenshot");
+ widget.setThumbnailUrl("thumbnail");
+ Errors errors = new BindException(widget, WIDGET);
+
+ newWidgetValidator.validate(widget, errors);
+ assertEquals(3, errors.getErrorCount());
+ assertNotNull("Field error on url", errors.getFieldError("url"));
+ assertNotNull("Field error on screenshot url", errors.getFieldError("screenshotUrl"));
+ assertNotNull("Field error on thumbnail url", errors.getFieldError("thumbnailUrl"));
+ }
+
+ @Before
+ public void setup() {
+ newWidgetValidator = new NewWidgetValidator();
+ }
+}
Modified: incubator/rave/trunk/rave-portal/src/test/resources/portal-test-applicationContext.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/resources/portal-test-applicationContext.xml?rev=1161066&r1=1161065&r2=1161066&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/resources/portal-test-applicationContext.xml (original)
+++ incubator/rave/trunk/rave-portal/src/test/resources/portal-test-applicationContext.xml Wed Aug 24 12:25:29 2011
@@ -109,6 +109,7 @@
<!-- Validators -->
<bean id="newAccountValidator" class="org.apache.rave.portal.web.validator.NewAccountValidator"/>
<bean id="userProfileValidator" class="org.apache.rave.portal.web.validator.UserProfileValidator"/>
+ <bean id="newWidgetValidator" class="org.apache.rave.portal.web.validator.NewWidgetValidator"/>
<!-- Configuring messages.properties file -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"