Thu 5:10 commit after resolving some conflicts due to merge from trunk.
This commit is contained in:
commit
e866fcc7e5
23 changed files with 1222 additions and 272 deletions
|
@ -488,7 +488,8 @@
|
||||||
<field name="nameLowercase" type="string" indexed="true" stored="true" multiValued="true"/>
|
<field name="nameLowercase" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||||
<field name="nameUnstemmed" type="text" indexed="true" stored="false" multiValued="true"/>
|
<field name="nameUnstemmed" type="text" indexed="true" stored="false" multiValued="true"/>
|
||||||
<field name="nameStemmed" type="text" indexed="true" stored="false" multiValued="true"/>
|
<field name="nameStemmed" type="text" indexed="true" stored="false" multiValued="true"/>
|
||||||
|
<field name="acNameUnstemmed" type="textUnstemmed" indexed="true" stored="false" multiValued="true"/>
|
||||||
|
<field name="acNameStemmed" type="text" indexed="true" stored="false" multiValued="true"/>
|
||||||
<field name="indexedTime" type="string" indexed="true" stored="true" multiValued="true"/>
|
<field name="indexedTime" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||||
|
|
||||||
<field name="ALLTEXT" type="text" indexed="true" stored="false" multiValued="true"/>
|
<field name="ALLTEXT" type="text" indexed="true" stored="false" multiValued="true"/>
|
||||||
|
|
|
@ -385,7 +385,10 @@
|
||||||
be based on the last SolrCore to be initialized.
|
be based on the last SolrCore to be initialized.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<maxBooleanClauses>1024</maxBooleanClauses>
|
-->
|
||||||
|
<!-- Increasing to handle large wildcard queries used in IndividualListController.
|
||||||
|
See VIVO-384. -->
|
||||||
|
<maxBooleanClauses>50000</maxBooleanClauses>
|
||||||
|
|
||||||
|
|
||||||
<!-- Solr Internal Query Caches
|
<!-- Solr Internal Query Caches
|
||||||
|
@ -1393,7 +1396,45 @@
|
||||||
</fragmentsBuilder>
|
</fragmentsBuilder>
|
||||||
</highlighting>
|
</highlighting>
|
||||||
</searchComponent>
|
</searchComponent>
|
||||||
|
<!-- Autocomplete -->
|
||||||
|
<!--
|
||||||
|
<searchComponent class="solr.SpellCheckComponent" name="suggest">
|
||||||
|
<lst name="spellchecker">
|
||||||
|
<str name="name">suggest</str>
|
||||||
|
<str name="classname">org.apache.solr.spelling.suggest.Suggester</str>
|
||||||
|
<str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str>
|
||||||
|
-->
|
||||||
|
<!-- Alternatives to lookupImpl:
|
||||||
|
org.apache.solr.spelling.suggest.fst.FSTLookup [finite state automaton]
|
||||||
|
org.apache.solr.spelling.suggest.jaspell.JaspellLookup [default, jaspell-based]
|
||||||
|
org.apache.solr.spelling.suggest.tst.TSTLookup [ternary trees]
|
||||||
|
-->
|
||||||
|
<!-- the indexed field to derive suggestions from -->
|
||||||
|
<!--
|
||||||
|
<str name="field">nameLowercase</str>
|
||||||
|
<float name="threshold">0.005</float>
|
||||||
|
<str name="buildOnCommit">false</str>
|
||||||
|
<str name="storeDir">suggest</str>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<str name="sourceLocation">american-english</str>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
</lst>
|
||||||
|
</searchComponent>
|
||||||
|
<requestHandler class="org.apache.solr.handler.component.SearchHandler" name="/suggest">
|
||||||
|
<lst name="defaults">
|
||||||
|
<str name="spellcheck">true</str>
|
||||||
|
<str name="spellcheck.dictionary">suggest</str>
|
||||||
|
<str name="spellcheck.onlyMorePopular">false</str>
|
||||||
|
<str name="spellcheck.count">100</str>
|
||||||
|
<str name="spellcheck.collate">false</str>
|
||||||
|
</lst>
|
||||||
|
<arr name="components">
|
||||||
|
<str>suggest</str>
|
||||||
|
</arr>
|
||||||
|
</requestHandler>
|
||||||
|
-->
|
||||||
<!-- Update Processors
|
<!-- Update Processors
|
||||||
|
|
||||||
Chains of Update Processor Factories for dealing with Update
|
Chains of Update Processor Factories for dealing with Update
|
||||||
|
|
|
@ -763,12 +763,12 @@
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>UserAccountsList</servlet-name>
|
<servlet-name>UserAccounts</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsListController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsController</servlet-class>
|
||||||
</servlet>
|
</servlet>
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>UserAccountsList</servlet-name>
|
<servlet-name>UserAccounts</servlet-name>
|
||||||
<url-pattern>/listUserAccounts</url-pattern>
|
<url-pattern>/userAccounts/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
|
@ -875,6 +875,12 @@
|
||||||
<servlet-name>IndividualListController</servlet-name>
|
<servlet-name>IndividualListController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController</servlet-class>
|
||||||
</servlet>
|
</servlet>
|
||||||
|
<!--
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>IndividualListController</servlet-name>
|
||||||
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.SolrIndividualListController</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
-->
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>IndividualListController</servlet-name>
|
<servlet-name>IndividualListController</servlet-name>
|
||||||
<url-pattern>/individuallist</url-pattern>
|
<url-pattern>/individuallist</url-pattern>
|
||||||
|
@ -976,12 +982,6 @@
|
||||||
<servlet-name>JSON Service</servlet-name>
|
<servlet-name>JSON Service</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.JSONServlet</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.JSONServlet</servlet-class>
|
||||||
</servlet>
|
</servlet>
|
||||||
<!--
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>JSON Service</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.SolrJsonServlet</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
-->
|
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>JSON Service</servlet-name>
|
<servlet-name>JSON Service</servlet-name>
|
||||||
<url-pattern>/dataservice</url-pattern>
|
<url-pattern>/dataservice</url-pattern>
|
||||||
|
|
|
@ -197,18 +197,20 @@ public class VitroHttpServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If logging is set to the TRACE level, dump the HTTP headers on the
|
* If logging on the subclass is set to the TRACE level, dump the HTTP
|
||||||
* request.
|
* headers on the request.
|
||||||
*/
|
*/
|
||||||
private void dumpRequestHeaders(HttpServletRequest req) {
|
private void dumpRequestHeaders(HttpServletRequest req) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Enumeration<String> names = req.getHeaderNames();
|
Enumeration<String> names = req.getHeaderNames();
|
||||||
|
|
||||||
log.trace("----------------------request:" + req.getRequestURL());
|
Log subclassLog = LogFactory.getLog(this.getClass());
|
||||||
|
subclassLog.trace("----------------------request:"
|
||||||
|
+ req.getRequestURL());
|
||||||
while (names.hasMoreElements()) {
|
while (names.hasMoreElements()) {
|
||||||
String name = names.nextElement();
|
String name = names.nextElement();
|
||||||
if (!BORING_HEADERS.contains(name)) {
|
if (!BORING_HEADERS.contains(name)) {
|
||||||
log.trace(name + "=" + req.getHeader(name));
|
subclassLog.trace(name + "=" + req.getHeader(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public class UserAccountsAddPage extends UserAccountsPage {
|
||||||
|
private static final String PARAMETER_SUBMIT = "submitAdd";
|
||||||
|
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
|
||||||
|
private static final String PARAMETER_FIRST_NAME = "firstName";
|
||||||
|
private static final String PARAMETER_LAST_NAME = "lastName";
|
||||||
|
private static final String PARAMETER_ROLE = "role";
|
||||||
|
private static final String PARAMETER_ASSOCIATE_WITH_PROFILE = "associate";
|
||||||
|
|
||||||
|
private static final String ERROR_NO_EMAIL = "errorEmailIsEmpty";
|
||||||
|
private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse";
|
||||||
|
private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty";
|
||||||
|
private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty";
|
||||||
|
private static final String ERROR_NO_ROLE = "errorNoRoleSelected";
|
||||||
|
|
||||||
|
private static final String TEMPLATE_NAME = "userAccounts-add.ftl";
|
||||||
|
|
||||||
|
/* The request parameters */
|
||||||
|
private boolean submit;
|
||||||
|
private String emailAddress = "";
|
||||||
|
private String firstName = "";
|
||||||
|
private String lastName = "";
|
||||||
|
private String selectedRoleUri = "";
|
||||||
|
private boolean associateWithProfile;
|
||||||
|
|
||||||
|
/* The result of validating a "submit" request. */
|
||||||
|
private String errorCode = "";
|
||||||
|
|
||||||
|
public UserAccountsAddPage(VitroRequest vreq) {
|
||||||
|
super(vreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseParametersAndValidate() {
|
||||||
|
parseRequestParameters();
|
||||||
|
|
||||||
|
if (submit) {
|
||||||
|
validateParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseRequestParameters() {
|
||||||
|
submit = isFlagOnRequest(PARAMETER_SUBMIT);
|
||||||
|
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
|
||||||
|
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
|
||||||
|
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
|
||||||
|
selectedRoleUri = getRoleChoices();
|
||||||
|
associateWithProfile = getAssociateFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubmit() {
|
||||||
|
return submit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateParameters() {
|
||||||
|
if (emailAddress.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_EMAIL;
|
||||||
|
} else if (isEmailInUse()) {
|
||||||
|
errorCode = ERROR_EMAIL_IN_USE;
|
||||||
|
} else if (firstName.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_FIRST_NAME;
|
||||||
|
} else if (lastName.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_LAST_NAME;
|
||||||
|
} else if (selectedRoleUri.isEmpty()) {
|
||||||
|
errorCode = ERROR_NO_ROLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEmailInUse() {
|
||||||
|
return userAccountsDao.getUserAccountByEmail(emailAddress) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return errorCode.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserAccount createNewAccount() {
|
||||||
|
UserAccount u = new UserAccount();
|
||||||
|
u.setEmailAddress(emailAddress);
|
||||||
|
u.setFirstName(firstName);
|
||||||
|
u.setLastName(lastName);
|
||||||
|
u.setExternalAuthId("");
|
||||||
|
|
||||||
|
u.setMd5Password("");
|
||||||
|
u.setOldPassword("");
|
||||||
|
u.setPasswordChangeRequired(false);
|
||||||
|
u.setPasswordLinkExpires(0);
|
||||||
|
u.setLoginCount(0);
|
||||||
|
u.setStatus(Status.INACTIVE);
|
||||||
|
|
||||||
|
u.setPermissionSetUris(Collections.singleton(selectedRoleUri));
|
||||||
|
|
||||||
|
String uri = userAccountsDao.insertUserAccount(u);
|
||||||
|
return userAccountsDao.getUserAccountByUri(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** What role are they asking for? */
|
||||||
|
private String getRoleChoices() {
|
||||||
|
String[] roles = vreq.getParameterValues(PARAMETER_ROLE);
|
||||||
|
if ((roles == null) || (roles.length == 0)) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return roles[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Are they associating with an Individual profile? */
|
||||||
|
private boolean getAssociateFlag() {
|
||||||
|
return "yes".equals(getStringParameter(
|
||||||
|
PARAMETER_ASSOCIATE_WITH_PROFILE, "no"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseValues showPage() {
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
body.put("emailAddress", emailAddress);
|
||||||
|
body.put("firstName", firstName);
|
||||||
|
body.put("lastName", lastName);
|
||||||
|
body.put("selectedRole", selectedRoleUri);
|
||||||
|
body.put("associate", associateWithProfile);
|
||||||
|
|
||||||
|
body.put("roles", buildRolesList());
|
||||||
|
|
||||||
|
body.put("formUrls", buildUrlsMap());
|
||||||
|
|
||||||
|
if (!errorCode.isEmpty()) {
|
||||||
|
body.put(errorCode, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageUserAccounts;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parcel out the different actions required of the UserAccounts GUI.
|
||||||
|
*/
|
||||||
|
public class UserAccountsController extends FreemarkerHttpServlet {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(UserAccountsController.class);
|
||||||
|
|
||||||
|
private static final String ACTION_ADD = "/add";
|
||||||
|
private static final String ACTION_DELETE = "/delete";
|
||||||
|
private static final String ACTION_EDIT = "/edit";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Actions requiredActions(VitroRequest vreq) {
|
||||||
|
return new Actions(new ManageUserAccounts());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ResponseValues processRequest(VitroRequest vreq) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
dumpRequestParameters(vreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
String action = vreq.getPathInfo();
|
||||||
|
log.debug("action = '" + action + "'");
|
||||||
|
|
||||||
|
if (ACTION_ADD.equals(action)) {
|
||||||
|
UserAccountsAddPage page = new UserAccountsAddPage(vreq);
|
||||||
|
page.parseParametersAndValidate();
|
||||||
|
if (page.isSubmit() && page.isValid()) {
|
||||||
|
return addAccountAndShowList(vreq, page);
|
||||||
|
} else {
|
||||||
|
return page.showPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (ACTION_EDIT.equals(action)) {
|
||||||
|
return new UserAccountsEditPage(vreq).showPage();
|
||||||
|
|
||||||
|
} else if (ACTION_DELETE.equals(action)) {
|
||||||
|
UserAccountsDeleter deleter = new UserAccountsDeleter(vreq);
|
||||||
|
Collection<String> deletedUris = deleter.delete();
|
||||||
|
|
||||||
|
return new UserAccountsListPage(vreq)
|
||||||
|
.showPageWithDeletions(deletedUris);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
UserAccountsListPage page = new UserAccountsListPage(vreq);
|
||||||
|
return page.showPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseValues addAccountAndShowList(VitroRequest vreq,
|
||||||
|
UserAccountsAddPage addPage) {
|
||||||
|
UserAccount userAccount = addPage.createNewAccount();
|
||||||
|
|
||||||
|
UserAccountsListPage listPage = new UserAccountsListPage(vreq);
|
||||||
|
return listPage.showPageWithNewAccount(userAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public class UserAccountsDeleter extends UserAccountsPage {
|
||||||
|
|
||||||
|
protected UserAccountsDeleter(VitroRequest vreq) {
|
||||||
|
super(vreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public Collection<String> delete() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new RuntimeException("UserAccountsDeleter.delete() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public class UserAccountsEditPage extends UserAccountsPage {
|
||||||
|
private static final String TEMPLATE_NAME = "userAccounts-edit.ftl";
|
||||||
|
|
||||||
|
public UserAccountsEditPage(VitroRequest vreq) {
|
||||||
|
super(vreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseValues showPage() {
|
||||||
|
return new TemplateResponseValues(TEMPLATE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -5,41 +5,32 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
import static edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelectionCriteria.DEFAULT_ACCOUNTS_PER_PAGE;
|
import static edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelectionCriteria.DEFAULT_ACCOUNTS_PER_PAGE;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import com.hp.hpl.jena.ontology.OntModel;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageUserAccounts;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
|
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction;
|
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
|
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the paginated list of User Accounts.
|
* Handle the List page.
|
||||||
*/
|
*/
|
||||||
public class UserAccountsListController extends FreemarkerHttpServlet {
|
public class UserAccountsListPage extends UserAccountsPage {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
.getLog(UserAccountsListController.class);
|
.getLog(UserAccountsListPage.class);
|
||||||
|
|
||||||
public static final String PARAMETER_ACCOUNTS_PER_PAGE = "accountsPerPage";
|
public static final String PARAMETER_ACCOUNTS_PER_PAGE = "accountsPerPage";
|
||||||
public static final String PARAMETER_PAGE_INDEX = "pageIndex";
|
public static final String PARAMETER_PAGE_INDEX = "pageIndex";
|
||||||
|
@ -54,67 +45,19 @@ public class UserAccountsListController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
private static final String TEMPLATE_NAME = "userAccounts-list.ftl";
|
private static final String TEMPLATE_NAME = "userAccounts-list.ftl";
|
||||||
|
|
||||||
private OntModel userAccountsModel;
|
private UserAccountsSelectionCriteria criteria = UserAccountsSelectionCriteria.DEFAULT_CRITERIA;
|
||||||
private UserAccountsDao userAccountsDao;
|
|
||||||
|
|
||||||
@Override
|
public UserAccountsListPage(VitroRequest vreq) {
|
||||||
public void init() throws ServletException {
|
super(vreq);
|
||||||
super.init();
|
|
||||||
|
|
||||||
OntModelSelector oms = (OntModelSelector) getServletContext()
|
|
||||||
.getAttribute("baseOntModelSelector");
|
|
||||||
userAccountsModel = oms.getUserAccountsModel();
|
|
||||||
|
|
||||||
WebappDaoFactory wdf = (WebappDaoFactory) getServletContext()
|
|
||||||
.getAttribute("webappDaoFactory");
|
|
||||||
userAccountsDao = wdf.getUserAccountsDao();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Actions requiredActions(VitroRequest vreq) {
|
|
||||||
return new Actions(new ManageUserAccounts());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assume the default criteria for display. Modify the criteria based on
|
* Build the criteria from the request parameters.
|
||||||
* parameters in the request. Get the selected accounts and display them.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
public void parseParameters() {
|
||||||
protected ResponseValues processRequest(VitroRequest vreq) {
|
int accountsPerPage = getIntegerParameter(PARAMETER_ACCOUNTS_PER_PAGE,
|
||||||
if (log.isDebugEnabled()) {
|
DEFAULT_ACCOUNTS_PER_PAGE);
|
||||||
dumpRequestParameters(vreq);
|
int pageIndex = getIntegerParameter(PARAMETER_PAGE_INDEX, 1);
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> body = new HashMap<String, Object>();
|
|
||||||
|
|
||||||
UserAccountsSelectionCriteria criteria = buildCriteria(vreq);
|
|
||||||
|
|
||||||
body.put("accountsPerPage", criteria.getAccountsPerPage());
|
|
||||||
body.put("pageIndex", criteria.getPageIndex());
|
|
||||||
body.put("orderDirection", criteria.getOrderBy().getDirection().keyword);
|
|
||||||
body.put("orderField", criteria.getOrderBy().getField().name);
|
|
||||||
body.put("roleFilterUri", criteria.getRoleFilterUri());
|
|
||||||
body.put("searchTerm", criteria.getSearchTerm());
|
|
||||||
|
|
||||||
UserAccountsSelection selection = UserAccountsSelector.select(
|
|
||||||
userAccountsModel, criteria);
|
|
||||||
|
|
||||||
body.put("accounts", wrapUserAccounts(selection));
|
|
||||||
body.put("total", selection.getResultCount());
|
|
||||||
body.put("page", buildPageMap(selection));
|
|
||||||
|
|
||||||
body.put("formUrl", buildFormUrl(vreq));
|
|
||||||
body.put("roles", buildRolesList());
|
|
||||||
|
|
||||||
body.put("messages", buildMessagesMap(vreq));
|
|
||||||
|
|
||||||
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserAccountsSelectionCriteria buildCriteria(VitroRequest vreq) {
|
|
||||||
int accountsPerPage = getIntegerParameter(vreq,
|
|
||||||
PARAMETER_ACCOUNTS_PER_PAGE, DEFAULT_ACCOUNTS_PER_PAGE);
|
|
||||||
int pageIndex = getIntegerParameter(vreq, PARAMETER_PAGE_INDEX, 1);
|
|
||||||
|
|
||||||
Direction orderingDirection = Direction.fromKeyword(vreq
|
Direction orderingDirection = Direction.fromKeyword(vreq
|
||||||
.getParameter(PARAMETER_ORDERING_DIRECTION));
|
.getParameter(PARAMETER_ORDERING_DIRECTION));
|
||||||
|
@ -123,33 +66,72 @@ public class UserAccountsListController extends FreemarkerHttpServlet {
|
||||||
UserAccountsOrdering ordering = new UserAccountsOrdering(orderingField,
|
UserAccountsOrdering ordering = new UserAccountsOrdering(orderingField,
|
||||||
orderingDirection);
|
orderingDirection);
|
||||||
|
|
||||||
String roleFilterUri = getStringParameter(vreq,
|
String roleFilterUri = getStringParameter(PARAMETER_ROLE_FILTER_URI, "");
|
||||||
PARAMETER_ROLE_FILTER_URI, "");
|
String searchTerm = getStringParameter(PARAMETER_SEARCH_TERM, "");
|
||||||
String searchTerm = getStringParameter(vreq, PARAMETER_SEARCH_TERM, "");
|
|
||||||
|
|
||||||
return new UserAccountsSelectionCriteria(accountsPerPage, pageIndex,
|
criteria = new UserAccountsSelectionCriteria(accountsPerPage,
|
||||||
ordering, roleFilterUri, searchTerm);
|
pageIndex, ordering, roleFilterUri, searchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getStringParameter(VitroRequest vreq, String key,
|
/**
|
||||||
String defaultValue) {
|
* Build the selection criteria from the request, select the accounts, and
|
||||||
String value = vreq.getParameter(key);
|
* create the ResponseValues to display the page.
|
||||||
return (value == null) ? defaultValue : value;
|
*/
|
||||||
|
public ResponseValues showPage() {
|
||||||
|
UserAccountsSelection selection = UserAccountsSelector.select(
|
||||||
|
userAccountsModel, criteria);
|
||||||
|
Map<String, Object> body = buildTemplateBodyMap(selection);
|
||||||
|
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getIntegerParameter(VitroRequest vreq, String key,
|
/**
|
||||||
int defaultValue) {
|
* We just came from adding a new account. Show the list with a message.
|
||||||
String value = vreq.getParameter(key);
|
*/
|
||||||
if (value == null) {
|
public ResponseValues showPageWithNewAccount(UserAccount userAccount) {
|
||||||
return defaultValue;
|
UserAccountsSelection selection = UserAccountsSelector.select(
|
||||||
|
userAccountsModel, criteria);
|
||||||
|
Map<String, Object> body = buildTemplateBodyMap(selection);
|
||||||
|
|
||||||
|
body.put("newUserAccount", new UserAccountWrapper(vreq, userAccount,
|
||||||
|
Collections.<String> emptyList()));
|
||||||
|
|
||||||
|
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
/**
|
||||||
return Integer.parseInt(value);
|
* We just came from deleting accounts. Show the list with a message.
|
||||||
} catch (NumberFormatException e) {
|
*/
|
||||||
log.warn("Invalid integer for parameter '" + key + "': " + value);
|
public ResponseValues showPageWithDeletions(Collection<String> deletedUris) {
|
||||||
return defaultValue;
|
UserAccountsSelection selection = UserAccountsSelector.select(
|
||||||
|
userAccountsModel, criteria);
|
||||||
|
Map<String, Object> body = buildTemplateBodyMap(selection);
|
||||||
|
|
||||||
|
body.put("deletedAccountCount", deletedUris.size());
|
||||||
|
|
||||||
|
return new TemplateResponseValues(TEMPLATE_NAME, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> buildTemplateBodyMap(
|
||||||
|
UserAccountsSelection selection) {
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
body.put("accountsPerPage", criteria.getAccountsPerPage());
|
||||||
|
body.put("pageIndex", criteria.getPageIndex());
|
||||||
|
body.put("orderDirection", criteria.getOrderBy().getDirection().keyword);
|
||||||
|
body.put("orderField", criteria.getOrderBy().getField().name);
|
||||||
|
body.put("roleFilterUri", criteria.getRoleFilterUri());
|
||||||
|
body.put("searchTerm", criteria.getSearchTerm());
|
||||||
|
|
||||||
|
body.put("accounts", wrapUserAccounts(selection));
|
||||||
|
body.put("total", selection.getResultCount());
|
||||||
|
body.put("page", buildPageMap(selection));
|
||||||
|
|
||||||
|
body.put("formUrls", buildUrlsMap());
|
||||||
|
body.put("roles", buildRolesList());
|
||||||
|
|
||||||
|
body.put("messages", buildMessagesMap());
|
||||||
|
|
||||||
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Integer> buildPageMap(UserAccountsSelection selection) {
|
private Map<String, Integer> buildPageMap(UserAccountsSelection selection) {
|
||||||
|
@ -175,50 +157,31 @@ public class UserAccountsListController extends FreemarkerHttpServlet {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildFormUrl(VitroRequest vreq) {
|
private Map<String, Object> buildMessagesMap() {
|
||||||
UrlBuilder urlBuilder = new UrlBuilder(vreq.getAppBean());
|
|
||||||
return urlBuilder.getPortalUrl("/listUserAccounts");
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<PermissionSet> buildRolesList() {
|
|
||||||
List<PermissionSet> list = new ArrayList<PermissionSet>();
|
|
||||||
list.addAll(userAccountsDao.getAllPermissionSets());
|
|
||||||
Collections.sort(list, new Comparator<PermissionSet>() {
|
|
||||||
@Override
|
|
||||||
public int compare(PermissionSet ps1, PermissionSet ps2) {
|
|
||||||
return ps1.getUri().compareTo(ps2.getUri());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, Object> buildMessagesMap(VitroRequest vreq) {
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
|
|
||||||
UserAccount newUser = getUserFromUriParameter(vreq,
|
UserAccount newUser = getUserFromUriParameter(PARAMETER_NEW_USER_URI);
|
||||||
PARAMETER_NEW_USER_URI);
|
|
||||||
if (newUser != null) {
|
if (newUser != null) {
|
||||||
map.put("newUser", newUser);
|
map.put("newUser", newUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserAccount updatedUser = getUserFromUriParameter(vreq,
|
UserAccount updatedUser = getUserFromUriParameter(PARAMETER_UPDATED_USER_URI);
|
||||||
PARAMETER_UPDATED_USER_URI);
|
|
||||||
if (updatedUser != null) {
|
if (updatedUser != null) {
|
||||||
map.put("updatedUser", updatedUser);
|
map.put("updatedUser", updatedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFlagOnRequest(vreq, FLAG_UPDATED_USER_PW)) {
|
if (isFlagOnRequest(FLAG_UPDATED_USER_PW)) {
|
||||||
map.put("updatedUserPw", true);
|
map.put("updatedUserPw", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFlagOnRequest(vreq, FLAG_USERS_DELETED)) {
|
if (isFlagOnRequest(FLAG_USERS_DELETED)) {
|
||||||
map.put("usersDeleted", true);
|
map.put("usersDeleted", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserAccount getUserFromUriParameter(VitroRequest vreq, String key) {
|
private UserAccount getUserFromUriParameter(String key) {
|
||||||
String uri = vreq.getParameter(key);
|
String uri = vreq.getParameter(key);
|
||||||
if ((uri == null) || uri.isEmpty()) {
|
if ((uri == null) || uri.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -227,11 +190,6 @@ public class UserAccountsListController extends FreemarkerHttpServlet {
|
||||||
return userAccountsDao.getUserAccountByUri(uri);
|
return userAccountsDao.getUserAccountByUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFlagOnRequest(VitroRequest vreq, String key) {
|
|
||||||
String value = vreq.getParameter(key);
|
|
||||||
return (value != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The UserAccount has a list of PermissionSetUris, but the Freemarker
|
* The UserAccount has a list of PermissionSetUris, but the Freemarker
|
||||||
* template needs a list of PermissionSet labels instead.
|
* template needs a list of PermissionSet labels instead.
|
||||||
|
@ -240,7 +198,7 @@ public class UserAccountsListController extends FreemarkerHttpServlet {
|
||||||
UserAccountsSelection selection) {
|
UserAccountsSelection selection) {
|
||||||
List<UserAccountWrapper> list = new ArrayList<UserAccountWrapper>();
|
List<UserAccountWrapper> list = new ArrayList<UserAccountWrapper>();
|
||||||
for (UserAccount account : selection.getUserAccounts()) {
|
for (UserAccount account : selection.getUserAccounts()) {
|
||||||
list.add(new UserAccountWrapper(account,
|
list.add(new UserAccountWrapper(vreq, account,
|
||||||
findPermissionSetLabels(account)));
|
findPermissionSetLabels(account)));
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
|
@ -263,11 +221,16 @@ public class UserAccountsListController extends FreemarkerHttpServlet {
|
||||||
public static class UserAccountWrapper {
|
public static class UserAccountWrapper {
|
||||||
private final UserAccount account;
|
private final UserAccount account;
|
||||||
private final List<String> permissionSets;
|
private final List<String> permissionSets;
|
||||||
|
private final String editUrl;
|
||||||
|
|
||||||
public UserAccountWrapper(UserAccount account,
|
public UserAccountWrapper(VitroRequest vreq, UserAccount account,
|
||||||
List<String> permissionSets) {
|
List<String> permissionSets) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.permissionSets = permissionSets;
|
this.permissionSets = permissionSets;
|
||||||
|
|
||||||
|
UrlBuilder urlBuilder = new UrlBuilder(vreq.getAppBean());
|
||||||
|
this.editUrl = urlBuilder.getPortalUrl("/userAccounts/edit",
|
||||||
|
new ParamMap("editAccount", account.getUri()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUri() {
|
public String getUri() {
|
||||||
|
@ -303,6 +266,10 @@ public class UserAccountsListController extends FreemarkerHttpServlet {
|
||||||
return permissionSets;
|
return permissionSets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEditUrl() {
|
||||||
|
return editUrl;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common routines for the page controllers.
|
||||||
|
*/
|
||||||
|
public abstract class UserAccountsPage {
|
||||||
|
private static final Log log = LogFactory.getLog(UserAccountsPage.class);
|
||||||
|
|
||||||
|
protected final VitroRequest vreq;
|
||||||
|
protected final ServletContext ctx;
|
||||||
|
protected final OntModel userAccountsModel;
|
||||||
|
protected final UserAccountsDao userAccountsDao;
|
||||||
|
|
||||||
|
protected UserAccountsPage(VitroRequest vreq) {
|
||||||
|
this.vreq = vreq;
|
||||||
|
this.ctx = vreq.getSession().getServletContext();
|
||||||
|
|
||||||
|
OntModelSelector oms = (OntModelSelector) this.ctx
|
||||||
|
.getAttribute("baseOntModelSelector");
|
||||||
|
userAccountsModel = oms.getUserAccountsModel();
|
||||||
|
|
||||||
|
WebappDaoFactory wdf = (WebappDaoFactory) this.ctx
|
||||||
|
.getAttribute("webappDaoFactory");
|
||||||
|
userAccountsDao = wdf.getUserAccountsDao();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getStringParameter(String key, String defaultValue) {
|
||||||
|
String value = vreq.getParameter(key);
|
||||||
|
return (value == null) ? defaultValue : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getIntegerParameter(String key, int defaultValue) {
|
||||||
|
String value = vreq.getParameter(key);
|
||||||
|
if (value == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.warn("Invalid integer for parameter '" + key + "': " + value);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for the presence of a parameter, regardless of its value, even if
|
||||||
|
* it's an empty string.
|
||||||
|
*/
|
||||||
|
protected boolean isFlagOnRequest(String key) {
|
||||||
|
String value = vreq.getParameter(key);
|
||||||
|
return (value != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a list of all known PermissionSets.
|
||||||
|
*/
|
||||||
|
protected List<PermissionSet> buildRolesList() {
|
||||||
|
List<PermissionSet> list = new ArrayList<PermissionSet>();
|
||||||
|
list.addAll(userAccountsDao.getAllPermissionSets());
|
||||||
|
Collections.sort(list, new Comparator<PermissionSet>() {
|
||||||
|
@Override
|
||||||
|
public int compare(PermissionSet ps1, PermissionSet ps2) {
|
||||||
|
return ps1.getUri().compareTo(ps2.getUri());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make these URLs available to all of the pages.
|
||||||
|
*/
|
||||||
|
protected Map<String, String> buildUrlsMap() {
|
||||||
|
UrlBuilder urlBuilder = new UrlBuilder(vreq.getAppBean());
|
||||||
|
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
|
||||||
|
map.put("list", urlBuilder.getPortalUrl("/userAccounts/list"));
|
||||||
|
map.put("add", urlBuilder.getPortalUrl("/userAccounts/add"));
|
||||||
|
map.put("delete", urlBuilder.getPortalUrl("/userAccounts/delete"));
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,6 +11,10 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts;
|
||||||
public class UserAccountsSelectionCriteria {
|
public class UserAccountsSelectionCriteria {
|
||||||
public static final int DEFAULT_ACCOUNTS_PER_PAGE = 25;
|
public static final int DEFAULT_ACCOUNTS_PER_PAGE = 25;
|
||||||
|
|
||||||
|
public static final UserAccountsSelectionCriteria DEFAULT_CRITERIA = new UserAccountsSelectionCriteria(
|
||||||
|
DEFAULT_ACCOUNTS_PER_PAGE, 1,
|
||||||
|
UserAccountsOrdering.DEFAULT_ORDERING, "", "");
|
||||||
|
|
||||||
/** How many accounts should we bring back, at most? */
|
/** How many accounts should we bring back, at most? */
|
||||||
private final int accountsPerPage;
|
private final int accountsPerPage;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import com.hp.hpl.jena.datatypes.TypeMapper;
|
import com.hp.hpl.jena.datatypes.TypeMapper;
|
||||||
|
import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
|
||||||
import com.hp.hpl.jena.ontology.OntModel;
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
import com.hp.hpl.jena.rdf.model.Literal;
|
import com.hp.hpl.jena.rdf.model.Literal;
|
||||||
import com.hp.hpl.jena.rdf.model.Model;
|
import com.hp.hpl.jena.rdf.model.Model;
|
||||||
|
@ -25,6 +26,9 @@ import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||||
import com.hp.hpl.jena.rdf.model.Property;
|
import com.hp.hpl.jena.rdf.model.Property;
|
||||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||||
import com.hp.hpl.jena.rdf.model.Resource;
|
import com.hp.hpl.jena.rdf.model.Resource;
|
||||||
|
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Statement;
|
||||||
|
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||||
import com.hp.hpl.jena.shared.Lock;
|
import com.hp.hpl.jena.shared.Lock;
|
||||||
import com.hp.hpl.jena.vocabulary.RDF;
|
import com.hp.hpl.jena.vocabulary.RDF;
|
||||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||||
|
@ -74,6 +78,9 @@ public class IndividualController extends FreemarkerHttpServlet {
|
||||||
put("vitroPublic", VitroVocabulary.VITRO_PUBLIC);
|
put("vitroPublic", VitroVocabulary.VITRO_PUBLIC);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
private static final Property extendedLinkedDataProperty = ResourceFactory.createProperty(namespaces.get("vitro") + "extendedLinkedData");
|
||||||
|
private static final Literal xsdTrue = ResourceFactory.createTypedLiteral("true", XSDDatatype.XSDboolean);
|
||||||
|
|
||||||
private static final String TEMPLATE_INDIVIDUAL_DEFAULT = "individual.ftl";
|
private static final String TEMPLATE_INDIVIDUAL_DEFAULT = "individual.ftl";
|
||||||
private static final String TEMPLATE_HELP = "individual-help.ftl";
|
private static final String TEMPLATE_HELP = "individual-help.ftl";
|
||||||
private static Map<String,Float>qsMap;
|
private static Map<String,Float>qsMap;
|
||||||
|
@ -330,7 +337,7 @@ public class IndividualController extends FreemarkerHttpServlet {
|
||||||
if( ontModel == null)
|
if( ontModel == null)
|
||||||
ontModel = (OntModel)getServletContext().getAttribute("jenaOntModel");
|
ontModel = (OntModel)getServletContext().getAttribute("jenaOntModel");
|
||||||
|
|
||||||
Model newModel = getRDF(individual, ontModel, ModelFactory.createDefaultModel(), 0);
|
Model newModel = getRDF(individual, ontModel, ModelFactory.createDefaultModel(),0);
|
||||||
|
|
||||||
return new RdfResponseValues(rdfFormat, newModel);
|
return new RdfResponseValues(rdfFormat, newModel);
|
||||||
}
|
}
|
||||||
|
@ -548,7 +555,6 @@ public class IndividualController extends FreemarkerHttpServlet {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private boolean checkForSunset(VitroRequest vreq, Individual entity) {
|
private boolean checkForSunset(VitroRequest vreq, Individual entity) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
@ -591,11 +597,11 @@ public class IndividualController extends FreemarkerHttpServlet {
|
||||||
return "enabled".equals(property);
|
return "enabled".equals(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Model getRDF(Individual entity, OntModel contextModel, Model newModel, int recurseDepth ) {
|
private Model getRDF(Individual entity, OntModel contextModel, Model newModel, int recurseDepth) {
|
||||||
|
|
||||||
Resource subj = newModel.getResource(entity.getURI());
|
Resource subj = newModel.getResource(entity.getURI());
|
||||||
|
|
||||||
List<DataPropertyStatement> dstates = entity.getDataPropertyStatements();
|
List<DataPropertyStatement> dstates = entity.getDataPropertyStatements();
|
||||||
//System.out.println("data: "+dstates.size());
|
|
||||||
TypeMapper typeMapper = TypeMapper.getInstance();
|
TypeMapper typeMapper = TypeMapper.getInstance();
|
||||||
for (DataPropertyStatement ds: dstates) {
|
for (DataPropertyStatement ds: dstates) {
|
||||||
Property dp = newModel.getProperty(ds.getDatapropURI());
|
Property dp = newModel.getProperty(ds.getDatapropURI());
|
||||||
|
@ -610,19 +616,45 @@ public class IndividualController extends FreemarkerHttpServlet {
|
||||||
newModel.add(newModel.createStatement(subj, dp, lit));
|
newModel.add(newModel.createStatement(subj, dp, lit));
|
||||||
}
|
}
|
||||||
|
|
||||||
if( recurseDepth < 5 ){
|
if (recurseDepth < 5) {
|
||||||
List<ObjectPropertyStatement> ostates = entity.getObjectPropertyStatements();
|
List<ObjectPropertyStatement> ostates = entity.getObjectPropertyStatements();
|
||||||
|
|
||||||
for (ObjectPropertyStatement os: ostates) {
|
for (ObjectPropertyStatement os: ostates) {
|
||||||
ObjectProperty objProp = os.getProperty();
|
ObjectProperty objProp = os.getProperty();
|
||||||
Property op = newModel.getProperty(os.getPropertyURI());
|
Property prop = newModel.getProperty(os.getPropertyURI());
|
||||||
Resource obj = newModel.getResource(os.getObjectURI());
|
Resource obj = newModel.getResource(os.getObjectURI());
|
||||||
newModel.add(newModel.createStatement(subj, op, obj));
|
newModel.add(newModel.createStatement(subj, prop, obj));
|
||||||
if( objProp.getStubObjectRelation() )
|
if ( includeInLinkedData(obj, contextModel)) {
|
||||||
newModel.add(getRDF(os.getObject(), contextModel, newModel, recurseDepth + 1));
|
newModel.add(getRDF(os.getObject(), contextModel, newModel, recurseDepth + 1));
|
||||||
|
} else {
|
||||||
|
contextModel.enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
newModel.add(contextModel.listStatements(obj, RDFS.label, (RDFNode)null));
|
||||||
|
} finally {
|
||||||
|
contextModel.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newModel = getLabelAndTypes(entity, contextModel, newModel );
|
newModel = getLabelAndTypes(entity, contextModel, newModel );
|
||||||
|
|
||||||
|
// get all the statements not covered by the object property / datatype property code above
|
||||||
|
// note implication that extendedLinkedData individuals will only be evaulated for the
|
||||||
|
// recognized object properties.
|
||||||
|
contextModel.enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
StmtIterator iter = contextModel.listStatements(subj, (Property) null, (RDFNode) null);
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Statement stmt = iter.next();
|
||||||
|
if (!newModel.contains(stmt)) {
|
||||||
|
newModel.add(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
contextModel.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
|
||||||
return newModel;
|
return newModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -692,7 +724,27 @@ public class IndividualController extends FreemarkerHttpServlet {
|
||||||
return qsMap;
|
return qsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static String getAcceptedContentType(String acceptHeader,Map<String,Float>qs){
|
public static boolean includeInLinkedData(Resource object, Model contextModel) {
|
||||||
//
|
|
||||||
// }
|
boolean retval = false;
|
||||||
|
|
||||||
|
contextModel.enterCriticalSection(Lock.READ);
|
||||||
|
|
||||||
|
try {
|
||||||
|
StmtIterator iter = contextModel.listStatements(object, RDF.type, (RDFNode)null);
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Statement stmt = iter.next();
|
||||||
|
|
||||||
|
if (stmt.getObject().isResource() && contextModel.contains(stmt.getObject().asResource(), extendedLinkedDataProperty, xsdTrue)) {
|
||||||
|
retval = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
contextModel.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class SiteAdminController extends FreemarkerHttpServlet {
|
||||||
urls.put("users", urlBuilder.getPortalUrl("/listUsers"));
|
urls.put("users", urlBuilder.getPortalUrl("/listUsers"));
|
||||||
}
|
}
|
||||||
if (PolicyHelper.isAuthorizedForActions(vreq, new ManageUserAccounts())) {
|
if (PolicyHelper.isAuthorizedForActions(vreq, new ManageUserAccounts())) {
|
||||||
urls.put("userList", urlBuilder.getPortalUrl("/listUserAccounts"));
|
urls.put("userList", urlBuilder.getPortalUrl("/userAccounts"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PolicyHelper.isAuthorizedForActions(vreq, new EditSiteInformation())) {
|
if (PolicyHelper.isAuthorizedForActions(vreq, new EditSiteInformation())) {
|
||||||
|
|
|
@ -0,0 +1,337 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
|
import org.apache.lucene.index.CorruptIndexException;
|
||||||
|
import org.apache.lucene.index.Term;
|
||||||
|
import org.apache.lucene.search.BooleanClause;
|
||||||
|
import org.apache.lucene.search.BooleanQuery;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
import org.apache.lucene.search.PrefixQuery;
|
||||||
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.ScoreDoc;
|
||||||
|
import org.apache.lucene.search.Sort;
|
||||||
|
import org.apache.lucene.search.TermQuery;
|
||||||
|
import org.apache.lucene.search.TopDocs;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ExceptionResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.ListedIndividualTemplateModel;
|
||||||
|
import freemarker.ext.beans.BeansWrapper;
|
||||||
|
import freemarker.template.TemplateModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a list of individuals for display in a template
|
||||||
|
*/
|
||||||
|
public class SolrIndividualListController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Log log = LogFactory.getLog(SolrIndividualListController.class.getName());
|
||||||
|
|
||||||
|
public static final int ENTITY_LIST_CONTROLLER_MAX_RESULTS = 30000;
|
||||||
|
public static final int INDIVIDUALS_PER_PAGE = 30;
|
||||||
|
public static final int MAX_PAGES = 40; //must be even
|
||||||
|
|
||||||
|
private static final String TEMPLATE_DEFAULT = "individualList.ftl";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ResponseValues processRequest(VitroRequest vreq) {
|
||||||
|
|
||||||
|
String templateName = TEMPLATE_DEFAULT;
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
String errorMessage = null;
|
||||||
|
String message = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object obj = vreq.getAttribute("vclass");
|
||||||
|
VClass vclass = null;
|
||||||
|
if ( obj == null ) { // look for vitroclass id parameter
|
||||||
|
String vitroClassIdStr = vreq.getParameter("vclassId");
|
||||||
|
if ( !StringUtils.isEmpty(vitroClassIdStr)) {
|
||||||
|
try {
|
||||||
|
//TODO have to change this so vclass's group and entity count are populated
|
||||||
|
vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vitroClassIdStr);
|
||||||
|
if (vclass == null) {
|
||||||
|
log.error("Couldn't retrieve vclass " + vitroClassIdStr);
|
||||||
|
errorMessage = "Class " + vitroClassIdStr + " not found";
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new HelpException("IndividualListController: request parameter 'vclassId' must be a URI string.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (obj instanceof VClass) {
|
||||||
|
vclass = (VClass)obj;
|
||||||
|
} else {
|
||||||
|
throw new HelpException("IndividualListController: attribute 'vclass' must be of type "
|
||||||
|
+ VClass.class.getName() + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
body.put("vclassId", vclass.getURI());
|
||||||
|
|
||||||
|
if (vclass != null) {
|
||||||
|
String alpha = getAlphaParameter(vreq);
|
||||||
|
int page = getPageParameter(vreq);
|
||||||
|
Map<String,Object> map = getResultsForVClass(
|
||||||
|
vclass.getURI(),
|
||||||
|
page,
|
||||||
|
alpha,
|
||||||
|
vreq.getWebappDaoFactory().getIndividualDao(),
|
||||||
|
getServletContext());
|
||||||
|
body.putAll(map);
|
||||||
|
|
||||||
|
List<Individual> inds = (List<Individual>)map.get("entities");
|
||||||
|
List<ListedIndividualTemplateModel> indsTm = new ArrayList<ListedIndividualTemplateModel>();
|
||||||
|
for(Individual ind : inds ){
|
||||||
|
indsTm.add(new ListedIndividualTemplateModel(ind,vreq));
|
||||||
|
}
|
||||||
|
body.put("individuals", indsTm);
|
||||||
|
|
||||||
|
List<TemplateModel> wpages = new ArrayList<TemplateModel>();
|
||||||
|
List<PageRecord> pages = (List<PageRecord>)body.get("pages");
|
||||||
|
BeansWrapper wrapper = new BeansWrapper();
|
||||||
|
for( PageRecord pr: pages ){
|
||||||
|
wpages.add( wrapper.wrap(pr) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set title and subtitle. Title will be retrieved later in getTitle().
|
||||||
|
VClassGroup classGroup = vclass.getGroup();
|
||||||
|
String title;
|
||||||
|
if (classGroup == null) {
|
||||||
|
title = vclass.getName();
|
||||||
|
} else {
|
||||||
|
title = classGroup.getPublicName();
|
||||||
|
body.put("subtitle", vclass.getName());
|
||||||
|
}
|
||||||
|
body.put("title", title);
|
||||||
|
body.put("redirecturl", vreq.getContextPath()+"/entityurl/");
|
||||||
|
getServletContext().setAttribute("classuri", vclass.getURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (HelpException help){
|
||||||
|
errorMessage = "Request attribute 'vclass' or request parameter 'vclassId' must be set before calling. Its value must be a class uri.";
|
||||||
|
} catch (Throwable e) {
|
||||||
|
return new ExceptionResponseValues(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorMessage != null) {
|
||||||
|
templateName = Template.ERROR_MESSAGE.toString();
|
||||||
|
body.put("errorMessage", errorMessage);
|
||||||
|
} else if (message != null) {
|
||||||
|
body.put("message", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TemplateResponseValues(templateName, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HelpException extends Throwable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public HelpException(String string) {
|
||||||
|
super(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAlphaParameter(VitroRequest request){
|
||||||
|
return request.getParameter("alpha");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getPageParameter(VitroRequest request) {
|
||||||
|
String pageStr = request.getParameter("page");
|
||||||
|
if( pageStr != null ){
|
||||||
|
try{
|
||||||
|
return Integer.parseInt(pageStr);
|
||||||
|
}catch(NumberFormatException nfe){
|
||||||
|
log.debug("could not parse page parameter");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is now called in a couple of places. It should be refactored
|
||||||
|
* into a DAO or similar object.
|
||||||
|
*/
|
||||||
|
public static Map<String,Object> getResultsForVClass(String vclassURI, int page, String alpha, IndividualDao indDao, ServletContext context)
|
||||||
|
throws CorruptIndexException, IOException, ServletException{
|
||||||
|
Map<String,Object> rvMap = new HashMap<String,Object>();
|
||||||
|
|
||||||
|
//make lucene query for this rdf:type
|
||||||
|
Query query = getQuery(vclassURI, alpha);
|
||||||
|
|
||||||
|
//execute lucene query for individuals of the specified type
|
||||||
|
IndexSearcher index = LuceneIndexFactory.getIndexSearcher(context);
|
||||||
|
TopDocs docs = null;
|
||||||
|
try{
|
||||||
|
docs = index.search(query, null,
|
||||||
|
ENTITY_LIST_CONTROLLER_MAX_RESULTS,
|
||||||
|
new Sort(Entity2LuceneDoc.term.NAME_LOWERCASE));
|
||||||
|
}catch(Throwable th){
|
||||||
|
log.error("Could not run search. " + th.getMessage());
|
||||||
|
docs = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( docs == null )
|
||||||
|
throw new ServletException("Could not run search in IndividualListController");
|
||||||
|
|
||||||
|
//get list of individuals for the search results
|
||||||
|
int size = docs.totalHits;
|
||||||
|
log.debug("Number of search results: " + size);
|
||||||
|
|
||||||
|
// don't get all the results, only get results for the requestedSize
|
||||||
|
List<Individual> individuals = new ArrayList<Individual>(INDIVIDUALS_PER_PAGE);
|
||||||
|
int individualsAdded = 0;
|
||||||
|
int ii = (page-1)*INDIVIDUALS_PER_PAGE;
|
||||||
|
while( individualsAdded < INDIVIDUALS_PER_PAGE && ii < size ){
|
||||||
|
ScoreDoc hit = docs.scoreDocs[ii];
|
||||||
|
if (hit != null) {
|
||||||
|
Document doc = index.doc(hit.doc);
|
||||||
|
if (doc != null) {
|
||||||
|
String uri = doc.getField(Entity2LuceneDoc.term.URI).stringValue();
|
||||||
|
Individual ind = indDao.getIndividualByURI( uri );
|
||||||
|
if( ind != null ){
|
||||||
|
individuals.add( ind );
|
||||||
|
individualsAdded++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("no document found for lucene doc id " + hit.doc);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("hit was null");
|
||||||
|
}
|
||||||
|
ii++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rvMap.put("count", size);
|
||||||
|
|
||||||
|
if( size > INDIVIDUALS_PER_PAGE ){
|
||||||
|
rvMap.put("showPages", Boolean.TRUE);
|
||||||
|
List<PageRecord> pageRecords = makePagesList(size, INDIVIDUALS_PER_PAGE, page);
|
||||||
|
rvMap.put("pages", pageRecords);
|
||||||
|
}else{
|
||||||
|
rvMap.put("showPages", Boolean.FALSE);
|
||||||
|
rvMap.put("pages", Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
rvMap.put("alpha",alpha);
|
||||||
|
|
||||||
|
rvMap.put("totalCount", size);
|
||||||
|
rvMap.put("entities",individuals);
|
||||||
|
if (individuals == null)
|
||||||
|
log.debug("entities list is null for vclass " + vclassURI );
|
||||||
|
|
||||||
|
return rvMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BooleanQuery getQuery(String vclassUri, String alpha){
|
||||||
|
BooleanQuery query = new BooleanQuery();
|
||||||
|
try{
|
||||||
|
//query term for rdf:type
|
||||||
|
query.add(
|
||||||
|
new TermQuery( new Term(Entity2LuceneDoc.term.RDFTYPE, vclassUri)),
|
||||||
|
BooleanClause.Occur.MUST );
|
||||||
|
|
||||||
|
//Add alpha filter if it is needed
|
||||||
|
Query alphaQuery = null;
|
||||||
|
if( alpha != null && !"".equals(alpha) && alpha.length() == 1){
|
||||||
|
alphaQuery =
|
||||||
|
new PrefixQuery(new Term(Entity2LuceneDoc.term.NAME_LOWERCASE, alpha.toLowerCase()));
|
||||||
|
query.add(alphaQuery,BooleanClause.Occur.MUST);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Query: " + query);
|
||||||
|
return query;
|
||||||
|
} catch (Exception ex){
|
||||||
|
log.error(ex,ex);
|
||||||
|
return new BooleanQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<PageRecord> makePagesList( int count, int pageSize, int selectedPage){
|
||||||
|
|
||||||
|
List<PageRecord> records = new ArrayList<PageRecord>( MAX_PAGES + 1 );
|
||||||
|
int requiredPages = count/pageSize ;
|
||||||
|
int remainder = count % pageSize ;
|
||||||
|
if( remainder > 0 )
|
||||||
|
requiredPages++;
|
||||||
|
|
||||||
|
if( selectedPage < MAX_PAGES && requiredPages > MAX_PAGES ){
|
||||||
|
//the selected pages is within the first maxPages, just show the normal pages up to maxPages.
|
||||||
|
for(int page = 1; page < requiredPages && page <= MAX_PAGES ; page++ ){
|
||||||
|
records.add( new PageRecord( "page=" + page, Integer.toString(page), Integer.toString(page), selectedPage == page ) );
|
||||||
|
}
|
||||||
|
records.add( new PageRecord( "page="+ (MAX_PAGES+1), Integer.toString(MAX_PAGES+1), "more...", false));
|
||||||
|
}else if( requiredPages > MAX_PAGES && selectedPage+1 > MAX_PAGES && selectedPage < requiredPages - MAX_PAGES){
|
||||||
|
//the selected pages is in the middle of the list of page
|
||||||
|
int startPage = selectedPage - MAX_PAGES / 2;
|
||||||
|
int endPage = selectedPage + MAX_PAGES / 2;
|
||||||
|
for(int page = startPage; page <= endPage ; page++ ){
|
||||||
|
records.add( new PageRecord( "page=" + page, Integer.toString(page), Integer.toString(page), selectedPage == page ) );
|
||||||
|
}
|
||||||
|
records.add( new PageRecord( "page="+ endPage+1, Integer.toString(endPage+1), "more...", false));
|
||||||
|
}else if ( requiredPages > MAX_PAGES && selectedPage > requiredPages - MAX_PAGES ){
|
||||||
|
//the selected page is in the end of the list
|
||||||
|
int startPage = requiredPages - MAX_PAGES;
|
||||||
|
double max = Math.ceil(count/pageSize);
|
||||||
|
for(int page = startPage; page <= max; page++ ){
|
||||||
|
records.add( new PageRecord( "page=" + page, Integer.toString(page), Integer.toString(page), selectedPage == page ) );
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//there are fewer than maxPages pages.
|
||||||
|
for(int i = 1; i <= requiredPages; i++ ){
|
||||||
|
records.add( new PageRecord( "page=" + i, Integer.toString(i), Integer.toString(i), selectedPage == i ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PageRecord {
|
||||||
|
public PageRecord(String param, String index, String text, boolean selected) {
|
||||||
|
this.param = param;
|
||||||
|
this.index = index;
|
||||||
|
this.text = text;
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
public String param;
|
||||||
|
public String index;
|
||||||
|
public String text;
|
||||||
|
public boolean selected=false;
|
||||||
|
|
||||||
|
public String getParam() {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
public String getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
public boolean getSelected(){
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,6 +20,14 @@ public interface UserAccountsDao {
|
||||||
*/
|
*/
|
||||||
UserAccount getUserAccountByUri(String uri);
|
UserAccount getUserAccountByUri(String uri);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the UserAccount for this Email address.
|
||||||
|
*
|
||||||
|
* @return null if the Email address is null, or if there is no such
|
||||||
|
* UserAccount
|
||||||
|
*/
|
||||||
|
UserAccount getUserAccountByEmail(String emailAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new UserAccount in the model.
|
* Create a new UserAccount in the model.
|
||||||
*
|
*
|
||||||
|
|
|
@ -32,6 +32,11 @@ public class UserAccountsDaoFiltering extends BaseFiltering implements
|
||||||
return innerDao.getUserAccountByUri(uri);
|
return innerDao.getUserAccountByUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserAccount getUserAccountByEmail(String emailAddress) {
|
||||||
|
return innerDao.getUserAccountByEmail(emailAddress);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String insertUserAccount(UserAccount userAccount) {
|
public String insertUserAccount(UserAccount userAccount) {
|
||||||
return innerDao.insertUserAccount(userAccount);
|
return innerDao.insertUserAccount(userAccount);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.hp.hpl.jena.ontology.OntModel;
|
||||||
import com.hp.hpl.jena.ontology.OntResource;
|
import com.hp.hpl.jena.ontology.OntResource;
|
||||||
import com.hp.hpl.jena.rdf.model.Resource;
|
import com.hp.hpl.jena.rdf.model.Resource;
|
||||||
import com.hp.hpl.jena.rdf.model.Statement;
|
import com.hp.hpl.jena.rdf.model.Statement;
|
||||||
|
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||||
import com.hp.hpl.jena.shared.Lock;
|
import com.hp.hpl.jena.shared.Lock;
|
||||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||||
import com.hp.hpl.jena.vocabulary.RDF;
|
import com.hp.hpl.jena.vocabulary.RDF;
|
||||||
|
@ -71,6 +72,28 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserAccount getUserAccountByEmail(String emailAddress) {
|
||||||
|
if (emailAddress == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String userUri = null;
|
||||||
|
|
||||||
|
getOntModel().enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
StmtIterator stmts = getOntModel().listStatements(null, USERACCOUNT_EMAIL_ADDRESS,
|
||||||
|
getOntModel().createLiteral(emailAddress));
|
||||||
|
if (stmts.hasNext()) {
|
||||||
|
userUri = stmts.next().getSubject().getURI();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
getOntModel().leaveCriticalSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
return getUserAccountByUri(userUri);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String insertUserAccount(UserAccount userAccount) {
|
public String insertUserAccount(UserAccount userAccount) {
|
||||||
if (userAccount == null) {
|
if (userAccount == null) {
|
||||||
|
|
|
@ -13,15 +13,16 @@ import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.lucene.search.BooleanQuery;
|
import org.apache.lucene.search.BooleanQuery;
|
||||||
import org.apache.solr.client.solrj.SolrQuery;
|
import org.apache.solr.client.solrj.SolrQuery;
|
||||||
import org.apache.solr.client.solrj.SolrServer;
|
import org.apache.solr.client.solrj.SolrServer;
|
||||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||||
|
import org.apache.solr.client.solrj.response.TermsResponse;
|
||||||
import org.apache.solr.common.SolrDocument;
|
import org.apache.solr.common.SolrDocument;
|
||||||
import org.apache.solr.common.SolrDocumentList;
|
import org.apache.solr.common.SolrDocumentList;
|
||||||
import org.apache.solr.common.params.FacetParams;
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
@ -113,6 +114,7 @@ public class SolrAutocompleteController extends VitroAjaxController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since SolrQuery.setSortField() is buggy, sort the results here
|
||||||
Collections.sort(results);
|
Collections.sort(results);
|
||||||
|
|
||||||
// map.put("results", results);
|
// map.put("results", results);
|
||||||
|
@ -130,37 +132,42 @@ public class SolrAutocompleteController extends VitroAjaxController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SolrQuery getQuery(String querystr, VitroRequest vreq) {
|
private SolrQuery getQuery(String queryStr, VitroRequest vreq) {
|
||||||
|
|
||||||
if ( querystr == null) {
|
if ( queryStr == null) {
|
||||||
log.error("There was no parameter '"+ PARAM_QUERY
|
log.error("There was no parameter '"+ PARAM_QUERY
|
||||||
+"' in the request.");
|
+"' in the request.");
|
||||||
return null;
|
return null;
|
||||||
} else if( querystr.length() > MAX_QUERY_LENGTH ) {
|
} else if( queryStr.length() > MAX_QUERY_LENGTH ) {
|
||||||
log.debug("The search was too long. The maximum " +
|
log.debug("The search was too long. The maximum " +
|
||||||
"query length is " + MAX_QUERY_LENGTH );
|
"query length is " + MAX_QUERY_LENGTH );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
SolrQuery query = new SolrQuery();
|
SolrQuery query = new SolrQuery();
|
||||||
query = query.setStart(0);
|
query.setStart(0)
|
||||||
query = query.setRows(DEFAULT_MAX_HIT_COUNT);
|
.setRows(DEFAULT_MAX_HIT_COUNT);
|
||||||
|
|
||||||
query = setNameQuery(query, querystr, vreq);
|
setQuery(query, queryStr, vreq);
|
||||||
|
|
||||||
// Filter by type
|
// Filter by type
|
||||||
String typeParam = (String) vreq.getParameter(PARAM_RDFTYPE);
|
String typeParam = (String) vreq.getParameter(PARAM_RDFTYPE);
|
||||||
if (typeParam != null) {
|
if (typeParam != null) {
|
||||||
query = query.addFilterQuery(VitroLuceneTermNames.RDFTYPE + ":\"" + typeParam + "\"");
|
query.addFilterQuery(VitroLuceneTermNames.RDFTYPE + ":\"" + typeParam + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the fields to retrieve **** RY
|
query.setFields(VitroLuceneTermNames.NAME_RAW, VitroLuceneTermNames.URI); // fields to retrieve
|
||||||
// query = query.setFields( ... );
|
// Solr bug: generates sort=nameLowercase asc instead of sort=nameLowercase+asc
|
||||||
|
//.setSortField(VitroLuceneTermNames.NAME_LOWERCASE, SolrQuery.ORDER.asc);
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SolrQuery setNameQuery(SolrQuery query, String querystr, HttpServletRequest request) {
|
private void setQuery(SolrQuery query, String queryStr, HttpServletRequest request) {
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(queryStr)) {
|
||||||
|
log.error("No query string");
|
||||||
|
}
|
||||||
|
|
||||||
String tokenizeParam = (String) request.getParameter("tokenize");
|
String tokenizeParam = (String) request.getParameter("tokenize");
|
||||||
boolean tokenize = "true".equals(tokenizeParam);
|
boolean tokenize = "true".equals(tokenizeParam);
|
||||||
|
@ -169,19 +176,21 @@ public class SolrAutocompleteController extends VitroAjaxController {
|
||||||
// query will not be stemmed. So we don't look at the stem parameter until we get to
|
// query will not be stemmed. So we don't look at the stem parameter until we get to
|
||||||
// setTokenizedNameQuery().
|
// setTokenizedNameQuery().
|
||||||
if (tokenize) {
|
if (tokenize) {
|
||||||
return setTokenizedNameQuery(query, querystr, request);
|
setTokenizedQuery(query, queryStr, request);
|
||||||
} else {
|
} else {
|
||||||
return setUntokenizedNameQuery(query, querystr);
|
setUntokenizedQuery(query, queryStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SolrQuery setTokenizedNameQuery(SolrQuery query, String querystr, HttpServletRequest request) {
|
private void setTokenizedQuery(SolrQuery query, String queryStr, HttpServletRequest request) {
|
||||||
|
|
||||||
String stemParam = (String) request.getParameter("stem");
|
// RY 5/18/2011 For now, just doing untokenized query, due to the interactions of wildcard
|
||||||
boolean stem = "true".equals(stemParam);
|
// query and stemming described below. Need to find a way to do this in Solr.
|
||||||
String termName = stem ? VitroLuceneTermNames.AC_NAME_STEMMED : VitroLuceneTermNames.AC_NAME_UNSTEMMED ;
|
// Should take the same approach if we can figure out how to do a disjunction.
|
||||||
|
|
||||||
BooleanQuery boolQuery = new BooleanQuery();
|
// String stemParam = (String) request.getParameter("stem");
|
||||||
|
// boolean stem = "true".equals(stemParam);
|
||||||
|
// String termName = stem ? VitroLuceneTermNames.AC_NAME_STEMMED : VitroLuceneTermNames.AC_NAME_UNSTEMMED ;
|
||||||
|
|
||||||
// // Use the query parser to analyze the search term the same way the indexed text was analyzed.
|
// // Use the query parser to analyze the search term the same way the indexed text was analyzed.
|
||||||
// // For example, text is lowercased, and function words are stripped out.
|
// // For example, text is lowercased, and function words are stripped out.
|
||||||
|
@ -190,7 +199,7 @@ public class SolrAutocompleteController extends VitroAjaxController {
|
||||||
// // The wildcard query doesn't play well with stemming. Query term name:tales* doesn't match
|
// // The wildcard query doesn't play well with stemming. Query term name:tales* doesn't match
|
||||||
// // "tales", which is indexed as "tale", while query term name:tales does. Obviously we need
|
// // "tales", which is indexed as "tale", while query term name:tales does. Obviously we need
|
||||||
// // the wildcard for name:tal*, so the only way to get them all to match is use a disjunction
|
// // the wildcard for name:tal*, so the only way to get them all to match is use a disjunction
|
||||||
// // of wildcard and non-wildcard queries. The query will look have only an implicit disjunction
|
// // of wildcard and non-wildcard queries. The query will have only an implicit disjunction
|
||||||
// // operator: e.g., +(name:tales name:tales*)
|
// // operator: e.g., +(name:tales name:tales*)
|
||||||
// try {
|
// try {
|
||||||
// log.debug("Adding non-wildcard query for " + querystr);
|
// log.debug("Adding non-wildcard query for " + querystr);
|
||||||
|
@ -210,20 +219,18 @@ public class SolrAutocompleteController extends VitroAjaxController {
|
||||||
// log.warn(e, e);
|
// log.warn(e, e);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return query;
|
setUntokenizedQuery(query, queryStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SolrQuery setUntokenizedNameQuery(SolrQuery query, String querystr) {
|
private void setUntokenizedQuery(SolrQuery query, String queryStr) {
|
||||||
|
|
||||||
// Using facet method described in http://solr.pl/en/2010/10/18/solr-and-autocomplete-part-1/
|
// We have to lowercase manually, because Solr doesn't do text analysis on wildcard queries
|
||||||
// Consider using Solr Suggester in a future version.
|
queryStr = queryStr.toLowerCase();
|
||||||
return query.setFacet(true)
|
// Solr wants whitespace to be escaped with a backslash
|
||||||
.addFacetField(VitroLuceneTermNames.NAME_LOWERCASE)
|
// Better: replace \s+
|
||||||
.setFacetMinCount(1)
|
queryStr = queryStr.replaceAll(" ", "\\\\ ");
|
||||||
.setFacetLimit(MAX_QUERY_LENGTH)
|
queryStr = VitroLuceneTermNames.NAME_LOWERCASE + ":" + queryStr + "*";
|
||||||
.setFacetPrefix(querystr)//.toLowerCase())
|
query.setQuery(queryStr);
|
||||||
//.setFacetSort(FacetParams.FACET_SORT_INDEX) // sort by alpha (but doesn't work)
|
|
||||||
.setQuery("*:*");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
@ -46,6 +47,9 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass {
|
||||||
private static final String URI_USER1 = NS_MINE + "user01";
|
private static final String URI_USER1 = NS_MINE + "user01";
|
||||||
private static final String URI_NO_SUCH_USER = NS_MINE + "bogusUser";
|
private static final String URI_NO_SUCH_USER = NS_MINE + "bogusUser";
|
||||||
|
|
||||||
|
private static final String EMAIL_USER1 = "email@able.edu";
|
||||||
|
private static final String EMAIL_NO_SUCH_USER = NS_MINE + "bogus@email.com";
|
||||||
|
|
||||||
private static final String URI_ROLE1 = NS_MINE + "role1";
|
private static final String URI_ROLE1 = NS_MINE + "role1";
|
||||||
private static final String URI_ROLE2 = NS_MINE + "role2";
|
private static final String URI_ROLE2 = NS_MINE + "role2";
|
||||||
private static final String URI_ROLE3 = NS_MINE + "role3";
|
private static final String URI_ROLE3 = NS_MINE + "role3";
|
||||||
|
@ -100,6 +104,24 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass {
|
||||||
assertNull("null result", u);
|
assertNull("null result", u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getUserAccountByEmailSuccess() {
|
||||||
|
UserAccount u = dao.getUserAccountByEmail(EMAIL_USER1);
|
||||||
|
assertEquals("uri", URI_USER1, u.getUri());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getUserAccountByEmailNull() {
|
||||||
|
UserAccount u = dao.getUserAccountByEmail(null);
|
||||||
|
assertEquals("uri", null, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getUserAccountByEmailNotFound() {
|
||||||
|
UserAccount u = dao.getUserAccountByEmail(EMAIL_NO_SUCH_USER);
|
||||||
|
assertEquals("uri", null, u);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void insertUserAccountSuccess() {
|
public void insertUserAccountSuccess() {
|
||||||
UserAccount in = new UserAccount();
|
UserAccount in = new UserAccount();
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Template for adding a user account -->
|
||||||
|
|
||||||
|
<h1>Add new account</h1>
|
||||||
|
|
||||||
|
<#if errorEmailIsEmpty??>
|
||||||
|
<#assign errorMessage = "You must supply an email address." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorEmailInUse??>
|
||||||
|
<#assign errorMessage = "An account with that email address already exists." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorFirstNameIsEmpty??>
|
||||||
|
<#assign errorMessage = "You must supply a first name." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorLastNameIsEmpty??>
|
||||||
|
<#assign errorMessage = "You must supply a last name." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorNoRoleSelected??>
|
||||||
|
<#assign errorMessage = "You must select a role." />
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if errorMessage?has_content>
|
||||||
|
<section id="error-alert" role="alert">
|
||||||
|
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/>
|
||||||
|
<p>${errorMessage}</p>
|
||||||
|
</section>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<form method="POST" action="${formUrls.add}">
|
||||||
|
Email address *
|
||||||
|
<br/>
|
||||||
|
<input type="text" name="emailAddress" value="${emailAddress}" />
|
||||||
|
<br/>
|
||||||
|
First name *
|
||||||
|
<br/>
|
||||||
|
<input type="text" name="firstName" value="${firstName}" />
|
||||||
|
<br/>
|
||||||
|
Last name *
|
||||||
|
<br/>
|
||||||
|
<input type="text" name="lastName" value="${lastName}" />
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
Roles *
|
||||||
|
<br/>
|
||||||
|
<#list roles as role>
|
||||||
|
<input type="radio" name="role" value="${role.uri}" <#if selectedRole = role.uri>selected</#if> />${role.label}
|
||||||
|
<br>
|
||||||
|
</#list>
|
||||||
|
<br/>
|
||||||
|
Associate a profile with this account
|
||||||
|
<br/>
|
||||||
|
<input type="radio" name="associate" value="yes" <#if associate??>checked</#if> />Yes
|
||||||
|
<br/>
|
||||||
|
<input type="radio" name="associate" value="no" <#if !associate??>checked</#if> />No
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note: An email will be sent to the address entered above
|
||||||
|
notifying that an account has been created.
|
||||||
|
It will include instructions for activating the account and creating a password.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<input type="submit" name="submitAdd" value="Add new account" />
|
||||||
|
or <a href="${formUrls.list}">Cancel</a>
|
||||||
|
</form>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Template for editing a user account -->
|
||||||
|
|
||||||
|
<h1>Edit user account</h1>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<#-- Template for displaying list of user accounts -->
|
<#-- Template for displaying list of user accounts -->
|
||||||
|
|
||||||
<form method="POST" action="${formUrl}">
|
<form method="POST" action="${formUrls.list}">
|
||||||
|
|
||||||
<#--current page: <input type="text" name="pageIndex" value="${page.current}" />
|
<#--current page: <input type="text" name="pageIndex" value="${page.current}" />
|
||||||
<br />-->
|
<br />-->
|
||||||
|
@ -38,12 +38,28 @@
|
||||||
<input type="submit" name="list" value="Refresh page" />-->
|
<input type="submit" name="list" value="Refresh page" />-->
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h3>Account | <input type="submit" name="add" class="submit" value="Add new account" /></h3>
|
<form method="POST" action="${formUrls.add}">
|
||||||
<!-- When this is clicked, all other fields are ignored. -->
|
<h3>Account | <input type="submit" class="submit" value="Add new account" /></h3>
|
||||||
|
</form>
|
||||||
|
|
||||||
<section class="account-feedback">
|
<#if newUserAccount?? >
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. <a hrf="#">Maecenas dui erat</a>, dapibus non vehicula at, tristique eu sem. Suspendisse ligula felis, mollis vitae elementum eget, semper a nisl.</p>
|
<section class="account-feedback">
|
||||||
</section>
|
<p>
|
||||||
|
A new account for
|
||||||
|
<a href="${newUserAccount.editUrl}">${newUserAccount.firstName} ${newUserAccount.lastName}</a>
|
||||||
|
was successfully created. A notification email has been sent to ${newUserAccount.emailAddress}
|
||||||
|
with instructions for activating the account and creating a password.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if deletedAccountCount?? >
|
||||||
|
<section class="account-feedback">
|
||||||
|
<p>
|
||||||
|
Deleted ${deletedAccountCount} accounts.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</#if>
|
||||||
|
|
||||||
<section id="filter-roles">
|
<section id="filter-roles">
|
||||||
<select name="roleFilterUri" id="">
|
<select name="roleFilterUri" id="">
|
||||||
|
@ -59,7 +75,8 @@
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="search-accounts">
|
<form method="POST" action="${formUrls.list}">
|
||||||
|
<section id="search-accounts">
|
||||||
<input type="text" name="" />
|
<input type="text" name="" />
|
||||||
<input class="submit" type="submit" value="Search accounts"/>
|
<input class="submit" type="submit" value="Search accounts"/>
|
||||||
<!--
|
<!--
|
||||||
|
@ -69,17 +86,27 @@
|
||||||
set orderField to "email"
|
set orderField to "email"
|
||||||
submit the form (submit action is "list")
|
submit the form (submit action is "list")
|
||||||
-->
|
-->
|
||||||
</section>
|
</section>
|
||||||
|
</form>
|
||||||
|
|
||||||
<section class="accounts">
|
<SCRIPT TYPE="text/javascript">
|
||||||
<input type="submit" name="delete" class="submit delete-account" value="Delete" />
|
function changeAction(form, url) {
|
||||||
<!-- When this is clicked, the checkboxes are noticed and all other fields are ignored. -->
|
form.action = url;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
</SCRIPT>
|
||||||
|
|
||||||
|
<form method="POST" action="${formUrls.list}">
|
||||||
|
<section class="accounts">
|
||||||
|
<input type="submit" class="submit delete-account" value="Delete" onClick="changeAction(this.form, '${formUrls.delete}')" />
|
||||||
|
<!--
|
||||||
|
When this is clicked, the checkboxes are noticed and all other fields are ignored.
|
||||||
|
submit the form (submit action is formUrls.delete)
|
||||||
|
-->
|
||||||
|
|
||||||
<nav class="display-tools">
|
<nav class="display-tools">
|
||||||
<span>| <a href="#">n</a> accounts | </span>
|
<span>| <a href="#">n</a> accounts | </span>
|
||||||
|
|
||||||
<form method="get" class="accounts-per-page-form" name="list" action="${formUrl}">
|
|
||||||
|
|
||||||
<#assign counts = [25, 50, 100]>
|
<#assign counts = [25, 50, 100]>
|
||||||
<select name="accountsPerPage" class="accounts-per-page">
|
<select name="accountsPerPage" class="accounts-per-page">
|
||||||
<#list counts as count>
|
<#list counts as count>
|
||||||
|
@ -88,35 +115,32 @@
|
||||||
<!--
|
<!--
|
||||||
When accountsPerPage changes,
|
When accountsPerPage changes,
|
||||||
set pageIndex to 1
|
set pageIndex to 1
|
||||||
submit the form (submit action is "list")
|
submit the form (submit action is formUrls.list)
|
||||||
-->
|
-->
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<input class="hide" type="submit" value="Update" />
|
<input class="hide" type="submit" value="Update" />
|
||||||
</form>
|
|
||||||
|
|
||||||
accounts per page |
|
accounts per page |
|
||||||
|
|
||||||
<#if page.previous?has_content>
|
<#if page.previous?has_content>
|
||||||
<a href="${formUrl}?accountsPerPage=${accountsPerPage}&pageIndex=${page.previous}">Previous</a> <!-- only present if current page is not 1.-->
|
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.previous}">Previous</a> <!-- only present if current page is not 1.-->
|
||||||
</#if>
|
</#if>
|
||||||
${page.current} of ${page.last}
|
${page.current} of ${page.last}
|
||||||
<#if page.next?has_content>
|
<#if page.next?has_content>
|
||||||
<a href="${formUrl}?accountsPerPage=${accountsPerPage}&pageIndex=${page.next}">Next</a><!-- only present if current page is not last page.-->
|
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.next}">Next</a><!-- only present if current page is not last page.-->
|
||||||
</#if>
|
</#if>
|
||||||
</nav>
|
</nav>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<table id="account">
|
<table id="account">
|
||||||
<caption>Account Management</caption>
|
<caption>Account Management</caption>
|
||||||
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
<div>
|
<div>
|
||||||
<form method="get" class="delete-all-accounts" name="list" action="${formUrl}">
|
|
||||||
<input class="hide" type="checkbox" name="delete-all" id="">Email Address<span></span>
|
<input class="hide" type="checkbox" name="delete-all" id="">Email Address<span></span>
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col"><div>First name <a href="?accountsPerPage=${accountsPerPage}&orderField=firstName&orderDirection=ASC"><img class="middle" src="${urls.themeImages}/sort-asc.gif" /></a> <a href="?accountsPerPage=${accountsPerPage}&orderField=firstNameorderDirection=DEC"><img src="${urls.themeImages}/sort-desc.gif" /></a></div></th>
|
<th scope="col"><div>First name <a href="?accountsPerPage=${accountsPerPage}&orderField=firstName&orderDirection=ASC"><img class="middle" src="${urls.themeImages}/sort-asc.gif" /></a> <a href="?accountsPerPage=${accountsPerPage}&orderField=firstNameorderDirection=DEC"><img src="${urls.themeImages}/sort-desc.gif" /></a></div></th>
|
||||||
|
@ -132,10 +156,10 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" name="deleteAccount" value="${account.uri}" />
|
<input type="checkbox" name="deleteAccount" value="${account.uri}" />
|
||||||
<!-- ignored unless submit action is "delete" -->
|
<!-- ignored unless submit action is formUrls.delete -->
|
||||||
|
|
||||||
<a href="${formUrl}?edit&editAccount=${account.uri}" >${account.emailAddress}</a>
|
<a href="${account.editUrl}" >${account.emailAddress}</a>
|
||||||
<!-- if submit action is "edit", editAccount is noticed and all other fields are ignored. -->
|
<!-- when this link is clicked, editAccount is noticed and all other fields are ignored. -->
|
||||||
</td>
|
</td>
|
||||||
<td>${account.firstName}</td>
|
<td>${account.firstName}</td>
|
||||||
<td>${account.lastName}</td>
|
<td>${account.lastName}</td>
|
||||||
|
@ -149,8 +173,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</#list>
|
</#list>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</form>
|
||||||
<#--link on user's email address currently does nothing-->
|
|
||||||
|
|
||||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/account/accountUtils.js"></script>')}
|
${scripts.add('<script type="text/javascript" src="${urls.base}/js/account/accountUtils.js"></script>')}
|
Loading…
Add table
Reference in a new issue