First part native SQL option for PersonalPublications

git-svn-id: https://svn.libreccm.org/ccm/trunk@5003 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2017-09-20 09:02:26 +00:00
parent b53cb9d192
commit b5e2677e49
3 changed files with 438 additions and 130 deletions

View File

@ -11,7 +11,14 @@ import com.arsdigita.domain.DomainObject;
import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.globalization.GlobalizationHelper; import com.arsdigita.globalization.GlobalizationHelper;
import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -19,28 +26,96 @@ import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
/** /**
* A {@link ContentGenerator} for personal profiles which displays all * A {@link ContentGenerator} for personal profiles which displays all
* publications of a person. The person and be organized in groups. The groups * publications of a person. The person and be organized in groups. The groups
* are configured via the configuration. * are configured via the configuration.
* *
* *
* @author Jens Pelzetter * @author Jens Pelzetter
* @version $Id$ * @version $Id$
*/ */
public class PersonalPublications implements ContentGenerator { public class PersonalPublications implements ContentGenerator {
private final static String MISC = "misc"; private final static String MISC = "misc";
private final static PersonalPublicationsConfig config = new PersonalPublicationsConfig(); private final static PersonalPublicationsConfig CONFIG
private final static Logger logger = Logger.getLogger(PersonalPublications.class); = new PersonalPublicationsConfig();
private static final String REVIEWED = "_reviewed"; private static final String REVIEWED = "_reviewed";
private static final String NOT_REVIEWED = "_notreviewed"; private static final String NOT_REVIEWED = "_notreviewed";
/**
* Template for the query to fetch the publications assigned to the
* category.
*/
private final static String PUBLIATIONS_QUERY_TEMPLATE
= "SELECT cms_items.item_id, name, version, language, object_type, "
+ "master_id, parent_id, title, cms_pages.description, "
+ "year, abstract, misc, reviewed, authors, firstPublished, lang, "
+ "isbn, ct_publication_with_publisher.volume, number_of_volumes, _number_of_pages, ct_publication_with_publisher.edition, "
+ "nameofconference, place_of_conference, date_from_of_conference, date_to_of_conference, "
+ "ct_article_in_collected_volume.pages_from AS collvol_pages_from, ct_article_in_collected_volume.pages_to AS collvol_pages_to, chapter, "
+ "ct_article_in_journal.pages_from AS journal_pages_from, ct_article_in_journal.pages_to AS journal_pages_to, ct_article_in_journal.volume AS journal_volume, issue, publication_date, "
+ "ct_expertise.place AS expertise_place, ct_expertise.number_of_pages AS expertise_number_of_pages, "
+ "ct_inproceedings.pages_from AS inproceedings_pages_from, ct_inproceedings.pages_to AS inproceedings_pages_to, "
+ "ct_internet_article.place AS internet_article_place, "
+ "ct_internet_article.number AS internet_article_number, "
+ "ct_internet_article.number_of_pages AS internet_article_number_of_pages, "
+ "ct_internet_article.edition AS internet_article_edition, "
+ "ct_internet_article.issn AS internet_article_issn, "
+ "ct_internet_article.last_accessed AS internet_article_last_accessed, "
+ "ct_internet_article.publicationdate AS internet_article_publication_date, "
+ "ct_internet_article.url AS internet_article_url, "
+ "ct_internet_article.urn AS internet_article_urn, "
+ "ct_internet_article.doi AS internet_article_doi, "
+ "ct_unpublished.place AS unpublished_place, "
+ "ct_unpublished.number AS unpublished_number, "
+ "ct_unpublished.number_of_pages AS unpublished_number_of_pages, "
+ "ct_grey_literature.pagesfrom AS grey_literature_pages_from, "
+ "ct_grey_literature.pagesto AS grey_literature_pages_to "
+ "FROM cms_items "
+ "JOIN cms_pages ON cms_items.item_id = cms_pages.item_id "
+ "JOIN content_types ON cms_items.type_id = content_types.type_id "
+ "JOIN ct_publications ON cms_items.item_id = ct_publications.publication_id "
+ "LEFT JOIN ct_publication_with_publisher ON ct_publications.publication_id = ct_publication_with_publisher.publication_with_publisher_id "
+ "LEFT JOIN ct_proceedings ON ct_publications.publication_id = ct_proceedings.proceedings_id "
+ "LEFT JOIN ct_article_in_collected_volume ON ct_publications.publication_id = ct_article_in_collected_volume.article_id "
+ "LEFT JOIN ct_article_in_journal ON ct_publications.publication_id = ct_article_in_journal.article_in_journal_id "
+ "LEFT JOIN ct_expertise ON ct_publications.publication_id = ct_expertise.expertise_id "
+ "LEFT JOIN ct_inproceedings ON ct_publications.publication_id = ct_inproceedings.inproceedings_id "
+ "LEFT JOIN ct_internet_article ON ct_publications.publication_id = ct_internet_article.internet_article_id "
+ "LEFT JOIN ct_unpublished ON ct_publications.publication_id = ct_unpublished.unpublished_id "
+ "LEFT JOIN ct_grey_literature ON ct_unpublished.unpublished_id = ct_grey_literature.grey_literature_id "
+ "%s"
+ "WHERE parent_id IN (SELECT bundle_id FROM ct_publication_bundles JOIN ct_publications_authorship ON ct_publication_bundles.bundle_id = ct_publications_authorship.publication_id WHERE person_id = ?) AND language = ? AND version = 'live' %s"
+ "%s "
+ "LIMIT ? OFFSET ?";
/**
* Template for the query for counting the publications assigned to the
* category.
*/
private final static String COUNT_PUBLICATIONS_QUERY_TEMPLATE
= "SELECT COUNT(*) "
+ "FROM cms_items "
+ "JOIN cms_pages ON cms_items.item_id = cms_pages.item_id "
+ "JOIN content_types ON cms_items.type_id = content_types.type_id "
+ "JOIN ct_publications ON cms_items.item_id = ct_publications.publication_id "
+ "LEFT JOIN ct_publication_with_publisher ON ct_publications.publication_id = ct_publication_with_publisher.publication_with_publisher_id "
+ "LEFT JOIN ct_proceedings ON ct_publications.publication_id = ct_proceedings.proceedings_id "
+ "LEFT JOIN ct_article_in_collected_volume ON ct_publications.publication_id = ct_article_in_collected_volume.article_id "
+ "LEFT JOIN ct_article_in_journal ON ct_publications.publication_id = ct_article_in_journal.article_in_journal_id "
+ "LEFT JOIN ct_expertise ON ct_publications.publication_id = ct_expertise.expertise_id "
+ "LEFT JOIN ct_inproceedings ON ct_publications.publication_id = ct_inproceedings.inproceedings_id "
+ "LEFT JOIN ct_internet_article ON ct_publications.publication_id = ct_internet_article.internet_article_id "
+ "LEFT JOIN ct_unpublished ON ct_publications.publication_id = ct_unpublished.unpublished_id "
+ "LEFT JOIN ct_grey_literature ON ct_unpublished.unpublished_id = ct_grey_literature.grey_literature_id "
+ "%s"
+ "WHERE parent_id IN (SELECT bundle_id FROM ct_publication_bundles JOIN ct_publications_authorship ON ct_publication_bundles.bundle_id = ct_publications_authorship.publication_id WHERE person_id = ?) AND version = 'live' %s";
static { static {
config.load(); CONFIG.load();
} }
@Override @Override
@ -48,11 +123,24 @@ public class PersonalPublications implements ContentGenerator {
final GenericPerson person, final GenericPerson person,
final PageState state, final PageState state,
final String language) { final String language) {
if (CONFIG.getUseNativeSql()) {
generateContentNativeSql(parent, person, state, language);
} else {
generateContentPDL(parent, person, state, language);
}
}
public void generateContentPDL(final Element parent,
final GenericPerson person,
final PageState state,
final String language) {
//final long start = System.currentTimeMillis(); //final long start = System.currentTimeMillis();
final List<PublicationBundle> publications = collectPublications(person, language); final List<PublicationBundle> publications = collectPublications(person,
language);
final Element personalPubsElem = parent.newChildElement("personalPublications"); final Element personalPubsElem = parent.newChildElement(
"personalPublications");
final long overallSize; final long overallSize;
if (publications == null) { if (publications == null) {
overallSize = 0; overallSize = 0;
@ -61,26 +149,30 @@ public class PersonalPublications implements ContentGenerator {
} }
if (overallSize <= 0) { if (overallSize <= 0) {
personalPubsElem.newChildElement("noPublications"); personalPubsElem.newChildElement("noPublications");
return;
} else { } else {
final Map<String, List<String>> groupsConfig = getGroupsConfig(); final Map<String, List<String>> groupsConfig = getGroupsConfig();
final Map<String, List<PublicationBundle>> publicationsByGroup = final Map<String, List<PublicationBundle>> publicationsByGroup
new LinkedHashMap<String, List<PublicationBundle>>(); = new LinkedHashMap<>();
for (Map.Entry<String, List<String>> entry : groupsConfig.entrySet()) { for (Map.Entry<String, List<String>> entry : groupsConfig.entrySet()) {
filterPublicationsByGroup(entry.getKey(), entry.getValue(), publications, publicationsByGroup); filterPublicationsByGroup(entry.getKey(), entry.getValue(),
publications, publicationsByGroup);
} }
final List<PublicationBundle> miscGroup = filterPublicationsForMiscGroup(publications, groupsConfig); final List<PublicationBundle> miscGroup
= filterPublicationsForMiscGroup(
publications, groupsConfig);
publicationsByGroup.put(MISC, miscGroup); publicationsByGroup.put(MISC, miscGroup);
final Element availableGroupsElem = personalPubsElem.newChildElement("availablePublicationGroups"); final Element availableGroupsElem = personalPubsElem
final Element publicationsElem = personalPubsElem.newChildElement("publications"); .newChildElement("availablePublicationGroups");
final Element publicationsElem = personalPubsElem.newChildElement(
"publications");
if (overallSize < config.getGroupSplit()) { if (overallSize < CONFIG.getGroupSplit()) {
publicationsElem.addAttribute("all", "all"); publicationsElem.addAttribute("all", "all");
for (Map.Entry<String, List<PublicationBundle>> group : publicationsByGroup.entrySet()) { for (Map.Entry<String, List<PublicationBundle>> group
: publicationsByGroup.entrySet()) {
generateXmlForGroup(group.getKey(), generateXmlForGroup(group.getKey(),
availableGroupsElem, availableGroupsElem,
publicationsElem, publicationsElem,
@ -90,11 +182,14 @@ public class PersonalPublications implements ContentGenerator {
state); state);
} }
} else { } else {
final List<String> availableGroups = new LinkedList<String>(); final List<String> availableGroups = new LinkedList<>();
for (Map.Entry<String, List<String>> entry : groupsConfig.entrySet()) { for (Map.Entry<String, List<String>> entry : groupsConfig
.entrySet()) {
if ((publicationsByGroup.get(entry.getKey()) != null) if ((publicationsByGroup.get(entry.getKey()) != null)
&& !(publicationsByGroup.get(entry.getKey()).isEmpty())) { && !(publicationsByGroup.get(entry.getKey())
generateAvailableForGroup(entry.getKey(), availableGroupsElem); .isEmpty())) {
generateAvailableForGroup(entry.getKey(),
availableGroupsElem);
availableGroups.add(entry.getKey()); availableGroups.add(entry.getKey());
} }
} }
@ -105,7 +200,9 @@ public class PersonalPublications implements ContentGenerator {
} }
final HttpServletRequest request = state.getRequest(); final HttpServletRequest request = state.getRequest();
final String group = selectGroup(request, config.getDefaultGroup(), availableGroups); final String group = selectGroup(request, CONFIG
.getDefaultGroup(),
availableGroups);
generateXmlForGroup(group, generateXmlForGroup(group,
availableGroupsElem, availableGroupsElem,
@ -127,11 +224,180 @@ public class PersonalPublications implements ContentGenerator {
}*/ }*/
} }
private List<PublicationBundle> collectPublications(final GenericPerson author, final String language) { public void generateContentNativeSql(final Element parent,
final List<PublicationBundle> publications = final GenericPerson person,
new LinkedList<PublicationBundle>(); final PageState state,
final String language) {
final Connection connection = SessionManager
.getSession()
.getConnection();
final PreparedStatement publicationsQueryStatement;
final PreparedStatement authorsQueryStatement;
final PreparedStatement publisherQueryStatement;
final PreparedStatement journalQueryStatement;
final PreparedStatement collectedVolumeQueryStatement;
final PreparedStatement proceedingsQueryStatement;
final PreparedStatement organizationQueryStatement;
final StringBuffer whereBuffer = new StringBuffer();
final int page;
final int offset;
int limit = 20;
final String personId = person.getParent().getID().toString();
try {
authorsQueryStatement = connection
.prepareStatement(
"SELECT surname, givenname, titlepre, titlepost, editor, authorship_order "
+ "FROM cms_persons "
+ "JOIN cms_items ON cms_persons.person_id = cms_items.item_id "
+ "JOIN cms_bundles ON cms_items.parent_id = cms_bundles.bundle_id "
+ "JOIN ct_publications_authorship ON cms_bundles.bundle_id = ct_publications_authorship.person_id "
+ "WHERE publication_id = ? "
+ "ORDER BY authorship_order");
publisherQueryStatement = connection
.prepareStatement(
"SELECT publishername, ct_publisher.place "
+ "FROM ct_publisher "
+ "JOIN cms_items ON ct_publisher.publisher_id = cms_items.item_id "
+ "JOIN cms_bundles ON cms_items.parent_id = cms_bundles.bundle_id "
+ "JOIN ct_publication_with_publisher_publisher_map ON cms_bundles.bundle_id = ct_publication_with_publisher_publisher_map.publisher_id "
+ "WHERE publication_id = ?");
journalQueryStatement = connection
.prepareStatement(
"SELECT title "
+ "FROM cms_items "
+ "JOIN cms_pages ON cms_items.item_id = cms_pages.item_id "
+ "JOIN ct_journal ON cms_items.item_id = ct_journal.journal_id "
+ "JOIN cms_bundles ON cms_items.parent_id = cms_bundles.bundle_id "
+ "JOIN ct_journal_article_map ON cms_bundles.bundle_id = ct_journal_article_map.journal_id "
+ "WHERE article_in_journal_id = ?");
collectedVolumeQueryStatement = connection
.prepareStatement(
"SELECT cms_items.item_id, name, version, language, master_id, "
+ "parent_id, title, cms_pages.description, year, abstract, "
+ "misc, reviewed, authors, firstPublished, lang, isbn, "
+ "ct_publication_with_publisher.volume, number_of_volumes, "
+ "_number_of_pages, ct_publication_with_publisher.edition "
+ "FROM cms_items "
+ "JOIN cms_pages ON cms_items.item_id = cms_pages.item_id "
+ "JOIN ct_publications ON cms_items.item_id = ct_publications.publication_id "
+ "JOIN ct_publication_with_publisher ON ct_publications.publication_id = ct_publication_with_publisher.publication_with_publisher_id "
+ "JOIN ct_collected_volume ON ct_publication_with_publisher.publication_with_publisher_id = ct_collected_volume.collected_volume_id "
+ "JOIN cms_bundles ON cms_items.parent_id = cms_bundles.bundle_id "
+ "JOIN ct_collected_volume_article_map ON cms_bundles.bundle_id = ct_collected_volume_article_map.collected_volume_id "
+ "WHERE ct_collected_volume_article_map.article_id = ?");
proceedingsQueryStatement = connection
.prepareStatement(
"SELECT cms_items.item_id, name, version, language, master_id, "
+ "parent_id, title, cms_pages.description, year, abstract, "
+ "misc, reviewed, authors, firstPublished, lang, isbn, "
+ "ct_publication_with_publisher.volume, number_of_volumes, "
+ "_number_of_pages, ct_publication_with_publisher.edition "
+ "nameofconference, place_of_conference, date_from_of_conference, date_to_of_conference "
+ "FROM cms_items "
+ "JOIN cms_pages ON cms_items.item_id = cms_pages.item_id "
+ "JOIN ct_publications ON cms_items.item_id = ct_publications.publication_id "
+ "JOIN ct_publication_with_publisher ON ct_publications.publication_id = ct_publication_with_publisher.publication_with_publisher_id "
+ "JOIN ct_proceedings ON ct_publication_with_publisher.publication_with_publisher_id = ct_proceedings.proceedings_id "
+ "JOIN cms_bundles ON cms_items.parent_id = cms_bundles.bundle_id "
+ "JOIN ct_proceedings_papers_map ON cms_bundles.bundle_id = ct_proceedings_papers_map.proceedings_id "
+ "WHERE ct_proceedings_papers_map.paper_id = ?"
);
organizationQueryStatement = connection
.prepareStatement(
"SELECT cms_items.item_id, name, version, language, master_id, "
+ "parent_id, title, cms_pages.description "
+ "FROM cms_items "
+ "JOIN cms_pages ON cms_items.item_id = cms_pages.item_id "
+ "JOIN cms_bundles ON cms_items.parent_id = cms_bundles.bundle_id "
+ "JOIN ct_unpublished_organization_map ON cms_bundles.bundle_id = ct_unpublished_organization_map.organization_id "
+ "WHERE ct_unpublished_organization_map.unpublished_id = ?");
final String orderBy = "ORDER BY year DESC, authors, title ";
publicationsQueryStatement = connection
.prepareStatement(String.format(PUBLIATIONS_QUERY_TEMPLATE,
"",
whereBuffer.toString(),
orderBy));
publicationsQueryStatement.setString(1, personId);
publicationsQueryStatement.setString(2, language);
publicationsQueryStatement.setInt(3, limit);
if (state.getRequest().getParameter("page") == null) {
page = 1;
publicationsQueryStatement.setInt(4, 0);
offset = 0;
} else {
page = Integer.parseInt(state.getRequest().getParameter("page"));
offset = (page - 1) * limit;
publicationsQueryStatement.setInt(4, offset);
}
} catch (SQLException ex) {
throw new UncheckedWrapperException(ex);
}
try (final ResultSet mainQueryResult = publicationsQueryStatement
.executeQuery()) {
final Element personalPubsElem = parent
.newChildElement("personalPublications");
final Element paginatorElem = personalPubsElem
.newChildElement("paginator");
final PreparedStatement countPublicationsQueryStatement = connection
.prepareStatement(String.format(
COUNT_PUBLICATIONS_QUERY_TEMPLATE,
"",
whereBuffer.toString()));
countPublicationsQueryStatement.setString(1, personId);
final ResultSet countResultSet = countPublicationsQueryStatement
.executeQuery();
final int count;
if (countResultSet.next()) {
count = countResultSet.getInt(1);
paginatorElem.addAttribute("count", Integer.toString(count));
} else {
count = 0;
}
final int maxPages = (int) Math.ceil(count / (double) limit);
paginatorElem.addAttribute("maxPages", Integer.toString(maxPages));
paginatorElem.addAttribute("currentPage", Integer.toString(page));
paginatorElem.addAttribute("offset", Integer.toString(offset));
paginatorElem.addAttribute("limit", Integer.toString(limit));
while (mainQueryResult.next()) {
final Element elem = personalPubsElem.newChildElement(
"publication");
final Element title = elem.newChildElement("title");
title.setText(mainQueryResult.getString("title"));
}
} catch (SQLException ex) {
throw new UncheckedWrapperException(ex);
}
}
private List<PublicationBundle> collectPublications(
final GenericPerson author, final String language) {
final List<PublicationBundle> publications = new LinkedList<>();
//final List<BigDecimal> processed = new ArrayList<BigDecimal>(); //final List<BigDecimal> processed = new ArrayList<BigDecimal>();
final DataCollection collection = (DataCollection) author.getGenericPersonBundle().get("publication"); final DataCollection collection = (DataCollection) author
.getGenericPersonBundle().get("publication");
collection.addEqualsFilter("version", "live"); collection.addEqualsFilter("version", "live");
DomainObject obj; DomainObject obj;
while (collection.next()) { while (collection.next()) {
@ -152,7 +418,8 @@ public class PersonalPublications implements ContentGenerator {
private void collectPublications(final GenericPerson alias, private void collectPublications(final GenericPerson alias,
final List<PublicationBundle> publications, final List<PublicationBundle> publications,
final String language) { final String language) {
final DataCollection collection = (DataCollection) alias.getGenericPersonBundle().get("publication"); final DataCollection collection = (DataCollection) alias
.getGenericPersonBundle().get("publication");
collection.addEqualsFilter("version", "live"); collection.addEqualsFilter("version", "live");
DomainObject obj; DomainObject obj;
while (collection.next()) { while (collection.next()) {
@ -168,9 +435,9 @@ public class PersonalPublications implements ContentGenerator {
} }
private Map<String, List<String>> getGroupsConfig() { private Map<String, List<String>> getGroupsConfig() {
final String conf = config.getPublictionGroups(); final String conf = CONFIG.getPublictionGroups();
final Map<String, List<String>> groups = new LinkedHashMap<String, List<String>>(); final Map<String, List<String>> groups = new LinkedHashMap<>();
final String[] groupTokens = conf.split(";"); final String[] groupTokens = conf.split(";");
for (String groupToken : groupTokens) { for (String groupToken : groupTokens) {
@ -187,7 +454,7 @@ public class PersonalPublications implements ContentGenerator {
throw new IllegalArgumentException("Failed to parse group config."); throw new IllegalArgumentException("Failed to parse group config.");
} }
final List<String> types = new ArrayList<String>(); final List<String> types = new ArrayList<>();
final String[] typeTokens = tokens[1].split(","); final String[] typeTokens = tokens[1].split(",");
for (String typeToken : typeTokens) { for (String typeToken : typeTokens) {
types.add(typeToken.trim()); types.add(typeToken.trim());
@ -196,8 +463,10 @@ public class PersonalPublications implements ContentGenerator {
groups.put(tokens[0], types); groups.put(tokens[0], types);
} }
private void generateAvailableForGroup(final String groupName, final Element availableGroupsElem) { private void generateAvailableForGroup(final String groupName,
final Element group = availableGroupsElem.newChildElement("availablePublicationGroup"); final Element availableGroupsElem) {
final Element group = availableGroupsElem.newChildElement(
"availablePublicationGroup");
group.addAttribute("name", groupName); group.addAttribute("name", groupName);
} }
@ -211,44 +480,54 @@ public class PersonalPublications implements ContentGenerator {
List<PublicationBundle> publicationList = publications; List<PublicationBundle> publicationList = publications;
Collections.sort(publicationList, new Comparator<PublicationBundle>() { Collections.sort(publicationList, new Comparator<PublicationBundle>() {
@Override
public int compare(final PublicationBundle bundle1, final PublicationBundle bundle2) {
final Publication publication1 = bundle1.getPublication(GlobalizationHelper.getNegotiatedLocale().
getLanguage());
final Publication publication2 = bundle2.getPublication(GlobalizationHelper.getNegotiatedLocale().
getLanguage());
final int year1; @Override
final int year2; public int compare(final PublicationBundle bundle1,
if (publication1.getYearOfPublication() == null) { final PublicationBundle bundle2) {
year1 = 0; final Publication publication1 = bundle1
} else { .getPublication(GlobalizationHelper
year1 = publication1.getYearOfPublication(); .getNegotiatedLocale().
} getLanguage());
if (publication2.getYearOfPublication() == null) { final Publication publication2 = bundle2
year2 = 0; .getPublication(GlobalizationHelper
} else { .getNegotiatedLocale().
year2 = publication2.getYearOfPublication(); getLanguage());
}
if (year1 < year2) { final int year1;
return 1; final int year2;
} else if (year1 > year2) { if (publication1.getYearOfPublication() == null) {
return -1; year1 = 0;
} } else {
year1 = publication1.getYearOfPublication();
}
if (publication2.getYearOfPublication() == null) {
year2 = 0;
} else {
year2 = publication2.getYearOfPublication();
}
final String authorsStr1 = (String) publication1.get("authorsStr"); if (year1 < year2) {
final String authorsStr2 = (String) publication2.get("authorsStr"); return 1;
} else if (year1 > year2) {
return -1;
}
if ((authorsStr1 != null) && (authorsStr2 != null) && (authorsStr1.compareTo(authorsStr2) != 0)) { final String authorsStr1 = (String) publication1
return authorsStr1.compareTo(authorsStr2); .get("authorsStr");
} final String authorsStr2 = (String) publication2
.get("authorsStr");
return publication1.getTitle().compareTo(publication2.getTitle()); if ((authorsStr1 != null) && (authorsStr2 != null)
&& (authorsStr1.compareTo(authorsStr2) != 0)) {
return authorsStr1.compareTo(authorsStr2);
}
} return publication1.getTitle().compareTo(
publication2.getTitle());
}); }
});
if ((publications == null) || publications.isEmpty()) { if ((publications == null) || publications.isEmpty()) {
return; return;
@ -258,24 +537,33 @@ public class PersonalPublications implements ContentGenerator {
generateAvailableForGroup(groupName, availableGroupsElem); generateAvailableForGroup(groupName, availableGroupsElem);
} }
final Element groupElem = publicationsElem.newChildElement("publicationGroup"); final Element groupElem = publicationsElem.newChildElement(
"publicationGroup");
groupElem.addAttribute("name", groupName); groupElem.addAttribute("name", groupName);
if (withPaginator) { if (withPaginator) {
final Paginator paginator = new Paginator(state.getRequest(), publications.size(), config.getPageSize()); final Paginator paginator = new Paginator(state.getRequest(),
publications.size(),
CONFIG.getPageSize());
//publicationList = publicationList.subList(paginator.getBegin() - 1, paginator.getEnd() - 1); //publicationList = publicationList.subList(paginator.getBegin() - 1, paginator.getEnd() - 1);
publicationList = paginator.applyListLimits(publicationList, PublicationBundle.class); publicationList = paginator.applyListLimits(publicationList,
PublicationBundle.class);
paginator.generateXml(groupElem); paginator.generateXml(groupElem);
} }
for (PublicationBundle publication : publicationList) { for (PublicationBundle publication : publicationList) {
generatePublicationXml(publication.getPublication( generatePublicationXml(publication.getPublication(
GlobalizationHelper.getNegotiatedLocale().getLanguage()), groupElem, state); GlobalizationHelper.getNegotiatedLocale().getLanguage()),
groupElem, state);
} }
} }
private void generatePublicationXml(final Publication publication, final Element parent, final PageState state) { private void generatePublicationXml(final Publication publication,
final PersonalPublications.XmlGenerator generator = new PersonalPublications.XmlGenerator(publication); final Element parent,
final PageState state) {
final PersonalPublications.XmlGenerator generator
= new PersonalPublications.XmlGenerator(
publication);
generator.setItemElemName("publications", ""); generator.setItemElemName("publications", "");
generator.setListMode(true); generator.setListMode(true);
generator.generateXML(state, parent, ""); generator.generateXML(state, parent, "");
@ -301,7 +589,8 @@ public class PersonalPublications implements ContentGenerator {
final String defaultGroupConfig, final String defaultGroupConfig,
final List<String> availableGroups) { final List<String> availableGroups) {
String group = request.getParameter("group"); String group = request.getParameter("group");
if ((group == null) || group.trim().isEmpty() || !(availableGroups.contains(group))) { if ((group == null) || group.trim().isEmpty() || !(availableGroups
.contains(group))) {
String defaultGroups[] = defaultGroupConfig.split(","); String defaultGroups[] = defaultGroupConfig.split(",");
for (String defaultGroup : defaultGroups) { for (String defaultGroup : defaultGroups) {
@ -316,11 +605,11 @@ public class PersonalPublications implements ContentGenerator {
} }
private void filterPublicationsByGroup( private void filterPublicationsByGroup(
final String groupName, final String groupName,
final List<String> typeTokens, final List<String> typeTokens,
final List<PublicationBundle> publications, final List<PublicationBundle> publications,
final Map<String, List<PublicationBundle>> publicationsByGroup) { final Map<String, List<PublicationBundle>> publicationsByGroup) {
final List<PublicationBundle> group = new LinkedList<PublicationBundle>(); final List<PublicationBundle> group = new LinkedList<>();
for (PublicationBundle publication : publications) { for (PublicationBundle publication : publications) {
for (String typeToken : typeTokens) { for (String typeToken : typeTokens) {
@ -356,14 +645,17 @@ public class PersonalPublications implements ContentGenerator {
} }
if (reviewed == null) { if (reviewed == null) {
if (publication.getContentType().getAssociatedObjectType().equals(type)) { if (publication.getContentType().getAssociatedObjectType().equals(
type)) {
group.add(publication); group.add(publication);
return true; return true;
} }
} else { } else {
final Boolean pubReviewed = ((Publication) publication.getPrimaryInstance()).getReviewed(); final Boolean pubReviewed = ((Publication) publication
if (publication.getContentType().getAssociatedObjectType().equals(type) .getPrimaryInstance()).getReviewed();
&& (reviewed.equals(pubReviewed) || (pubReviewed == null))) { if (publication.getContentType().getAssociatedObjectType().equals(
type)
&& (reviewed.equals(pubReviewed) || (pubReviewed == null))) {
group.add(publication); group.add(publication);
return true; return true;
} }
@ -373,15 +665,16 @@ public class PersonalPublications implements ContentGenerator {
} }
private List<PublicationBundle> filterPublicationsForMiscGroup( private List<PublicationBundle> filterPublicationsForMiscGroup(
final List<PublicationBundle> publications, final List<PublicationBundle> publications,
final Map<String, List<String>> groupsConfig) { final Map<String, List<String>> groupsConfig) {
final List<PublicationBundle> misc = new LinkedList<PublicationBundle>(); final List<PublicationBundle> misc = new LinkedList<>();
boolean found = false; boolean found = false;
for (PublicationBundle publication : publications) { for (PublicationBundle publication : publications) {
for (Map.Entry<String, List<String>> entry : groupsConfig.entrySet()) { for (Map.Entry<String, List<String>> entry : groupsConfig.entrySet()) {
for (String type : entry.getValue()) { for (String type : entry.getValue()) {
if (publication.getContentType().getAssociatedObjectType().equals(getTypeFromTypeToken(type))) { if (publication.getContentType().getAssociatedObjectType()
.equals(getTypeFromTypeToken(type))) {
found = true; found = true;
} }
} }

View File

@ -2,21 +2,23 @@ package com.arsdigita.cms.publicpersonalprofile;
import com.arsdigita.cms.contenttypes.Publication; import com.arsdigita.cms.contenttypes.Publication;
import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.IntegerParameter; import com.arsdigita.util.parameter.IntegerParameter;
import com.arsdigita.util.parameter.Parameter; import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.StringParameter; import com.arsdigita.util.parameter.StringParameter;
/** /**
* *
* @author Jens Pelzetter * @author Jens Pelzetter
* @version $Id$ * @version $Id: PersonalPublicationsConfig.java 1870 2012-09-23 07:29:10Z jensp
* $
*/ */
public class PersonalPublicationsConfig extends AbstractConfig { public class PersonalPublicationsConfig extends AbstractConfig {
/** /**
* <p> * <p>
* Groups of publications. The syntax for this string is as follows * Groups of publications. The syntax for this string is as follows (as
* (as EBNF): * EBNF):
* </p> * </p>
* <pre> * <pre>
* publicationGroupsConfig = groupDefinition {";"groupDefinition}; * publicationGroupsConfig = groupDefinition {";"groupDefinition};
@ -24,34 +26,34 @@ public class PersonalPublicationsConfig extends AbstractConfig {
* typeDef = typeName["_ref"]; * typeDef = typeName["_ref"];
* </pre> * </pre>
* <p> * <p>
* The groups definition string consists of one or more group definitions. * The groups definition string consists of one or more group definitions.
* Group definitions are separated by the semicolon {@code ;}. * Group definitions are separated by the semicolon {@code ;}. Each groups
* Each groups definition consists of a group name and a comma separated * definition consists of a group name and a comma separated lists of type
* lists of type names. Group name and types names are separated by a colon. * names. Group name and types names are separated by a colon.
* </p> * </p>
* <p> * <p>
* {@code groupName} and {@code typeName} are not shown in the above * {@code groupName} and {@code typeName} are not shown in the above
* grammar. A group name may contain all letters (uppercase and * grammar. A group name may contain all letters (uppercase and lowercase),
* lowercase), all numbers and the underscore "{@code _}". A type name * all numbers and the underscore "{@code _}". A type name is the fully
* is the fully qualified name of content type derived from * qualified name of content type derived from {@link Publication}. A type
* {@link Publication}. A type name can be followed by the literals * name can be followed by the literals {@code _reviewed} and
* {@code _reviewed} and {@code _notriewed}. If a type name is not followed by * {@code _notriewed}. If a type name is not followed by one of this
* one of this literals, all publications of the type will be put into the * literals, all publications of the type will be put into the group. If the
* group. If the type name is followed by one of this literals, the property * type name is followed by one of this literals, the property
* {@code reviewed} is checked. If the type has this property, publications * {@code reviewed} is checked. If the type has this property, publications
* can be split into reviewed and not reviewed publications. * can be split into reviewed and not reviewed publications.
* </p> * </p>
*/ */
private final Parameter publicationGroups; private final Parameter publicationGroups;
/** /**
* If a person has more ({@code >=}) publications then this number, only one * If a person has more ({@code >=}) publications then this number, only one
* group of publications will be shown. If a person has less publications, * group of publications will be shown. If a person has less publications,
* all groups are shown. * all groups are shown.
*/ */
private final Parameter groupSplit; private final Parameter groupSplit;
/** /**
* The group of publications to show if no group has been requested or the * The group of publications to show if no group has been requested or the
* requested group is invalid. The values of this parameter * requested group is invalid. The values of this parameter
* <strong>must be</strong> a group defined in the {@code publicationGroups} * <strong>must be</strong> a group defined in the {@code publicationGroups}
* parameter. Otherwise, the {@link PersonalPublications} generator may * parameter. Otherwise, the {@link PersonalPublications} generator may
* crashes! The parameter accepts a comma separated list of groups which * crashes! The parameter accepts a comma separated list of groups which
@ -63,45 +65,50 @@ public class PersonalPublicationsConfig extends AbstractConfig {
private final Parameter defaultGroup; private final Parameter defaultGroup;
private final Parameter pageSize; private final Parameter pageSize;
private final Parameter order; private final Parameter order;
private final Parameter useNativeSql;
public PersonalPublicationsConfig() { public PersonalPublicationsConfig() {
publicationGroups = publicationGroups = new StringParameter(
new StringParameter( "com.arsdigita.cms.publicpersonalprofile.publications.groups",
"com.arsdigita.cms.publicpersonalprofile.publications.groups", Parameter.REQUIRED,
Parameter.REQUIRED, "monographs:com.arsdigita.cms.contenttypes.Monograph;"
"monographs:com.arsdigita.cms.contenttypes.Monograph;"
+ "collectedVolumes:com.arsdigita.cms.contenttypes.CollectedVolume;" + "collectedVolumes:com.arsdigita.cms.contenttypes.CollectedVolume;"
+ "collectedVolumeArticles:com.arsdigita.cms.contenttypes.ArticleInCollectedVolume;" + "collectedVolumeArticles:com.arsdigita.cms.contenttypes.ArticleInCollectedVolume;"
+ "journalArticlesReviewed:com.arsdigita.cms.contenttypes.ArticleInJournal_reviewed;" + "journalArticlesReviewed:com.arsdigita.cms.contenttypes.ArticleInJournal_reviewed;"
+ "journalArticles:com.arsdigita.cms.contenttypes.ArticleInJournal_notreviewed"); + "journalArticles:com.arsdigita.cms.contenttypes.ArticleInJournal_notreviewed");
groupSplit = new IntegerParameter( groupSplit = new IntegerParameter(
"com.arsdigita.cms.publicpersonlprofile.publications.groupSplit", "com.arsdigita.cms.publicpersonlprofile.publications.groupSplit",
Parameter.REQUIRED, Parameter.REQUIRED,
12); 12);
defaultGroup = defaultGroup = new StringParameter(
new StringParameter( "com.arsdigita.cms.publicpersonalprofile.publications.defaultGroup",
"com.arsdigita.cms.publicpersonalprofile.publications.defaultGroup", Parameter.REQUIRED,
Parameter.REQUIRED, "monographs,journalArticlesReviewed,journalArticles,misc");
"monographs,journalArticlesReviewed,journalArticles,misc");
pageSize = new IntegerParameter( pageSize = new IntegerParameter(
"com.arsdigita.cms.publicpersonlprofile.publications.pageSize", "com.arsdigita.cms.publicpersonlprofile.publications.pageSize",
Parameter.REQUIRED, Parameter.REQUIRED,
10); 10);
order = new StringParameter( order = new StringParameter(
"com.arsdigita.cms.publicpersonlprofile.publications.order", "com.arsdigita.cms.publicpersonlprofile.publications.order",
Parameter.REQUIRED, Parameter.REQUIRED,
"year,authors,title"); "year,authors,title");
useNativeSql = new BooleanParameter(
"com.arsdigita.cms.publicpersonalprofile.publications.use_native_sql",
Parameter.OPTIONAL,
Boolean.FALSE);
register(publicationGroups); register(publicationGroups);
register(groupSplit); register(groupSplit);
register(defaultGroup); register(defaultGroup);
register(pageSize); register(pageSize);
register(order); register(order);
register(useNativeSql);
loadInfo(); loadInfo();
} }
@ -124,5 +131,8 @@ public class PersonalPublicationsConfig extends AbstractConfig {
public final String getOrder() { public final String getOrder() {
return (String) get(order); return (String) get(order);
} }
public final Boolean getUseNativeSql() {
return (Boolean) get(useNativeSql);
}
} }

View File

@ -21,4 +21,9 @@ com.arsdigita.cms.publicpersonlprofile.publications.pageSize.format = [Integer]
com.arsdigita.cms.publicpersonlprofile.publications.order.title = Order com.arsdigita.cms.publicpersonlprofile.publications.order.title = Order
com.arsdigita.cms.publicpersonlprofile.publications.order.purpose = Order of publications com.arsdigita.cms.publicpersonlprofile.publications.order.purpose = Order of publications
com.arsdigita.cms.publicpersonlprofile.publications.order.example = Order of publications. Comma separated list of the following properties: title, year, authors com.arsdigita.cms.publicpersonlprofile.publications.order.example = Order of publications. Comma separated list of the following properties: title, year, authors
com.arsdigita.cms.publicpersonlprofile.publications.order.format = [String] com.arsdigita.cms.publicpersonlprofile.publications.order.format = [String]
com.arsdigita.cms.publicpersonalprofile.publications.use_native_sql.title = Use native SQL
com.arsdigita.cms.publicpersonalprofile.publications.use_native_sql.purpose = The personal publication list can either use PDL or native SQL queries to create the lists of personal publications.
com.arsdigita.cms.publicpersonalprofile.publications.use_native_sql.example = false
com.arsdigita.cms.publicpersonalprofile.publications.use_native_sql.format = [Boolean]