0001: /*******************************************************************************
0002: * $URL: https://source.sakaiproject.org/svn/citations/tags/sakai_2-4-1/citations-impl/impl/src/java/org/sakaiproject/citation/impl/BaseCitationService.java $
0003: * $Id: BaseCitationService.java 30509 2007-05-14 20:14:09Z ajpoland@iupui.edu $
0004: * **********************************************************************************
0005: *
0006: * Copyright (c) 2006 The Sakai Foundation.
0007: *
0008: * Licensed under the Educational Community License, Version 1.0 (the
0009: * "License"); you may not use this file except in compliance with the License.
0010: * You may obtain a copy of the License at
0011: *
0012: * http://www.opensource.org/licenses/ecl1.php
0013: *
0014: * Unless required by applicable law or agreed to in writing, software
0015: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0016: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0017: * License for the specific language governing permissions and limitations under
0018: * the License.
0019: *
0020: ******************************************************************************/package org.sakaiproject.citation.impl;
0021:
0022: import java.io.IOException;
0023: import java.io.InputStream;
0024: import java.io.OutputStream;
0025: import java.io.OutputStreamWriter;
0026: import java.io.UnsupportedEncodingException;
0027: import java.util.Collection;
0028: import java.util.Collections;
0029: import java.util.Comparator;
0030: import java.util.HashSet;
0031: import java.util.Hashtable;
0032: import java.util.Iterator;
0033: import java.util.List;
0034: import java.util.ListIterator;
0035: import java.util.Map;
0036: import java.util.NoSuchElementException;
0037: import java.util.Set;
0038: import java.util.SortedSet;
0039: import java.util.Stack;
0040: import java.util.TreeSet;
0041: import java.util.Vector;
0042: import java.net.URLEncoder;
0043:
0044: import org.apache.commons.logging.Log;
0045: import org.apache.commons.logging.LogFactory;
0046: import org.osid.repository.Asset;
0047: import org.osid.repository.Part;
0048: import org.osid.repository.PartIterator;
0049: import org.osid.repository.Record;
0050: import org.osid.repository.RecordIterator;
0051: import org.osid.repository.RepositoryException;
0052: import org.sakaiproject.citation.api.ActiveSearch;
0053: import org.sakaiproject.citation.api.Citation;
0054: import org.sakaiproject.citation.api.CitationCollection;
0055: import org.sakaiproject.citation.api.CitationIterator;
0056: import org.sakaiproject.citation.api.CitationService;
0057: import org.sakaiproject.citation.api.ConfigurationService;
0058: import org.sakaiproject.citation.api.Schema;
0059: import org.sakaiproject.citation.api.Schema.Field;
0060: import org.sakaiproject.component.api.ServerConfigurationService;
0061: import org.sakaiproject.component.cover.ComponentManager;
0062: import org.sakaiproject.content.api.ContentEntity;
0063: import org.sakaiproject.content.api.ContentHostingService;
0064: import org.sakaiproject.content.api.ContentResource;
0065: import org.sakaiproject.content.api.ContentResourceEdit;
0066: import org.sakaiproject.content.api.InteractionAction;
0067: import org.sakaiproject.content.api.ResourceType;
0068: import org.sakaiproject.content.api.ResourceTypeRegistry;
0069: import org.sakaiproject.content.api.ResourceToolAction;
0070: import org.sakaiproject.content.api.ServiceLevelAction;
0071: import org.sakaiproject.content.api.ResourceToolAction.ActionType;
0072: import org.sakaiproject.content.util.BaseInteractionAction;
0073: import org.sakaiproject.content.util.BaseResourceAction;
0074: import org.sakaiproject.content.util.BasicSiteSelectableResourceType; //import org.sakaiproject.content.util.BaseResourceAction.Localizer;
0075: import org.sakaiproject.content.util.BaseServiceLevelAction;
0076: import org.sakaiproject.content.util.BasicResourceType; //import org.sakaiproject.content.util.BasicResourceType.Localizer;
0077:
0078: import org.sakaiproject.entity.api.Entity;
0079: import org.sakaiproject.entity.api.EntityManager;
0080: import org.sakaiproject.entity.api.HttpAccess;
0081: import org.sakaiproject.entity.api.Reference;
0082: import org.sakaiproject.entity.api.ResourceProperties;
0083: import org.sakaiproject.exception.IdUnusedException;
0084: import org.sakaiproject.exception.InUseException;
0085: import org.sakaiproject.exception.OverQuotaException;
0086: import org.sakaiproject.exception.PermissionException;
0087: import org.sakaiproject.exception.ServerOverloadException;
0088: import org.sakaiproject.exception.TypeException;
0089: import org.sakaiproject.id.cover.IdManager;
0090: import org.sakaiproject.javax.Filter;
0091: import org.sakaiproject.tool.api.SessionManager;
0092: import org.sakaiproject.user.api.User;
0093: import org.sakaiproject.user.api.UserDirectoryService;
0094: import org.sakaiproject.util.ResourceLoader;
0095: import org.sakaiproject.util.StringUtil;
0096: import org.w3c.dom.Document;
0097: import org.w3c.dom.Element;
0098:
0099: /**
0100: *
0101: *
0102: */
0103: public abstract class BaseCitationService implements CitationService {
0104: protected boolean attemptToMatchSchema = false;
0105:
0106: protected static final List<String> AUTHOR_AS_KEY = new Vector<String>();
0107: static {
0108: AUTHOR_AS_KEY.add(CitationCollection.SORT_BY_AUTHOR);
0109: AUTHOR_AS_KEY.add(CitationCollection.SORT_BY_UUID);
0110: };
0111:
0112: protected static final List<String> TITLE_AS_KEY = new Vector<String>();
0113:
0114: static {
0115: TITLE_AS_KEY.add(CitationCollection.SORT_BY_TITLE);
0116: TITLE_AS_KEY.add(CitationCollection.SORT_BY_AUTHOR);
0117: TITLE_AS_KEY.add(CitationCollection.SORT_BY_UUID);
0118: };
0119:
0120: public static final Map<String, String> GS_TAGS = new Hashtable<String, String>();
0121: static {
0122: //GS_TAGS.put("rft_val_fmt", "genre");
0123: GS_TAGS.put("rft.title", "title");
0124: GS_TAGS.put("rft.atitle", "title");
0125: GS_TAGS.put("rft.jtitle", "atitle");
0126: GS_TAGS.put("rft.btitle", "atitle");
0127: GS_TAGS.put("rft.aulast", "au");
0128: GS_TAGS.put("rft.aufirst", "au");
0129: GS_TAGS.put("rft.au", "au");
0130: GS_TAGS.put("rft.pub", "publisher");
0131: GS_TAGS.put("rft.volume", "volume");
0132: GS_TAGS.put("rft.issue", "issue");
0133: GS_TAGS.put("rft.pages", "pages");
0134: GS_TAGS.put("rft.date", "date");
0135: GS_TAGS.put("rft.issn", "id");
0136: GS_TAGS.put("rft.isbn", "id");
0137: }
0138:
0139: /**
0140: *
0141: */
0142: public class BasicCitation implements Citation {
0143: /* for OpenUrl creation */
0144: protected final static String OPENURL_VERSION = "Z39.88-2004";
0145: protected final static String OPENURL_CONTEXT_FORMAT = "info:ofi/fmt:kev:mtx:ctx";
0146: protected final static String OPENURL_JOURNAL_FORMAT = "info:ofi/fmt:kev:mtx:journal";
0147: protected final static String OPENURL_BOOK_FORMAT = "info:ofi/fmt:kev:mtx:book";
0148:
0149: protected Map m_citationProperties = null;
0150: protected Map m_urls;
0151: protected String m_citationUrl = null;
0152: protected String m_displayName = null;
0153: protected String m_fullTextUrl = null;
0154: protected String m_id = null;
0155: protected String m_imageUrl = null;
0156: protected Schema m_schema;
0157: protected String m_searchSourceUrl = null;
0158: protected Integer m_serialNumber = null;
0159: protected boolean m_temporary = false;
0160: protected boolean m_isAdded = false;
0161:
0162: /**
0163: * Constructs a temporary citation.
0164: */
0165: protected BasicCitation() {
0166: m_serialNumber = nextSerialNumber();
0167: m_temporary = true;
0168: m_citationProperties = new Hashtable();
0169: m_urls = new Hashtable();
0170: setType(CitationService.UNKNOWN_TYPE);
0171: }
0172:
0173: /**
0174: * Constructs a temporary citation based on an asset.
0175: *
0176: * @param asset
0177: */
0178: protected BasicCitation(Asset asset) {
0179: m_serialNumber = nextSerialNumber();
0180: m_temporary = true;
0181: m_citationProperties = new Hashtable();
0182: m_urls = new Hashtable();
0183:
0184: boolean unknownSchema = true;
0185:
0186: Set validProperties = getValidPropertyNames();
0187: Set multivalued = getMultivalued();
0188:
0189: String description;
0190:
0191: // assetId = asset.getId().getIdString();
0192: try {
0193: m_displayName = asset.getDisplayName();
0194: if (this .m_displayName != null) {
0195: m_citationProperties.put(Schema.TITLE,
0196: this .m_displayName);
0197: }
0198:
0199: description = asset.getDescription();
0200: if (description != null) {
0201: m_citationProperties.put("abstract", description);
0202: }
0203:
0204: RecordIterator rit = asset.getRecords();
0205: try {
0206: while (rit.hasNextRecord()) {
0207: Record record;
0208: try {
0209: record = rit.nextRecord();
0210:
0211: try {
0212: PartIterator pit = record.getParts();
0213: try {
0214: while (pit.hasNextPart()) {
0215: try {
0216: Part part = pit.nextPart();
0217: String type = part
0218: .getPartStructure()
0219: .getType()
0220: .getKeyword();
0221: if (type == null) {
0222: // continue;
0223: } else if (validProperties
0224: .contains(type)) {
0225:
0226: if (multivalued
0227: .contains(type)) {
0228: List values = (List) m_citationProperties
0229: .get(type);
0230: if (values == null) {
0231: values = new Vector();
0232: m_citationProperties
0233: .put(
0234: type,
0235: values);
0236: }
0237: values
0238: .add(part
0239: .getValue());
0240: } else {
0241: m_citationProperties
0242: .put(
0243: type,
0244: part
0245: .getValue());
0246: }
0247: } else if (type
0248: .equals("type")) {
0249: if (m_schema == null
0250: || m_schema
0251: .getIdentifier()
0252: .equals(
0253: "unknown")) {
0254: if (getSynonyms(
0255: "article")
0256: .contains(
0257: part
0258: .getValue()
0259: .toString()
0260: .toLowerCase())) {
0261: m_schema = BaseCitationService.this
0262: .getSchema("article");
0263: unknownSchema = false;
0264: } else if (getSynonyms(
0265: "book")
0266: .contains(
0267: part
0268: .getValue()
0269: .toString()
0270: .toLowerCase())) {
0271: m_schema = BaseCitationService.this
0272: .getSchema("book");
0273: unknownSchema = false;
0274: } else if (getSynonyms(
0275: "chapter")
0276: .contains(
0277: part
0278: .getValue()
0279: .toString()
0280: .toLowerCase())) {
0281: m_schema = BaseCitationService.this
0282: .getSchema("chapter");
0283: unknownSchema = false;
0284: } else if (getSynonyms(
0285: "report")
0286: .contains(
0287: part
0288: .getValue()
0289: .toString()
0290: .toLowerCase())) {
0291: m_schema = BaseCitationService.this
0292: .getSchema("report");
0293: unknownSchema = false;
0294: } else {
0295: m_schema = BaseCitationService.this
0296: .getSchema("unknown");
0297: unknownSchema = true;
0298: }
0299: }
0300: List values = (List) m_citationProperties
0301: .get(type);
0302: if (values == null) {
0303: values = new Vector();
0304: m_citationProperties
0305: .put(type,
0306: values);
0307: }
0308: values.add(part
0309: .getValue());
0310: } else {
0311:
0312: }
0313:
0314: } catch (RepositoryException e) {
0315: M_log.warn("BasicCitation("
0316: + asset + ") ", e);
0317: }
0318: }
0319: } catch (RepositoryException e) {
0320: M_log.warn("BasicCitation(" + asset
0321: + ") ", e);
0322: }
0323: } catch (RepositoryException e1) {
0324: M_log.warn("BasicCitation(" + asset
0325: + ") ", e1);
0326: }
0327: } catch (RepositoryException e2) {
0328: M_log.warn("BasicCitation(" + asset + ") ",
0329: e2);
0330: }
0331: }
0332: } catch (RepositoryException e) {
0333: M_log.warn("BasicCitation(" + asset + ") ", e);
0334: }
0335: } catch (RepositoryException e) {
0336: M_log.warn("BasicCitation(" + asset + ") ", e);
0337: }
0338:
0339: if (unknownSchema && attemptToMatchSchema) {
0340: matchSchema();
0341: }
0342:
0343: setDefaults();
0344: }
0345:
0346: /**
0347: *
0348: */
0349: protected void matchSchema() {
0350: Map pros = new Hashtable();
0351: Map cons = new Hashtable();
0352: List schemas = getSchemas();
0353: Set fieldNames = this .m_citationProperties.keySet();
0354: Iterator schemaIt = schemas.iterator();
0355: while (schemaIt.hasNext()) {
0356: Schema schema = (Schema) schemaIt.next();
0357: if (schema.getIdentifier().equals("unknown")) {
0358: continue;
0359: }
0360:
0361: pros.put(schema.getIdentifier(), new Counter());
0362: cons.put(schema.getIdentifier(), new Counter());
0363:
0364: Iterator fieldIt = fieldNames.iterator();
0365: while (fieldIt.hasNext()) {
0366: String fieldName = (String) fieldIt.next();
0367: Field field = schema.getField(fieldName);
0368: if (field == null) {
0369: // this indicates that data would be lost.
0370: ((Counter) cons.get(schema.getIdentifier()))
0371: .increment();
0372: } else {
0373: // this is evidence that this schema might be best fit.
0374: ((Counter) pros.get(schema.getIdentifier()))
0375: .increment();
0376: }
0377: }
0378: }
0379:
0380: // elminate schema that lose data
0381: Iterator consIt = cons.keySet().iterator();
0382: while (consIt.hasNext()) {
0383: String schemaId = (String) consIt.next();
0384: boolean blocked = ((Counter) cons.get(schemaId))
0385: .intValue() > 0;
0386: if (blocked) {
0387: pros.remove(schemaId);
0388: }
0389: }
0390: Iterator prosIt = pros.keySet().iterator();
0391: int bestScore = 0;
0392: String bestMatch = null;
0393: // Nominate "article" as first candidate if it's not blocked
0394: Object article = pros.get("article");
0395: if (article != null) {
0396: bestScore = ((Counter) article).intValue();
0397: bestMatch = "article";
0398: }
0399: while (prosIt.hasNext()) {
0400: String schemaId = (String) prosIt.next();
0401: int score = ((Counter) pros.get(schemaId)).intValue();
0402: if (score > bestScore) {
0403: bestScore = score;
0404: bestMatch = schemaId;
0405: }
0406: }
0407: if (bestMatch != null) {
0408: m_schema = BaseCitationService.this
0409: .getSchema(bestMatch);
0410: }
0411: }
0412:
0413: /**
0414: * @param other
0415: */
0416: public BasicCitation(BasicCitation other) {
0417: m_id = other.m_id;
0418: m_serialNumber = other.m_serialNumber;
0419: m_temporary = other.m_temporary;
0420: m_citationProperties = new Hashtable();
0421: m_urls = new Hashtable();
0422: setSchema(other.m_schema);
0423:
0424: copy(other);
0425: }
0426:
0427: /**
0428: * Construct a citation not marked as temporary of a particular type.
0429: *
0430: * @param mediatype
0431: */
0432: public BasicCitation(String mediatype) {
0433: m_id = IdManager.createUuid();
0434: m_citationProperties = new Hashtable();
0435: m_urls = new Hashtable();
0436: setType(mediatype);
0437: }
0438:
0439: public BasicCitation(String citationId, Schema schema) {
0440: m_id = citationId;
0441: m_citationProperties = new Hashtable();
0442: m_urls = new Hashtable();
0443: setSchema(schema);
0444: }
0445:
0446: /**
0447: * Construct a citation not marked as temporary of a particular type
0448: * with a particular id.
0449: *
0450: * @param citationId
0451: * @param mediatype
0452: */
0453: public BasicCitation(String citationId, String mediatype) {
0454: m_id = citationId;
0455: m_citationProperties = new Hashtable();
0456: m_urls = new Hashtable();
0457: setType(mediatype);
0458: }
0459:
0460: /*
0461: * (non-Javadoc)
0462: *
0463: * @see org.sakaiproject.citation.api.Citation#addUrl(java.lang.String,
0464: * java.net.URL)
0465: */
0466: public void addCustomUrl(String label, String url) {
0467: UrlWrapper wrapper = new UrlWrapper(label, url);
0468: String id = IdManager.createUuid();
0469: m_urls.put(id, wrapper);
0470: }
0471:
0472: /*
0473: * (non-Javadoc)
0474: *
0475: * @see org.sakaiproject.citation.api.Citation#addPropertyValue(java.lang.String,
0476: * java.lang.Object)
0477: */
0478: public void addPropertyValue(String name, Object value) {
0479: if (this .m_citationProperties == null) {
0480: this .m_citationProperties = new Hashtable();
0481: }
0482: if (isMultivalued(name)) {
0483: List list = (List) this .m_citationProperties.get(name);
0484: if (list == null) {
0485: list = new Vector();
0486: this .m_citationProperties.put(name, list);
0487: }
0488: list.add(value);
0489: } else {
0490: this .m_citationProperties.put(name, value);
0491: }
0492: }
0493:
0494: /**
0495: *
0496: * @param citation
0497: */
0498: public void copy(Citation citation) {
0499: BasicCitation other = (BasicCitation) citation;
0500:
0501: m_citationUrl = other.m_citationUrl;
0502: m_displayName = other.m_displayName;
0503: m_fullTextUrl = other.m_fullTextUrl;
0504: m_imageUrl = other.m_imageUrl;
0505: m_searchSourceUrl = other.m_searchSourceUrl;
0506:
0507: if (m_citationProperties == null) {
0508: m_citationProperties = new Hashtable();
0509: }
0510: m_citationProperties.clear();
0511:
0512: if (other.m_citationProperties != null) {
0513: Iterator propIt = other.m_citationProperties.keySet()
0514: .iterator();
0515: while (propIt.hasNext()) {
0516: String name = (String) propIt.next();
0517: Object obj = other.m_citationProperties.get(name);
0518: if (obj == null) {
0519:
0520: } else if (obj instanceof List) {
0521: List list = (List) obj;
0522: List copy = new Vector();
0523: Iterator valueIt = list.iterator();
0524: while (valueIt.hasNext()) {
0525: Object val = valueIt.next();
0526: copy.add(val);
0527: }
0528: this .m_citationProperties.put(name, copy);
0529: } else if (obj instanceof String) {
0530: this .m_citationProperties.put(name, obj);
0531: } else {
0532: M_log
0533: .debug("BasicCitation copy constructor: property is not String or List: "
0534: + name
0535: + " ("
0536: + obj.getClass().getName()
0537: + ") == " + obj);
0538: this .m_citationProperties.put(name, obj);
0539: }
0540: }
0541: }
0542:
0543: if (m_urls == null) {
0544: m_urls = new Hashtable();
0545: }
0546: m_urls.clear();
0547:
0548: if (other.m_urls != null) {
0549: Iterator urlIt = other.m_urls.keySet().iterator();
0550: while (urlIt.hasNext()) {
0551: String id = (String) urlIt.next();
0552: UrlWrapper wrapper = (UrlWrapper) other.m_urls
0553: .get(id);
0554: addCustomUrl(wrapper.getLabel(), wrapper.getUrl());
0555: }
0556: }
0557:
0558: }
0559:
0560: /*
0561: * Simple helpers to export RIS items
0562: * prefix will most often be empty, and is used to offer an "internal label"
0563: * for stuff that gets shoved into the Notes (N1) field because there isn't
0564: * a dedicated field (e.g., Rights)
0565: *
0566: * Outputs XX - value
0567: * or
0568: * XX - prefix: value
0569: */
0570:
0571: public void exportRisField(String rislabel, String value,
0572: StringBuffer buffer, String prefix) {
0573: // Get rid of the newlines and spaces
0574: value = value.replaceAll("\n", " ");
0575: rislabel = rislabel.trim();
0576:
0577: // Adjust the prefix to have a colon-space afterwards, if there *is* a prefix
0578: if (prefix != null && !prefix.trim().equals("")) {
0579: prefix = prefix + ": ";
0580: }
0581:
0582: // Export it only if there's a value, or if it's an ER tag (which is by design empty)
0583: if (value != null && !value.trim().equals("")
0584: || rislabel.equals("ER")) {
0585: buffer.append(rislabel + RIS_DELIM + prefix + value
0586: + "\n");
0587: }
0588:
0589: }
0590:
0591: /*
0592: * Again, without the prefix
0593: */
0594:
0595: public void exportRisField(String rislabel, String value,
0596: StringBuffer buffer) {
0597: exportRisField(rislabel, value, buffer, "");
0598: }
0599:
0600: /*
0601: * If the value is a list, iterate over it and recursively call exportRISField
0602: *
0603: */
0604:
0605: public void exportRisField(String rislabel, List propvalues,
0606: StringBuffer buffer, String prefix) {
0607: Iterator propvaliter = propvalues.iterator();
0608: while (propvaliter.hasNext()) {
0609: exportRisField(rislabel, propvaliter.next(), buffer,
0610: prefix);
0611: }
0612: }
0613:
0614: /*
0615: * And again, to do the dispatch
0616: */
0617:
0618: public void exportRisField(String rislabel, Object val,
0619: StringBuffer buffer, String prefix) {
0620: if (val instanceof List) {
0621: exportRisField(rislabel, (List) val, buffer, prefix);
0622: } else {
0623: exportRisField(rislabel, (String) val.toString(),
0624: buffer, prefix);
0625: }
0626: }
0627:
0628: /*
0629: * And, finally, a dispatcher to deal with items without a prefix
0630: */
0631: public void exportRisField(String rislabel, Object val,
0632: StringBuffer buffer) {
0633: exportRisField(rislabel, val, buffer, "");
0634: }
0635:
0636: /*
0637: *
0638: * (non-Javadoc)
0639: *
0640: * @see org.sakaiproject.citation.api.Citation#exportToRis(java.io.OutputStream)
0641: */
0642: public void exportRis(StringBuffer buffer) throws IOException {
0643: // Get the RISType and write a blank line and the TY tag
0644: String type = "article";
0645: if (m_schema != null) {
0646: type = m_schema.getIdentifier();
0647: }
0648:
0649: String ristype = (String) m_RISType.get(type);
0650: if (ristype == null) {
0651: ristype = (String) m_RISType.get("article");
0652: }
0653: exportRisField("TY", ristype, buffer);
0654:
0655: // Cycle through all the properties except for those that need
0656: // pre-processing (as listed in m_RISSpecialFields)
0657:
0658: // Deal with the "normal" fields
0659:
0660: List fields = m_schema.getFields();
0661: Iterator iter = fields.iterator();
0662: while (iter.hasNext()) {
0663: Field field = (Field) iter.next();
0664: String fieldname = field.getIdentifier();
0665: if (m_RISSpecialFields.contains(fieldname)) {
0666: continue; // Skip if this is a special field
0667: }
0668: String rislabel = field.getIdentifier(RIS_FORMAT);
0669: if (rislabel != null) {
0670: exportRisField(rislabel,
0671: getCitationProperty(fieldname), buffer);
0672: }
0673: }
0674:
0675: // Deal with the speical fields.
0676:
0677: /**
0678: * Dates need to be of the formt YYYY/MM/DD/other, including the
0679: * slashes even if the data is empty. Hence, we'll mostly be
0680: * producing YYYY// for date formats
0681: */
0682:
0683: // TODO: deal with real dates. Right now, just year
0684: exportRisField("Y1", getCitationProperty(Schema.YEAR)
0685: + "//", buffer);
0686:
0687: // Other stuff goes into the note field -- including the note
0688: // itself of course.
0689:
0690: Iterator specIter = m_RISNoteFields.entrySet().iterator();
0691: while (specIter.hasNext()) {
0692: Map.Entry entry = (Map.Entry) specIter.next();
0693: String fieldname = (String) entry.getKey();
0694: String prefix = (String) entry.getValue();
0695: exportRisField("N1", getCitationProperty(fieldname),
0696: buffer, prefix);
0697: }
0698:
0699: /**
0700: * Deal with URLs.
0701: */
0702:
0703: Iterator urlIDs = this .getCustomUrlIds().iterator();
0704: while (urlIDs.hasNext()) {
0705: String id = urlIDs.next().toString();
0706: try {
0707: String url = this .getCustomUrl(id);
0708: String urlLabel = this .getCustomUrlLabel(id);
0709: exportRisField("UR", url, buffer); // URL
0710: exportRisField("NT", url, buffer, urlLabel); // Note
0711:
0712: } catch (IdUnusedException e) {
0713: // do nothing
0714: }
0715: }
0716:
0717: // Write out the end-of-record identifier and an extra newline
0718: exportRisField("ER", "", buffer);
0719: buffer.append("\n");
0720: }
0721:
0722: /* (non-Javadoc)
0723: * @see org.sakaiproject.citation.api.Citation#getCitationProperties()
0724: */
0725: public Map getCitationProperties() {
0726: if (m_citationProperties == null) {
0727: m_citationProperties = new Hashtable();
0728: }
0729:
0730: return m_citationProperties;
0731:
0732: }
0733:
0734: /* (non-Javadoc)
0735: * @see org.sakaiproject.citation.api.Citation#getCitationProperty(java.lang.String)
0736: */
0737: public Object getCitationProperty(String name) {
0738: if (m_citationProperties == null) {
0739: m_citationProperties = new Hashtable();
0740: }
0741: Object value = m_citationProperties.get(name);
0742: if (value == null) {
0743: if (isMultivalued(name)) {
0744: value = new Vector();
0745: ((List) value).add("");
0746: } else {
0747: value = "";
0748: }
0749: }
0750:
0751: return value;
0752:
0753: }
0754:
0755: /*
0756: * (non-Javadoc)
0757: *
0758: * @see org.sakaiproject.citation.api.Citation#getAuthor()
0759: */
0760: public String getCreator() {
0761: List creatorList = null;
0762:
0763: Object creatorObj = m_citationProperties
0764: .get(Schema.CREATOR);
0765:
0766: if (creatorObj == null) {
0767: creatorList = new Vector();
0768: m_citationProperties.put(Schema.CREATOR, creatorList);
0769: } else if (creatorObj instanceof List) {
0770: creatorList = (List) creatorObj;
0771: } else if (creatorObj instanceof String) {
0772: creatorList = new Vector();
0773: creatorList.add(creatorObj);
0774: m_citationProperties.put(Schema.CREATOR, creatorList);
0775: }
0776:
0777: String creators = "";
0778: int count = 0;
0779: Iterator it = creatorList.iterator();
0780: while (it.hasNext()) {
0781: String creator = (String) it.next();
0782: if (it.hasNext() && count > 0) {
0783: creators += "; " + creator;
0784: } else if (it.hasNext()) {
0785: creators += creator;
0786: } else if (count > 1) {
0787: creators += "; and " + creator;
0788: } else if (count > 0) {
0789: creators += " and " + creator;
0790: } else {
0791: creators += creator;
0792: }
0793: count++;
0794: }
0795: if (!creators.trim().equals("")
0796: && !creators.trim().endsWith(".")) {
0797: creators = creators.trim() + ". ";
0798: }
0799: return creators;
0800: }
0801:
0802: /*
0803: * (non-Javadoc)
0804: *
0805: * @see org.sakaiproject.citation.api.Citation#getUrl(java.lang.String)
0806: */
0807: public String getCustomUrl(String id) throws IdUnusedException {
0808: UrlWrapper wrapper = (UrlWrapper) m_urls.get(id);
0809: if (wrapper == null) {
0810: throw new IdUnusedException(id);
0811: }
0812:
0813: return wrapper.getUrl();
0814: }
0815:
0816: /*
0817: * (non-Javadoc)
0818: *
0819: * @see org.sakaiproject.citation.api.Citation#getUrlIds()
0820: */
0821: public List getCustomUrlIds() {
0822: List rv = new Vector();
0823: if (!m_urls.isEmpty()) {
0824: rv.addAll(m_urls.keySet());
0825: }
0826: return rv;
0827: }
0828:
0829: /*
0830: * (non-Javadoc)
0831: *
0832: * @see org.sakaiproject.citation.api.Citation#getUrlLabel(java.lang.String)
0833: */
0834: public String getCustomUrlLabel(String id)
0835: throws IdUnusedException {
0836: UrlWrapper wrapper = (UrlWrapper) m_urls.get(id);
0837: if (wrapper == null) {
0838: throw new IdUnusedException(id);
0839: }
0840:
0841: return wrapper.getLabel();
0842: }
0843:
0844: public String getDisplayName() {
0845: String displayName = m_displayName;
0846: if (displayName == null || displayName.trim() == "") {
0847: displayName = (String) getCitationProperty(Schema.TITLE);
0848: }
0849: if (displayName == null) {
0850: displayName = "";
0851: }
0852: displayName = displayName.trim();
0853: if (displayName.length() > 0 && !displayName.endsWith(".")
0854: && !displayName.endsWith("?")
0855: && !displayName.endsWith("!")
0856: && !displayName.endsWith(",")) {
0857: displayName += ".";
0858: }
0859: return new String(displayName);
0860:
0861: }
0862:
0863: /*
0864: * (non-Javadoc)
0865: *
0866: * @see org.sakaiproject.citation.api.Citation#getFirstAuthor()
0867: */
0868: public String getFirstAuthor() {
0869: String firstAuthor = null;
0870: List authors = (List) this .m_citationProperties
0871: .get(Schema.CREATOR);
0872: if (authors != null && !authors.isEmpty()) {
0873: firstAuthor = (String) authors.get(0);
0874: }
0875: if (firstAuthor != null) {
0876: firstAuthor = firstAuthor.trim();
0877: }
0878: return firstAuthor;
0879: }
0880:
0881: public String getId() {
0882: if (isTemporary()) {
0883: return m_serialNumber.toString();
0884: }
0885: return m_id;
0886: }
0887:
0888: /*
0889: * (non-Javadoc)
0890: *
0891: * @see org.sakaiproject.citation.api.Citation#getOpenurl()
0892: */
0893: public String getOpenurl() {
0894: // check citationProperties
0895: if (m_citationProperties == null) {
0896: // citation properties do not exist as yet - no OpenUrl
0897: return null;
0898: }
0899:
0900: String openUrlParams = getOpenurlParameters();
0901:
0902: // return the URL-encoded string
0903: return m_configService
0904: .getSiteConfigOpenUrlResolverAddress()
0905: + openUrlParams;
0906: }
0907:
0908: /*
0909: * (non-Javadoc)
0910: *
0911: * @see org.sakaiproject.citation.api.Citation#getOpenurlParameters()
0912: */
0913: public String getOpenurlParameters() {
0914: // check citationProperties
0915: if (m_citationProperties == null) {
0916: // citation properties do not exist as yet - no OpenUrl
0917: return "";
0918: }
0919:
0920: // default to journal type
0921: boolean journalOpenUrlType = true;
0922: String referentValueFormat = OPENURL_JOURNAL_FORMAT;
0923: // check to see whether we should construct a journal OpenUrl
0924: // (includes types: article, report, unknown)
0925: // or a book OpenUrl (includes types: book, chapter)
0926: // String type = (String) m_citationProperties.get("type");
0927: String type = "article";
0928: if (m_schema != null) {
0929: type = m_schema.getIdentifier();
0930: }
0931: if (type != null && !type.trim().equals("")) {
0932: if (type.equals("article") || type.equals("report")
0933: || type.equals("unknown")) {
0934: journalOpenUrlType = true;
0935: referentValueFormat = OPENURL_JOURNAL_FORMAT;
0936: } else {
0937: journalOpenUrlType = false;
0938: referentValueFormat = OPENURL_BOOK_FORMAT;
0939: }
0940: }
0941:
0942: // start building the OpenUrl
0943: StringBuffer openUrl = null;
0944: try {
0945: openUrl = new StringBuffer();
0946:
0947: openUrl.append("?url_ver="
0948: + URLEncoder.encode(OPENURL_VERSION, "utf8")
0949: + "&url_ctx_fmt="
0950: + URLEncoder.encode(OPENURL_CONTEXT_FORMAT,
0951: "utf8")
0952: + "&rft_val_fmt="
0953: + URLEncoder
0954: .encode(referentValueFormat, "utf8"));
0955:
0956: // get first author
0957: String author = getFirstAuthor();
0958:
0959: // get first author's last/first name
0960: if (author != null) {
0961: String aulast;
0962: StringBuffer aufirst = new StringBuffer();
0963: String[] authorNames = author.split(",");
0964: if (authorNames.length == 2) {
0965: aulast = authorNames[0].trim();
0966: aufirst.append(authorNames[1].trim());
0967: } else {
0968: authorNames = author.split("\\s");
0969: aulast = authorNames[authorNames.length - 1]
0970: .trim();
0971: for (int i = 0; i < authorNames.length - 1; i++) {
0972: aufirst.append(authorNames[i] + " ");
0973: }
0974:
0975: if (aufirst.length() > 0) {
0976: aufirst.deleteCharAt(aufirst.length() - 1);
0977: }
0978: }
0979: // append to the openUrl
0980: openUrl.append("&rft.aulast="
0981: + URLEncoder.encode(aulast, "utf8"));
0982:
0983: if (!aufirst.toString().trim().equals("")) {
0984: openUrl.append("&rft.aufirst="
0985: + URLEncoder.encode(aufirst.toString()
0986: .trim(), "utf8"));
0987: }
0988: }
0989: // append any other authors to the openUrl
0990: java.util.List authors = (java.util.List) m_citationProperties
0991: .get(Schema.CREATOR);
0992: if (authors != null && !authors.isEmpty()
0993: && authors.size() > 1) {
0994: for (int i = 1; i < authors.size(); i++) {
0995: openUrl.append("&rft.au="
0996: + URLEncoder.encode((String) authors
0997: .get(i), "utf8"));
0998: }
0999: }
1000: // atitle <journal:article title; book: chapter title>
1001: if (m_displayName != null) {
1002: openUrl.append("&rft.atitle="
1003: + URLEncoder.encode(m_displayName, "utf8"));
1004: } else {
1005: // want to 'borrow' a title from another field if possible
1006: String sourceTitle = (String) m_citationProperties
1007: .get(Schema.SOURCE_TITLE);
1008: if (sourceTitle != null
1009: && !sourceTitle.trim().equals("")) {
1010: m_displayName = sourceTitle;
1011: openUrl.append("&rft.atitle="
1012: + URLEncoder.encode(m_displayName,
1013: "utf8"));
1014: }
1015: // could add other else ifs for fields to borrow from...
1016: }
1017:
1018: // journal title or book title
1019: String sourceTitle = (String) m_citationProperties
1020: .get(Schema.SOURCE_TITLE);
1021: if (sourceTitle != null
1022: && !sourceTitle.trim().equals("")) {
1023: if (journalOpenUrlType) {
1024: openUrl.append("&rft.jtitle="
1025: + URLEncoder
1026: .encode(sourceTitle, "utf8"));
1027: } else {
1028: openUrl.append("&rft.btitle="
1029: + URLEncoder
1030: .encode(sourceTitle, "utf8"));
1031: }
1032: }
1033:
1034: // date [ YYYY-MM-DD | YYYY-MM | YYYY ] - need filtering TODO
1035: // -- perhaps do another regular expressions scan...
1036: // currently just using the year
1037: String year = (String) m_citationProperties
1038: .get(Schema.YEAR);
1039:
1040: if (year != null && !year.trim().equals("")) {
1041: openUrl.append("&rft.date="
1042: + URLEncoder.encode(year, "utf8"));
1043: }
1044:
1045: // volume (edition)
1046: if (journalOpenUrlType) {
1047: String volume = (String) m_citationProperties
1048: .get(Schema.VOLUME);
1049: if (volume != null && !volume.trim().equals("")) {
1050: openUrl.append("&rft.volume="
1051: + URLEncoder.encode(volume, "utf8"));
1052: }
1053: } else {
1054: String edition = (String) m_citationProperties
1055: .get("edition");
1056: if (edition != null && !edition.trim().equals("")) {
1057: openUrl.append("&rft.edition="
1058: + URLEncoder.encode(edition, "utf8"));
1059: }
1060: }
1061:
1062: // issue (place)
1063: // (pub)
1064: if (journalOpenUrlType) {
1065: String issue = (String) m_citationProperties
1066: .get(Schema.ISSUE);
1067: if (issue != null && !issue.trim().equals("")) {
1068: openUrl.append("&rft.issue="
1069: + URLEncoder.encode(issue, "utf8"));
1070: }
1071:
1072: } else {
1073: String pub = (String) m_citationProperties
1074: .get("pub");
1075:
1076: if (pub != null && !pub.trim().equals("")) {
1077: openUrl.append("&rft.pub="
1078: + URLEncoder.encode(pub, "utf8"));
1079: }
1080: String place = (String) m_citationProperties
1081: .get("place");
1082: if (place != null && !place.trim().equals("")) {
1083: openUrl.append("&rft.place="
1084: + URLEncoder.encode(place, "utf8"));
1085: }
1086: }
1087:
1088: // spage
1089: String spage = (String) m_citationProperties
1090: .get("startPage");
1091: if (spage != null && !spage.trim().equals("")) {
1092: openUrl.append("&rft.spage="
1093: + URLEncoder.encode(spage, "utf8"));
1094: }
1095:
1096: // epage
1097: String epage = (String) m_citationProperties
1098: .get("endPage");
1099: if (epage != null && !epage.trim().equals("")) {
1100: openUrl.append("&rft.epage="
1101: + URLEncoder.encode(epage, "utf8"));
1102: }
1103:
1104: // pages
1105: String pages = (String) m_citationProperties
1106: .get(Schema.PAGES);
1107: if (pages != null && !pages.trim().equals("")) {
1108: openUrl.append("&rft.pages="
1109: + URLEncoder.encode(pages, "utf8"));
1110: }
1111:
1112: // issn (isbn)
1113: String isn = (String) m_citationProperties
1114: .get(Schema.ISN);
1115: if (isn != null && !isn.trim().equals("")) {
1116: if (journalOpenUrlType) {
1117: openUrl.append("&rft.issn="
1118: + URLEncoder.encode(isn, "utf8"));
1119: } else {
1120: openUrl.append("&rft.isbn="
1121: + URLEncoder.encode(isn, "utf8"));
1122: }
1123: }
1124: } catch (UnsupportedEncodingException uee) {
1125: M_log
1126: .warn("getOpenurlParameters -- unsupported encoding argument: utf8");
1127: }
1128:
1129: // genre needs some further work... TODO
1130:
1131: return openUrl.toString();
1132: }
1133:
1134: public Schema getSchema() {
1135: return m_schema;
1136: }
1137:
1138: /*
1139: * (non-Javadoc)
1140: *
1141: * @see org.sakaiproject.citation.api.Citation#getSource()
1142: */
1143: public String getSource() {
1144: String place = (String) getCitationProperty("publicationLocation");
1145: String publisher = (String) getCitationProperty(Schema.PUBLISHER);
1146: String sourceTitle = (String) getCitationProperty(Schema.SOURCE_TITLE);
1147: String year = (String) getCitationProperty(Schema.YEAR);
1148: String volume = (String) getCitationProperty(Schema.VOLUME);
1149: String issue = (String) getCitationProperty(Schema.ISSUE);
1150: String pages = (String) getCitationProperty(Schema.PAGES);
1151: String startPage = (String) getCitationProperty("startPage");
1152: String endPage = (String) getCitationProperty("endPage");
1153: if (pages == null || pages.trim().equals("")) {
1154: pages = null;
1155: if (startPage != null && !startPage.trim().equals("")) {
1156: pages = startPage.trim();
1157: if (endPage != null && !endPage.trim().equals("")) {
1158: pages += "-" + endPage;
1159: }
1160: }
1161: }
1162:
1163: String source = "";
1164: String schemaId = "unknown";
1165: if (m_schema != null) {
1166: schemaId = m_schema.getIdentifier();
1167: }
1168: if ("book".equals(schemaId) || "report".equals(schemaId)) {
1169: if (place != null && !place.trim().equals("")) {
1170: source += place;
1171: }
1172: if (publisher != null && !publisher.trim().equals("")) {
1173: if (source.length() > 0) {
1174: source = source.trim() + ": ";
1175: }
1176: source += publisher;
1177: }
1178: if (year != null && !year.trim().equals("")) {
1179: if (source.length() > 0) {
1180: source = source.trim() + ", ";
1181: }
1182: source += year;
1183: }
1184: } else if ("article".equals(schemaId)) {
1185:
1186: if (sourceTitle != null
1187: && !sourceTitle.trim().equals("")) {
1188: source += sourceTitle;
1189: if (volume != null && !volume.trim().equals("")) {
1190: source += ", " + volume;
1191: if (issue != null && !issue.trim().equals("")) {
1192: source += "(" + issue + ") ";
1193: }
1194: }
1195: }
1196: if (year != null && !year.trim().equals("")) {
1197: source += " " + year;
1198: }
1199: if (source != null && source.length() > 1) {
1200: source = source.trim();
1201: if (!source.endsWith(".") && !source.endsWith("?")
1202: && !source.endsWith("!")
1203: && !source.endsWith(",")) {
1204: source += ". ";
1205: }
1206: }
1207: if (pages != null && !pages.trim().equals("")) {
1208: source += pages;
1209: }
1210: if (source != null && source.length() > 1) {
1211: source = source.trim();
1212: if (!source.endsWith(".") && !source.endsWith("?")
1213: && !source.endsWith("!")
1214: && !source.endsWith(",")) {
1215: source += ". ";
1216: }
1217: }
1218: } else if ("chapter".equals(schemaId)) {
1219: if (sourceTitle != null
1220: && !sourceTitle.trim().equals("")) {
1221: source += "In " + sourceTitle;
1222: if (pages == null) {
1223: if (startPage != null
1224: && !startPage.trim().equals("")) {
1225: source = source.trim() + ", " + startPage;
1226: if (endPage != null
1227: && !endPage.trim().equals("")) {
1228: source = source.trim() + "-" + endPage;
1229: }
1230: }
1231: } else {
1232: source = source.trim() + ", " + pages;
1233: }
1234: if (publisher != null
1235: && !publisher.trim().equals("")) {
1236: if (place != null && !place.trim().equals("")) {
1237: source += place + ": ";
1238: }
1239: source += publisher;
1240: if (year != null && !year.trim().equals("")) {
1241: source += ", " + year;
1242: }
1243: } else if (year != null && !year.trim().equals("")) {
1244: source += " " + year;
1245: }
1246: }
1247: } else {
1248: if (sourceTitle != null
1249: && !sourceTitle.trim().equals("")) {
1250: source += sourceTitle;
1251: if (volume != null && !volume.trim().equals("")) {
1252: source += ", " + volume;
1253: if (issue != null && !issue.trim().equals("")) {
1254: source += "(" + issue + ") ";
1255: }
1256: }
1257: if (pages == null) {
1258: if (startPage != null
1259: && !startPage.trim().equals("")) {
1260: source += startPage;
1261: if (endPage != null
1262: && !endPage.trim().equals("")) {
1263: source += "-" + endPage;
1264: }
1265: }
1266: } else {
1267: if (source.length() > 0) {
1268: source += ". ";
1269: }
1270: source += pages + ". ";
1271: }
1272: } else if (publisher != null
1273: && !publisher.trim().equals("")) {
1274: if (place != null && !place.trim().equals("")) {
1275: source += place + ": ";
1276: }
1277: source += publisher;
1278: if (year != null && !year.trim().equals("")) {
1279: source += ", " + year;
1280: }
1281: }
1282: }
1283:
1284: if (source.length() > 1 && !source.endsWith(".")
1285: && !source.endsWith("?") && !source.endsWith("!")
1286: && !source.endsWith(",")) {
1287: source = source.trim() + ". ";
1288: }
1289:
1290: if (source.trim().endsWith("..")) {
1291: source = source.substring(0, source.length() - 2);
1292: }
1293:
1294: return source;
1295: }
1296:
1297: public String getAbstract() {
1298: if (m_citationProperties != null
1299: && m_citationProperties.get("abstract") != null) {
1300: return m_citationProperties.get("abstract").toString()
1301: .trim();
1302: } else {
1303: return null;
1304: }
1305: }
1306:
1307: public String getSubjectString() {
1308: Object subjects = getCitationProperty("subject");
1309:
1310: if (subjects instanceof List) {
1311: List subjectList = (List) subjects;
1312: ListIterator subjectListIterator = subjectList
1313: .listIterator();
1314:
1315: StringBuffer subjectStringBuf = new StringBuffer();
1316:
1317: while (subjectListIterator.hasNext()) {
1318: subjectStringBuf
1319: .append(((String) subjectListIterator
1320: .next()).trim()
1321: + ", ");
1322: }
1323:
1324: String subjectString = subjectStringBuf.substring(0,
1325: subjectStringBuf.length() - 2);
1326:
1327: if (subjectString.equals("")) {
1328: return null;
1329: } else {
1330: return subjectString;
1331: }
1332: } else {
1333: return null;
1334: }
1335: }
1336:
1337: /*
1338: * (non-Javadoc)
1339: *
1340: * @see org.sakaiproject.citation.api.Citation#hasUrls()
1341: */
1342: public boolean hasCustomUrls() {
1343: return m_urls != null && !m_urls.isEmpty();
1344: }
1345:
1346: public boolean hasPropertyValue(String fieldId) {
1347: boolean hasPropertyValue = m_citationProperties
1348: .containsKey(fieldId);
1349: Object val = m_citationProperties.get(fieldId);
1350: if (hasPropertyValue && val != null) {
1351: if (val instanceof List) {
1352: List list = (List) val;
1353: hasPropertyValue = !list.isEmpty();
1354: }
1355: }
1356:
1357: return hasPropertyValue;
1358: }
1359:
1360: /*
1361: * (non-Javadoc)
1362: *
1363: * @see org.sakaiproject.citation.api.Citation#importFromRis(java.io.InputStream)
1364: */
1365: public void importFromRis(InputStream istream)
1366: throws IOException {
1367: // TODO Auto-generated method stub
1368:
1369: }
1370:
1371: /*
1372: * (non-Javadoc)
1373: *
1374: * @see org.sakaiproject.citation.api.Citation#isAdded()
1375: */
1376: public boolean isAdded() {
1377: return this .m_isAdded;
1378: }
1379:
1380: /*
1381: * (non-Javadoc)
1382: *
1383: * @see org.sakaiproject.citation.api.Citation#isMultivalued(java.lang.String)
1384: */
1385: public boolean isMultivalued(String fieldId) {
1386: boolean isMultivalued = false;
1387: if (m_schema != null) {
1388: Field field = m_schema.getField(fieldId);
1389: if (field != null) {
1390: isMultivalued = field.isMultivalued();
1391: }
1392: }
1393: return isMultivalued;
1394: }
1395:
1396: /**
1397: * @return
1398: */
1399: public boolean isTemporary() {
1400: return m_temporary;
1401: }
1402:
1403: public List listCitationProperties() {
1404: if (m_citationProperties == null) {
1405: m_citationProperties = new Hashtable();
1406: }
1407:
1408: return new Vector(m_citationProperties.keySet());
1409:
1410: }
1411:
1412: /*
1413: * (non-Javadoc)
1414: *
1415: * @see org.sakaiproject.citation.api.Citation#setAdded()
1416: */
1417: public void setAdded(boolean added) {
1418: this .m_isAdded = added;
1419: }
1420:
1421: public void setCitationProperty(String name, Object value) {
1422: if (m_citationProperties == null) {
1423: m_citationProperties = new Hashtable();
1424: }
1425: if (isMultivalued(name)) {
1426: List list = (List) m_citationProperties.get(name);
1427: if (list == null) {
1428: list = new Vector();
1429: m_citationProperties.put(name, list);
1430: }
1431: if (value != null) {
1432: list.add(value);
1433: }
1434: } else {
1435: if (value == null) {
1436: m_citationProperties.remove(name);
1437: } else {
1438: m_citationProperties.put(name, value);
1439: }
1440: }
1441:
1442: }
1443:
1444: protected void setDefaults() {
1445: if (m_schema != null) {
1446: List fields = m_schema.getFields();
1447: Iterator it = fields.iterator();
1448: while (it.hasNext()) {
1449: Field field = (Field) it.next();
1450: if (field.isRequired()) {
1451: Object value = field.getDefaultValue();
1452: if (value == null) {
1453: // do nothing -- there's no value to set
1454: } else if (field.isMultivalued()) {
1455: List current_values = (List) this
1456: .getCitationProperty(field
1457: .getIdentifier());
1458: if (current_values.isEmpty()) {
1459: this .addPropertyValue(field
1460: .getIdentifier(), value);
1461: }
1462: } else if (this .getCitationProperty(field
1463: .getIdentifier()) == null) {
1464: setCitationProperty(field.getIdentifier(),
1465: value);
1466: }
1467: }
1468: }
1469: }
1470: }
1471:
1472: public void setDisplayName(String name) {
1473: String title = (String) this .m_citationProperties
1474: .get(Schema.TITLE);
1475: if (title == null || title.trim().equals("")) {
1476: setCitationProperty(Schema.TITLE, name);
1477: }
1478: m_displayName = name;
1479:
1480: }
1481:
1482: /*
1483: * (non-Javadoc)
1484: *
1485: * @see org.sakaiproject.citation.api.Citation#setSchema(org.sakaiproject.citation.api.Schema)
1486: */
1487: public void setSchema(Schema schema) {
1488: this .m_schema = schema;
1489: setDefaults();
1490:
1491: }
1492:
1493: protected void setType(String mediatype) {
1494: Schema schema = m_storage.getSchema(mediatype);
1495: if (schema == null) {
1496: schema = m_storage
1497: .getSchema(CitationService.UNKNOWN_TYPE);
1498: }
1499: setSchema(schema);
1500:
1501: }
1502:
1503: public String toString() {
1504: return "BasicCitation: " + this .m_id;
1505: }
1506:
1507: public void updateCitationProperty(String name, List values) {
1508: // what if "name" is not a valid field in the schema??
1509: if (m_citationProperties == null) {
1510: m_citationProperties = new Hashtable();
1511: }
1512: if (isMultivalued(name)) {
1513: List list = (List) m_citationProperties.get(name);
1514: if (list == null) {
1515: list = new Vector();
1516: m_citationProperties.put(name, list);
1517: }
1518: list.clear();
1519: if (values != null) {
1520: list.addAll(values);
1521: }
1522: } else {
1523: if (values == null || values.isEmpty()) {
1524: m_citationProperties.remove(name);
1525: } else {
1526: m_citationProperties.put(name, values.get(0));
1527: }
1528: }
1529:
1530: }
1531:
1532: /*
1533: * (non-Javadoc)
1534: *
1535: * @see org.sakaiproject.citation.api.Citation#updateUrl(java.lang.String,
1536: * java.lang.String, java.net.URL)
1537: */
1538: public void updateCustomUrl(String urlid, String label,
1539: String url) {
1540: UrlWrapper wrapper = new UrlWrapper(label, url);
1541: m_urls.put(urlid, wrapper);
1542: }
1543:
1544: /* (non-Javadoc)
1545: * @see org.sakaiproject.citation.api.Citation#getSaveUrl()
1546: */
1547: public String getSaveUrl(String collectionId) {
1548: SessionManager sessionManager = (SessionManager) ComponentManager
1549: .get("org.sakaiproject.tool.api.SessionManager");
1550: String sessionId = sessionManager.getCurrentSession()
1551: .getId();
1552:
1553: String url = m_serverConfigurationService.getServerUrl()
1554: + "/savecite/" + collectionId + "?sakai.session="
1555: + sessionId;
1556:
1557: String genre = this .getSchema().getIdentifier();
1558: url += "&genre=" + genre;
1559:
1560: String openUrlParams = this .getOpenurlParameters();
1561: String[] params = openUrlParams.split("&");
1562: for (int i = 0; i < params.length; i++) {
1563: String[] parts = params[i].split("=");
1564: String key = GS_TAGS.get(parts[0]);
1565: if (key != null) {
1566: url += "&" + key + "=" + parts[1];
1567: }
1568: }
1569:
1570: return url;
1571: }
1572:
1573: } // BaseCitationService.BasicCitation
1574:
1575: /**
1576: *
1577: */
1578: public class BasicCitationCollection implements CitationCollection {
1579: protected final Comparator DEFAULT_COMPARATOR = new BasicCitationCollection.TitleComparator(
1580: true);
1581:
1582: public class MultipleKeyComparator implements Comparator {
1583: protected List<String> m_keys = new Vector<String>();
1584:
1585: protected boolean m_ascending = true;
1586:
1587: public MultipleKeyComparator(List<String> keys,
1588: boolean ascending) {
1589: m_keys.addAll(keys);
1590:
1591: }
1592:
1593: public MultipleKeyComparator(MultipleKeyComparator mkc) {
1594: this .m_keys = mkc.m_keys;
1595: this .m_ascending = mkc.m_ascending;
1596: }
1597:
1598: /* (non-Javadoc)
1599: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
1600: */
1601: public int compare(Object arg0, Object arg1) {
1602: int rv = 0;
1603: if (!(arg0 instanceof String)
1604: || !(arg1 instanceof String)) {
1605: throw new ClassCastException();
1606: }
1607:
1608: Object obj0 = m_citations.get(arg0);
1609: Object obj1 = m_citations.get(arg1);
1610:
1611: if (!(obj0 instanceof Citation)
1612: || !(obj1 instanceof Citation)) {
1613: throw new ClassCastException();
1614: }
1615: Citation cit0 = (Citation) obj0;
1616: Citation cit1 = (Citation) obj1;
1617:
1618: Iterator keyIt = m_keys.iterator();
1619: while (rv == 0 && keyIt.hasNext()) {
1620: String key = (String) keyIt.next();
1621: if (CitationCollection.SORT_BY_TITLE
1622: .equalsIgnoreCase(key)) {
1623: String title0 = cit0.getDisplayName()
1624: .toLowerCase();
1625: String title1 = cit1.getDisplayName()
1626: .toLowerCase();
1627:
1628: if (title0 == null) {
1629: title0 = "";
1630: }
1631:
1632: if (title1 == null) {
1633: title1 = "";
1634: }
1635:
1636: rv = m_ascending ? title0.compareTo(title1)
1637: : title1.compareTo(title0);
1638: } else if (CitationCollection.SORT_BY_AUTHOR
1639: .equalsIgnoreCase(key)) {
1640: String author0 = cit0.getCreator()
1641: .toLowerCase();
1642: String author1 = cit1.getCreator()
1643: .toLowerCase();
1644:
1645: if (author0 == null) {
1646: author0 = "";
1647: }
1648:
1649: if (author1 == null) {
1650: author1 = "";
1651: }
1652: rv = m_ascending ? author0.compareTo(author1)
1653: : author1.compareTo(author0);
1654: } else if (CitationCollection.SORT_BY_UUID
1655: .equalsIgnoreCase(key)) {
1656: // not considering m_ascending for ids because they are random alpha-numeric strings
1657: rv = cit0.getId().compareTo(cit1.getId());
1658: }
1659: }
1660: return rv;
1661: }
1662:
1663: public void addKey(String key) {
1664: m_keys.add(key);
1665: }
1666: }
1667:
1668: public class AuthorComparator extends MultipleKeyComparator {
1669: /**
1670: * @param ascending
1671: */
1672: public AuthorComparator(boolean ascending) {
1673: super (AUTHOR_AS_KEY, ascending);
1674: }
1675:
1676: }
1677:
1678: public class BasicIterator implements CitationIterator {
1679: protected List listOfKeys;
1680:
1681: protected int nextItem;
1682:
1683: protected int lastItem;
1684:
1685: protected int startPage = 0;
1686:
1687: public BasicIterator() {
1688: this .listOfKeys = new Vector(m_order);
1689: setIndexes();
1690: }
1691:
1692: /*
1693: * (non-Javadoc)
1694: *
1695: * @see org.sakaiproject.citation.api.CitationIterator#getPage()
1696: */
1697: public int getPage() {
1698: return this .startPage;
1699: }
1700:
1701: /*
1702: * (non-Javadoc)
1703: *
1704: * @see org.sakaiproject.citation.api.CitationIterator#getPageSize()
1705: */
1706: public int getPageSize() {
1707: // TODO Auto-generated method stub
1708: return m_pageSize;
1709: }
1710:
1711: /*
1712: * (non-Javadoc)
1713: *
1714: * @see org.sakaiproject.citation.api.CitationIterator#hasNext()
1715: */
1716: public boolean hasNext() {
1717: boolean hasNext = false;
1718: if (m_ascending) {
1719: hasNext = this .nextItem < this .lastItem
1720: && this .nextItem < this .listOfKeys.size();
1721: } else {
1722: hasNext = this .nextItem > this .lastItem
1723: && this .nextItem > 0;
1724: }
1725: return hasNext;
1726: }
1727:
1728: /*
1729: * (non-Javadoc)
1730: *
1731: * @see org.sakaiproject.citation.api.CitationIterator#hasNextPage()
1732: */
1733: public boolean hasNextPage() {
1734: return m_pageSize * (startPage + 1) < this .listOfKeys
1735: .size();
1736: }
1737:
1738: /*
1739: * (non-Javadoc)
1740: *
1741: * @see org.sakaiproject.citation.api.CitationIterator#hasPreviousPage()
1742: */
1743: public boolean hasPreviousPage() {
1744: return this .startPage > 0;
1745: }
1746:
1747: /*
1748: * (non-Javadoc)
1749: *
1750: * @see org.sakaiproject.citation.api.CitationIterator#next()
1751: */
1752: public Object next() {
1753: Object item = null;
1754: if (m_ascending) {
1755: if (this .nextItem >= this .lastItem
1756: || this .nextItem >= listOfKeys.size()) {
1757: throw new NoSuchElementException();
1758: }
1759: item = m_citations.get(listOfKeys
1760: .get(this .nextItem++));
1761: } else {
1762: if (this .nextItem <= this .lastItem
1763: || this .nextItem <= 0) {
1764: throw new NoSuchElementException();
1765: }
1766: item = m_citations.get(listOfKeys
1767: .get(this .nextItem--));
1768: }
1769: return item;
1770: }
1771:
1772: /*
1773: * (non-Javadoc)
1774: *
1775: * @see org.sakaiproject.citation.api.CitationIterator#nextPage()
1776: */
1777: public void nextPage() {
1778: this .startPage++;
1779: setIndexes();
1780: }
1781:
1782: /*
1783: * (non-Javadoc)
1784: *
1785: * @see org.sakaiproject.citation.api.CitationIterator#previousPage()
1786: */
1787: public void previousPage() {
1788: this .startPage--;
1789: setIndexes();
1790: }
1791:
1792: /*
1793: * (non-Javadoc)
1794: *
1795: * @see java.util.Iterator#remove()
1796: */
1797: public void remove() {
1798: throw new UnsupportedOperationException();
1799:
1800: }
1801:
1802: protected void setIndexes() {
1803: if (m_ascending) {
1804: this .nextItem = Math.min(this .listOfKeys.size(),
1805: this .startPage * m_pageSize);
1806: this .lastItem = Math.min(this .listOfKeys.size(),
1807: this .nextItem + m_pageSize);
1808: } else {
1809: this .nextItem = Math.max(0, this .listOfKeys.size()
1810: - this .startPage * m_pageSize);
1811: this .lastItem = Math.max(0, this .nextItem
1812: - m_pageSize);
1813: }
1814: }
1815:
1816: /*
1817: * (non-Javadoc)
1818: *
1819: * @see org.sakaiproject.citation.api.CitationIterator#setSort(java.util.Comparator)
1820: */
1821: public void setOrder(Comparator comparator) {
1822: m_comparator = comparator;
1823: if (comparator == null) {
1824:
1825: } else {
1826: Collections.sort(this .listOfKeys, m_comparator);
1827: }
1828: this .startPage = 0;
1829: setIndexes();
1830: }
1831:
1832: /*
1833: * (non-Javadoc)
1834: *
1835: * @see org.sakaiproject.citation.api.CitationIterator#setPage(int)
1836: */
1837: public void setPage(int page) {
1838: this .startPage = page;
1839: setIndexes();
1840: }
1841:
1842: /*
1843: * (non-Javadoc)
1844: *
1845: * @see org.sakaiproject.citation.api.CitationIterator#setPageSize(int)
1846: */
1847: public void setPageSize(int size) {
1848: m_pageSize = size;
1849: this .startPage = 0;
1850: setIndexes();
1851: }
1852:
1853: }
1854:
1855: public class TitleComparator extends MultipleKeyComparator {
1856: /**
1857: * @param ascending
1858: */
1859: public TitleComparator(boolean ascending) {
1860: super (TITLE_AS_KEY, ascending);
1861: }
1862:
1863: }
1864:
1865: protected Map<String, Citation> m_citations = new Hashtable<String, Citation>();
1866:
1867: protected Comparator m_comparator = DEFAULT_COMPARATOR;
1868:
1869: protected SortedSet<String> m_order;
1870:
1871: protected int m_pageSize = DEFAULT_PAGE_SIZE;
1872:
1873: protected String m_description;
1874:
1875: protected String m_id;
1876:
1877: protected String m_title;
1878:
1879: protected boolean m_temporary = false;
1880:
1881: protected Integer m_serialNumber;
1882:
1883: protected ActiveSearch m_mySearch;
1884:
1885: protected boolean m_ascending = true;
1886:
1887: public BasicCitationCollection() {
1888: m_id = IdManager.createUuid();
1889: }
1890:
1891: /**
1892: * @param b
1893: */
1894: public BasicCitationCollection(boolean temporary) {
1895: m_order = new TreeSet<String>(m_comparator);
1896:
1897: m_temporary = temporary;
1898: if (temporary) {
1899: m_serialNumber = nextSerialNumber();
1900: } else {
1901: m_id = IdManager.createUuid();
1902: }
1903: }
1904:
1905: public BasicCitationCollection(Map attributes, List citations) {
1906: m_id = IdManager.createUuid();
1907:
1908: m_order = new TreeSet<String>(m_comparator);
1909:
1910: if (citations != null) {
1911: Iterator citationIt = citations.iterator();
1912: while (citationIt.hasNext()) {
1913: Citation citation = (Citation) citationIt.next();
1914: m_citations.put(citation.getId(), citation);
1915: m_order.add(citation.getId());
1916: }
1917: }
1918: }
1919:
1920: /**
1921: * @param collectionId
1922: */
1923: public BasicCitationCollection(String collectionId) {
1924: m_id = collectionId;
1925:
1926: m_order = new TreeSet(m_comparator);
1927: }
1928:
1929: public void add(Citation citation) {
1930: if (!this .m_citations.keySet().contains(citation.getId())) {
1931: this .m_citations.put(citation.getId(), citation);
1932: this .m_order.add(citation.getId());
1933: }
1934: }
1935:
1936: /*
1937: * (non-Javadoc)
1938: *
1939: * @see org.sakaiproject.citation.api.CitationCollection#addAll(org.sakaiproject.citation.api.CitationCollection)
1940: */
1941: public void addAll(CitationCollection other) {
1942: if (this .m_order == null) {
1943: this .m_order = new TreeSet<String>();
1944: }
1945: for (String key : ((BasicCitationCollection) other).m_order) {
1946: try {
1947: Citation citation = other.getCitation(key);
1948: this .add(citation);
1949: } catch (IdUnusedException e) {
1950: M_log
1951: .debug("BasicCitationCollection.addAll citationId ("
1952: + key
1953: + ") in m_order but not in m_citations; collectionId: "
1954: + other.getId());
1955: }
1956: }
1957: }
1958:
1959: /*
1960: * (non-Javadoc)
1961: *
1962: * @see org.sakaiproject.citation.api.CitationCollection#clear()
1963: */
1964: public void clear() {
1965: this .m_order.clear();
1966: this .m_citations.clear();
1967: }
1968:
1969: public boolean contains(Citation citation) {
1970: return this .m_citations.containsKey(citation.getId());
1971: }
1972:
1973: protected void copy(BasicCitationCollection other) {
1974: this .m_ascending = other.m_ascending;
1975: this .m_description = other.m_description;
1976: // this.m_comparator = other.m_comparator;
1977: this .m_serialNumber = other.m_serialNumber;
1978: this .m_pageSize = other.m_pageSize;
1979: this .m_temporary = other.m_temporary;
1980: this .m_title = other.m_title;
1981:
1982: /*
1983: * Get new instance of comparator
1984: */
1985: if (other.m_comparator instanceof MultipleKeyComparator) {
1986: this .m_comparator = new MultipleKeyComparator(
1987: (MultipleKeyComparator) other.m_comparator);
1988: } else {
1989: // default to title, ascending
1990: this .m_comparator = new MultipleKeyComparator(
1991: TITLE_AS_KEY, true);
1992: }
1993:
1994: if (this .m_citations == null) {
1995: this .m_citations = new Hashtable<String, Citation>();
1996: }
1997: this .m_citations.clear();
1998: if (this .m_order == null) {
1999: this .m_order = new TreeSet<String>(this .m_comparator);
2000: }
2001: this .m_order.clear();
2002: Iterator it = other.m_citations.keySet().iterator();
2003: while (it.hasNext()) {
2004: String citationId = (String) it.next();
2005: BasicCitation oldCitation = (BasicCitation) other.m_citations
2006: .get(citationId);
2007: BasicCitation newCitation = new BasicCitation();
2008: try {
2009: newCitation.copy(oldCitation);
2010: this .saveCitation(newCitation);
2011: this .add(newCitation);
2012: } catch (Exception e) {
2013: M_log.warn("copy(" + oldCitation.getId() + ") ==> "
2014: + newCitation.getId(), e);
2015: }
2016: }
2017:
2018: }
2019:
2020: public void exportRis(StringBuffer buffer,
2021: List<String> citationIds) throws IOException {
2022: // output "header" info to buffer
2023:
2024: // Iterate over citations and output to ostream
2025: for (String citationId : citationIds) {
2026: Citation citation = (Citation) this .m_citations
2027: .get(citationId);
2028: if (citation != null) {
2029: citation.exportRis(buffer);
2030: }
2031: }
2032: }
2033:
2034: /**
2035: * Compute an alternate root for a reference, based on the root
2036: * property.
2037: *
2038: * @param rootProperty
2039: * The property name.
2040: * @return The alternate root, or "" if there is none.
2041: */
2042: protected String getAlternateReferenceRoot(String rootProperty) {
2043: // null means don't do this
2044: if (rootProperty == null || rootProperty.trim().equals("")) {
2045: return "";
2046: }
2047:
2048: // make sure it start with a separator and does not end with one
2049: if (!rootProperty.startsWith(Entity.SEPARATOR)) {
2050: rootProperty = Entity.SEPARATOR + rootProperty;
2051: }
2052:
2053: if (rootProperty.endsWith(Entity.SEPARATOR)) {
2054: rootProperty = rootProperty.substring(0, rootProperty
2055: .length()
2056: - SEPARATOR.length());
2057: }
2058:
2059: return rootProperty;
2060: }
2061:
2062: public Citation getCitation(String citationId)
2063: throws IdUnusedException {
2064: Citation citation = (Citation) m_citations.get(citationId);
2065: if (citation == null) {
2066: throw new IdUnusedException(citationId);
2067: }
2068: return citation;
2069: }
2070:
2071: /*
2072: * (non-Javadoc)
2073: *
2074: * @see org.sakaiproject.citation.api.CitationCollection#getCitations()
2075: */
2076: public List getCitations() {
2077: List citations = new Vector();
2078: if (m_citations == null) {
2079: m_citations = new Hashtable<String, Citation>();
2080: }
2081: if (m_order == null) {
2082: m_order = new TreeSet<String>();
2083: }
2084:
2085: Iterator keyIt = this .m_order.iterator();
2086: while (keyIt.hasNext()) {
2087: String key = (String) keyIt.next();
2088:
2089: Object citation = this .m_citations.get(key);
2090: if (citation != null) {
2091: citations.add(citation);
2092: }
2093: }
2094:
2095: return citations;
2096: }
2097:
2098: public CitationCollection getCitations(Comparator c) {
2099: // TODO Auto-generated method stub
2100: return null;
2101: }
2102:
2103: public CitationCollection getCitations(Comparator c, Filter f) {
2104: // TODO Auto-generated method stub
2105: return null;
2106: }
2107:
2108: public CitationCollection getCitations(Filter f) {
2109: // TODO Auto-generated method stub
2110: return null;
2111: }
2112:
2113: public CitationCollection getCitations(Map properties) {
2114: // TODO Auto-generated method stub
2115: return null;
2116: }
2117:
2118: // public Citation remove(int index)
2119: // {
2120: // // TODO
2121: // return null;
2122: // }
2123: //
2124: // public Citation remove(Map properties)
2125: // {
2126: // // TODO Auto-generated method stub
2127: // return null;
2128: // }
2129:
2130: /*
2131: * (non-Javadoc)
2132: *
2133: * @see org.sakaiproject.citation.api.CitationCollection#getDescription()
2134: */
2135: public String getDescription() {
2136: return m_description;
2137: }
2138:
2139: public String getId() {
2140: return this .m_id;
2141: }
2142:
2143: public ResourceProperties getProperties() {
2144: // TODO Auto-generated method stub
2145: return null;
2146: }
2147:
2148: // public void sort(Comparator c)
2149: // {
2150: // // TODO Auto-generated method stub
2151: //
2152: // }
2153:
2154: public String getReference() {
2155:
2156: return getReference(null);
2157: }
2158:
2159: public String getReference(String rootProperty) {
2160:
2161: return m_relativeAccessPoint
2162: + getAlternateReferenceRoot(rootProperty)
2163: + Entity.SEPARATOR + getId();
2164: }
2165:
2166: /* (non-Javadoc)
2167: * @see org.sakaiproject.citation.api.CitationCollection#getSaveUrl()
2168: */
2169: public String getSaveUrl() {
2170: String url = m_serverConfigurationService.getServerUrl()
2171: + "/savecite/" + this .getId() + "/";
2172:
2173: return url;
2174: }
2175:
2176: /*
2177: * (non-Javadoc)
2178: *
2179: * @see org.sakaiproject.citation.api.CitationCollection#getTitle()
2180: */
2181: public String getTitle() {
2182: return m_title;
2183: }
2184:
2185: public String getUrl() {
2186: return getUrl(null);
2187: }
2188:
2189: public String getUrl(String rootProperty) {
2190: return getAccessPoint(false)
2191: + getAlternateReferenceRoot(rootProperty)
2192: + Entity.SEPARATOR + getId();
2193: }
2194:
2195: public boolean isEmpty() {
2196: return this .m_citations.isEmpty();
2197: }
2198:
2199: /*
2200: * (non-Javadoc)
2201: *
2202: * @see org.sakaiproject.citation.api.CitationCollection#iterator()
2203: */
2204: public CitationIterator iterator() {
2205: return new BasicIterator();
2206: }
2207:
2208: // public Iterator iterator()
2209: // {
2210: // // TODO Auto-generated method stub
2211: // return null;
2212: // }
2213: //
2214: //
2215: // public int lastIndexOf(Citation item)
2216: // {
2217: // // TODO Auto-generated method stub
2218: // return 0;
2219: // }
2220: //
2221: // public boolean move(int from, int to)
2222: // {
2223: // // TODO Auto-generated method stub
2224: // return false;
2225: // }
2226: //
2227: // public boolean moveToBack(int index)
2228: // {
2229: // // TODO Auto-generated method stub
2230: // return false;
2231: // }
2232: //
2233: // public boolean moveToFront(int index)
2234: // {
2235: // // TODO Auto-generated method stub
2236: // return false;
2237: // }
2238: //
2239: public boolean remove(Citation item) {
2240: boolean success = true;
2241: this .m_order.remove(item.getId());
2242: Object obj = this .m_citations.remove(item.getId());
2243: if (obj == null) {
2244: success = false;
2245: }
2246: return success;
2247: }
2248:
2249: /*
2250: * (non-Javadoc)
2251: *
2252: * @see org.sakaiproject.citation.api.CitationCollection#saveCitation(org.sakaiproject.citation.api.Citation)
2253: */
2254: public void saveCitation(Citation citation) {
2255: // m_storage.saveCitation(citation);
2256: save(citation);
2257: }
2258:
2259: /**
2260: *
2261: * @param comparator
2262: */
2263: public void setSort(Comparator comparator) {
2264: this .m_comparator = comparator;
2265: }
2266:
2267: /**
2268: *
2269: * @param sortBy
2270: * @param ascending
2271: */
2272: public void setSort(String sortBy, boolean ascending) {
2273: m_ascending = ascending;
2274:
2275: if (sortBy == null
2276: || sortBy.equalsIgnoreCase(SORT_BY_DEFAULT_ORDER)) {
2277: this .m_comparator = null;
2278: } else if (sortBy.equalsIgnoreCase(SORT_BY_AUTHOR)) {
2279: this .m_comparator = new AuthorComparator(ascending);
2280: } else if (sortBy.equalsIgnoreCase(SORT_BY_TITLE)) {
2281: this .m_comparator = new TitleComparator(ascending);
2282: }
2283:
2284: }
2285:
2286: public int size() {
2287: return m_order.size();
2288: }
2289:
2290: public String toString() {
2291: return "BasicCitationCollection: " + this .m_id;
2292: }
2293:
2294: public Element toXml(Document doc, Stack stack) {
2295: // TODO Auto-generated method stub
2296: return null;
2297: }
2298:
2299: } // BaseCitationService.BasicCitationCollection
2300:
2301: /**
2302: *
2303: */
2304: public class BasicField implements Field {
2305: protected Object defaultValue;
2306:
2307: protected String description;
2308:
2309: protected String identifier;
2310:
2311: protected String label;
2312:
2313: protected int maxCardinality;
2314:
2315: protected int minCardinality;
2316:
2317: protected String namespace;
2318:
2319: protected int order;
2320:
2321: protected boolean required;
2322:
2323: protected String valueType;
2324:
2325: protected Map identifiers;
2326:
2327: protected boolean isEditable;
2328:
2329: /**
2330: * @param field
2331: */
2332: public BasicField(Field other) {
2333: this .identifier = other.getIdentifier();
2334: this .valueType = other.getValueType();
2335: this .required = other.isRequired();
2336: this .minCardinality = other.getMinCardinality();
2337: this .maxCardinality = other.getMaxCardinality();
2338: this .namespace = other.getNamespaceAbbreviation();
2339: this .description = other.getDescription();
2340: this .identifiers = new Hashtable();
2341: this .isEditable = other.isEditable();
2342:
2343: if (other instanceof BasicField) {
2344: this .order = ((BasicField) other).getOrder();
2345: Iterator it = ((BasicField) other).identifiers.keySet()
2346: .iterator();
2347: while (it.hasNext()) {
2348: String format = (String) it.next();
2349: this .identifiers.put(format,
2350: ((BasicField) other).identifiers
2351: .get(format));
2352: }
2353: }
2354: }
2355:
2356: public BasicField(String identifier, String valueType,
2357: boolean isEditable, boolean required,
2358: int minCardinality, int maxCardinality) {
2359: this .identifier = identifier;
2360: this .valueType = valueType;
2361: this .required = required;
2362: this .minCardinality = minCardinality;
2363: this .maxCardinality = maxCardinality;
2364: this .namespace = "";
2365: this .label = "";
2366: this .description = "";
2367: this .order = 0;
2368: this .identifiers = new Hashtable();
2369: this .isEditable = true;
2370: }
2371:
2372: public Object getDefaultValue() {
2373: return defaultValue;
2374: }
2375:
2376: public String getDescription() {
2377: return this .description;
2378: }
2379:
2380: public String getIdentifier() {
2381: return identifier;
2382: }
2383:
2384: public String getIdentifier(String format) {
2385: return (String) this .identifiers.get(format);
2386: }
2387:
2388: public String getLabel() {
2389: return this .label;
2390: }
2391:
2392: public int getMaxCardinality() {
2393: return maxCardinality;
2394: }
2395:
2396: public int getMinCardinality() {
2397: return minCardinality;
2398: }
2399:
2400: public String getNamespaceAbbreviation() {
2401: return this .namespace;
2402: }
2403:
2404: /*
2405: * (non-Javadoc)
2406: *
2407: * @see org.sakaiproject.citation.api.Schema.Field#getOrder()
2408: */
2409: public int getOrder() {
2410: return order;
2411: }
2412:
2413: public String getValueType() {
2414: return valueType;
2415: }
2416:
2417: public boolean isEditable() {
2418: return isEditable;
2419: }
2420:
2421: /*
2422: * (non-Javadoc)
2423: *
2424: * @see org.sakaiproject.citation.api.Schema.Field#isMultivalued()
2425: */
2426: public boolean isMultivalued() {
2427: return this .maxCardinality > 1;
2428: }
2429:
2430: public boolean isRequired() {
2431: return required;
2432: }
2433:
2434: public void setDefaultValue(Object value) {
2435: this .defaultValue = value;
2436: }
2437:
2438: /**
2439: * @param label
2440: */
2441: public void setDescription(String description) {
2442: this .description = description;
2443: }
2444:
2445: public void setEditable(boolean isEditable) {
2446: this .isEditable = isEditable;
2447: }
2448:
2449: public void setIdentifier(String format, String identifier) {
2450: this .identifiers.put(format, identifier);
2451:
2452: }
2453:
2454: /**
2455: * @param label
2456: */
2457: public void setLabel(String label) {
2458: this .label = label;
2459: }
2460:
2461: /**
2462: * @param maxCardinality
2463: * The maxCardinality to set.
2464: */
2465: public void setMaxCardinality(int maxCardinality) {
2466: this .maxCardinality = maxCardinality;
2467: }
2468:
2469: /**
2470: * @param minCardinality
2471: * The minCardinality to set.
2472: */
2473: public void setMinCardinality(int minCardinality) {
2474: this .minCardinality = minCardinality;
2475: }
2476:
2477: public void setNamespaceAbbreviation(String namespace) {
2478: this .namespace = namespace;
2479: }
2480:
2481: /*
2482: * (non-Javadoc)
2483: *
2484: * @see org.sakaiproject.citation.api.Schema.Field#setOrder(int)
2485: */
2486: public void setOrder(int order) {
2487: this .order = order;
2488:
2489: }
2490:
2491: /**
2492: * @param required
2493: * The required to set.
2494: */
2495: public void setRequired(boolean required) {
2496: this .required = required;
2497: }
2498:
2499: /**
2500: * @param valueType
2501: * The valueType to set.
2502: */
2503: public void setValueType(String valueType) {
2504: this .valueType = valueType;
2505: }
2506:
2507: public String toString() {
2508: return "BasicField: " + this .identifier;
2509: }
2510:
2511: }
2512:
2513: /**
2514: *
2515: */
2516: protected class BasicSchema implements Schema {
2517: protected String defaultNamespace;
2518:
2519: protected List fields;
2520:
2521: protected String identifier;
2522:
2523: protected Map index;
2524:
2525: protected Map namespaces;
2526:
2527: protected Map identifiers;
2528:
2529: /**
2530: *
2531: */
2532: public BasicSchema() {
2533: this .fields = new Vector();
2534: this .index = new Hashtable();
2535: this .identifiers = new Hashtable();
2536: }
2537:
2538: /**
2539: * @param schema
2540: */
2541: public BasicSchema(Schema other) {
2542: this .identifier = other.getIdentifier();
2543: this .defaultNamespace = other.getNamespaceAbbrev();
2544: namespaces = new Hashtable();
2545: List nsAbbrevs = other.getNamespaceAbbreviations();
2546: if (nsAbbrevs != null) {
2547: Iterator nsIt = nsAbbrevs.iterator();
2548: while (nsIt.hasNext()) {
2549: String nsAbbrev = (String) nsIt.next();
2550: String ns = other.getNamespaceUri(nsAbbrev);
2551: namespaces.put(nsAbbrev, ns);
2552: }
2553: }
2554: this .identifiers = new Hashtable();
2555: if (other instanceof BasicSchema) {
2556: Iterator it = ((BasicSchema) other).identifiers
2557: .keySet().iterator();
2558: while (it.hasNext()) {
2559: String format = (String) it.next();
2560: this .identifiers.put(format,
2561: ((BasicSchema) other).identifiers
2562: .get(format));
2563: }
2564: }
2565:
2566: this .fields = new Vector();
2567: this .index = new Hashtable();
2568: List fields = other.getFields();
2569: Iterator fieldIt = fields.iterator();
2570: while (fieldIt.hasNext()) {
2571: Field field = (Field) fieldIt.next();
2572: this .fields.add(new BasicField(field));
2573: index.put(field.getIdentifier(), field);
2574: }
2575: }
2576:
2577: /**
2578: * @param schemaId
2579: */
2580: public BasicSchema(String schemaId) {
2581: this .identifier = schemaId;
2582: this .fields = new Vector();
2583: this .index = new Hashtable();
2584: this .identifiers = new Hashtable();
2585: }
2586:
2587: public void addAlternativeIdentifier(String fieldId,
2588: String altFormat, String altIdentifier) {
2589: BasicField field = (BasicField) this .index.get(fieldId);
2590: if (field != null) {
2591: field.setIdentifier(altFormat, altIdentifier);
2592: }
2593: }
2594:
2595: /*
2596: * (non-Javadoc)
2597: *
2598: * @see org.sakaiproject.citation.api.Schema#addField(org.sakaiproject.citation.api.Schema.Field)
2599: */
2600: public void addField(Field field) {
2601: this .index.put(field.getIdentifier(), field);
2602: this .fields.add(field);
2603:
2604: }
2605:
2606: /**
2607: * @param order
2608: * @param field
2609: */
2610: public void addField(int order, Field field) {
2611: fields.add(order, field);
2612: index.put(identifier, field);
2613: }
2614:
2615: public BasicField addField(String identifier, String valueType,
2616: boolean isEditable, boolean required,
2617: int minCardinality, int maxCardinality) {
2618: if (fields == null) {
2619: fields = new Vector();
2620: }
2621: if (index == null) {
2622: index = new Hashtable();
2623: }
2624: BasicField field = new BasicField(identifier, valueType,
2625: isEditable, required, minCardinality,
2626: maxCardinality);
2627: fields.add(field);
2628: index.put(identifier, field);
2629: return field;
2630: }
2631:
2632: public BasicField addOptionalField(String identifier,
2633: String valueType, int minCardinality, int maxCardinality) {
2634: return addField(identifier, valueType, true, false,
2635: minCardinality, maxCardinality);
2636: }
2637:
2638: public BasicField addRequiredField(String identifier,
2639: String valueType, int minCardinality, int maxCardinality) {
2640: return addField(identifier, valueType, true, true,
2641: minCardinality, maxCardinality);
2642: }
2643:
2644: public Field getField(int index) {
2645: if (fields == null) {
2646: fields = new Vector();
2647: }
2648: return (Field) fields.get(index);
2649: }
2650:
2651: public Field getField(String name) {
2652: if (index == null) {
2653: index = new Hashtable();
2654: }
2655: return (Field) index.get(name);
2656: }
2657:
2658: public List getFields() {
2659: if (fields == null) {
2660: fields = new Vector();
2661: }
2662: return fields;
2663: }
2664:
2665: /*
2666: * (non-Javadoc)
2667: *
2668: * @see org.sakaiproject.citation.api.Schema#getIdentifier()
2669: */
2670: public String getIdentifier() {
2671: return this .identifier;
2672: }
2673:
2674: public String getIdentifier(String format) {
2675: return (String) this .identifiers.get(format);
2676: }
2677:
2678: public String getNamespaceAbbrev() {
2679: return defaultNamespace;
2680: }
2681:
2682: public List getNamespaceAbbreviations() {
2683: if (namespaces == null) {
2684: namespaces = new Hashtable();
2685: }
2686: Collection keys = namespaces.keySet();
2687: List rv = new Vector();
2688: if (keys != null) {
2689: rv.addAll(keys);
2690: }
2691: return rv;
2692: }
2693:
2694: public String getNamespaceUri(String abbrev) {
2695: if (namespaces == null) {
2696: namespaces = new Hashtable();
2697: }
2698: return (String) namespaces.get(abbrev);
2699: }
2700:
2701: public List getRequiredFields() {
2702: if (fields == null) {
2703: fields = new Vector();
2704: }
2705: List required = new Vector();
2706: Iterator it = fields.iterator();
2707: while (it.hasNext()) {
2708: Field field = (Field) it.next();
2709: if (field.isRequired()) {
2710: required.add(field);
2711: }
2712: }
2713:
2714: return required;
2715: }
2716:
2717: /**
2718: * @param identifier
2719: */
2720: public void setIdentifier(String identifier) {
2721: this .identifier = identifier;
2722: }
2723:
2724: public void setIdentifier(String format, String identifier) {
2725: this .identifiers.put(format, identifier);
2726:
2727: }
2728:
2729: /**
2730: *
2731: */
2732: public void sortFields() {
2733: Collections.sort(fields, new Comparator() {
2734:
2735: public int compare(Object arg0, Object arg1) {
2736: if (arg0 instanceof BasicField
2737: && arg1 instanceof BasicField) {
2738: Integer int0 = new Integer(((BasicField) arg0)
2739: .getOrder());
2740: Integer int1 = new Integer(((BasicField) arg1)
2741: .getOrder());
2742: return int0.compareTo(int1);
2743: } else if (arg0 instanceof Field
2744: && arg1 instanceof Field) {
2745: String lbl0 = ((Field) arg0).getLabel();
2746: String lbl1 = ((Field) arg1).getLabel();
2747: return lbl0.compareTo(lbl1);
2748: } else {
2749: throw new ClassCastException(arg0.toString()
2750: + " " + arg1.toString());
2751: }
2752: }
2753:
2754: });
2755:
2756: }
2757:
2758: public String toString() {
2759: return "BasicSchema: " + this .identifier;
2760: }
2761:
2762: }
2763:
2764: /**
2765: *
2766: */
2767: protected interface Storage {
2768: /**
2769: * @param mediatype
2770: * @return
2771: */
2772: public Citation addCitation(String mediatype);
2773:
2774: public CitationCollection addCollection(Map attributes,
2775: List citations);
2776:
2777: public Schema addSchema(Schema schema);
2778:
2779: public boolean checkCitation(String citationId);
2780:
2781: public boolean checkCollection(String collectionId);
2782:
2783: public boolean checkSchema(String schemaId);
2784:
2785: /**
2786: * Close.
2787: */
2788: public void close();
2789:
2790: public CitationCollection copyAll(String collectionId);
2791:
2792: public Citation getCitation(String citationId);
2793:
2794: public CitationCollection getCollection(String collectionId);
2795:
2796: public Schema getSchema(String schemaId);
2797:
2798: public List getSchemas();
2799:
2800: /**
2801: * @return
2802: */
2803: public List listSchemas();
2804:
2805: /**
2806: * Open and be ready to read / write.
2807: */
2808: public void open();
2809:
2810: public void putSchemas(Collection schemas);
2811:
2812: public void removeCitation(Citation edit);
2813:
2814: public void removeCollection(CitationCollection edit);
2815:
2816: public void removeSchema(Schema schema);
2817:
2818: public void saveCitation(Citation edit);
2819:
2820: public void saveCollection(CitationCollection collection);
2821:
2822: public void updateSchema(Schema schema);
2823:
2824: public void updateSchemas(Collection schemas);
2825:
2826: } // interface Storage
2827:
2828: /**
2829: *
2830: */
2831: public class UrlWrapper {
2832: protected String m_label;
2833:
2834: protected String m_url;
2835:
2836: /**
2837: * @param label
2838: * @param url
2839: */
2840: public UrlWrapper(String label, String url) {
2841: m_label = label;
2842: m_url = url;
2843: }
2844:
2845: /**
2846: * @return the label
2847: */
2848: public String getLabel() {
2849: return m_label;
2850: }
2851:
2852: /**
2853: * @return the url
2854: */
2855: public String getUrl() {
2856: return m_url;
2857: }
2858:
2859: /**
2860: * @param label
2861: * the label to set
2862: */
2863: public void setLabel(String label) {
2864: m_label = label;
2865: }
2866:
2867: /**
2868: * @param url
2869: * the url to set
2870: */
2871: public void setUrl(String url) {
2872: m_url = url;
2873: }
2874: }
2875:
2876: public static ResourceLoader rb;
2877:
2878: /** Our logger. */
2879: private static Log M_log = LogFactory
2880: .getLog(BaseCitationService.class);
2881:
2882: protected static final String PROPERTY_DEFAULTVALUE = "sakai:defaultValue";
2883:
2884: protected static final String PROPERTY_DESCRIPTION = "sakai:description";
2885:
2886: protected static final String PROPERTY_HAS_ABBREVIATION = "sakai:hasAbbreviation";
2887:
2888: protected static final String PROPERTY_HAS_CITATION = "sakai:hasCitation";
2889:
2890: protected static final String PROPERTY_HAS_FIELD = "sakai:hasField";
2891:
2892: protected static final String PROPERTY_HAS_NAMESPACE = "sakai:hasNamespace";
2893:
2894: protected static final String PROPERTY_HAS_ORDER = "sakai:hasOrder";
2895:
2896: protected static final String PROPERTY_HAS_SCHEMA = "sakai:hasSchema";
2897:
2898: protected static final String PROPERTY_LABEL = "sakai:label";
2899:
2900: protected static final String PROPERTY_MAXCARDINALITY = "sakai:maxCardinality";
2901:
2902: protected static final String PROPERTY_MINCARDINALITY = "sakai:minCardinality";
2903:
2904: protected static final String PROPERTY_NAMESPACE = "sakai:namespace";
2905:
2906: protected static final String PROPERTY_REQUIRED = "sakai:required";
2907:
2908: protected static final String PROPERTY_VALUETYPE = "sakai:valueType";
2909:
2910: public static final String SCHEMA_PREFIX = "schema.";
2911:
2912: protected static Integer m_nextSerialNumber;
2913:
2914: /*
2915: * RIS MAPPINGS below
2916: */
2917:
2918: protected static final String RIS_DELIM = " - ";
2919:
2920: /**
2921: * Set up a mapping of our type to RIS 'TY - ' values
2922: */
2923: protected static final Map m_RISType = new Hashtable();
2924:
2925: /**
2926: * Which fields map onto the RIS Notes field? Include a prefix for the data,
2927: * if necessary.
2928: */
2929: protected static final Map m_RISNoteFields = new Hashtable();
2930:
2931: /**
2932: * Which fields need special processing for RIS export?
2933: */
2934: protected static final Set m_RISSpecialFields = new java.util.HashSet();
2935:
2936: static {
2937: m_RISType.put("unknown", "JOUR"); // Default to journal article
2938: m_RISType.put("article", "JOUR");
2939: m_RISType.put("book", "BOOK");
2940: m_RISType.put("chapter", "CHAP");
2941: m_RISType.put("report", "RPRT");
2942: }
2943:
2944: static {
2945: m_RISNoteFields.put("language", "Language: ");
2946: m_RISNoteFields.put("doi", "DOI: ");
2947: m_RISNoteFields.put("rights", "Rights: ");
2948: }
2949:
2950: static {
2951: m_RISSpecialFields.add("date");
2952: m_RISSpecialFields.add("doi");
2953: }
2954:
2955: public static String escapeFieldName(String original) {
2956: if (original == null) {
2957: return "";
2958: }
2959: original = original.trim();
2960: try {
2961: // convert the string to bytes in UTF-8
2962: byte[] bytes = original.getBytes("UTF-8");
2963:
2964: StringBuffer buf = new StringBuffer();
2965: for (int i = 0; i < bytes.length; i++) {
2966: byte b = bytes[i];
2967: // escape ascii control characters, ascii high bits, specials
2968: if (Schema.ESCAPE_FIELD_NAME.indexOf((char) b) != -1) {
2969: buf.append(Schema.ESCAPE_CHAR); // special funky way to
2970: // encode bad URL characters
2971: // - ParameterParser will
2972: // decode it
2973: } else {
2974: buf.append((char) b);
2975: }
2976: }
2977:
2978: String rv = buf.toString();
2979: return rv;
2980: } catch (Exception e) {
2981: M_log.warn("BaseCitationService.escapeFieldName: ", e);
2982: return original;
2983: }
2984:
2985: }
2986:
2987: /** Dependency: CitationsConfigurationService. */
2988: protected ConfigurationService m_configService = null;
2989:
2990: /** Dependency: ServerConfigurationService. */
2991: protected ServerConfigurationService m_serverConfigurationService = null;
2992:
2993: /** Dependency: ContentHostingService. */
2994: protected ContentHostingService m_contentHostingService = null;
2995:
2996: /** Dependency: EntityManager. */
2997: protected EntityManager m_entityManager = null;
2998:
2999: protected String m_defaultSchema;
3000:
3001: /** A Storage object for persistent storage. */
3002: protected Storage m_storage = null;
3003:
3004: protected String m_relativeAccessPoint;
3005:
3006: /**
3007: * Dependency: the ResourceTypeRegistry
3008: */
3009: protected ResourceTypeRegistry m_resourceTypeRegistry;
3010:
3011: /**
3012: * Dependency: inject the ResourceTypeRegistry
3013: * @param registry
3014: */
3015: public void setResourceTypeRegistry(ResourceTypeRegistry registry) {
3016: m_resourceTypeRegistry = registry;
3017: }
3018:
3019: /**
3020: * @return the ResourceTypeRegistry
3021: */
3022: public ResourceTypeRegistry getResourceTypeRegistry() {
3023: return m_resourceTypeRegistry;
3024: }
3025:
3026: public static final String PROP_TEMPORARY_CITATION_LIST = "citations.temporary_citation_list";
3027:
3028: /**
3029: * Checks permissions to add a CitationList. Returns true if the user
3030: * has permission to add a resource in the collection identified by the
3031: * parameter.
3032: * @param contentCollectionId
3033: * @return
3034: */
3035: public boolean allowAddCitationList(String contentCollectionId) {
3036: return m_contentHostingService
3037: .allowAddResource(contentCollectionId + "testing");
3038: }
3039:
3040: /**
3041: * Checks permission to revise a CitationList, including permissions
3042: * to add, remove or revise citations within the CitationList. Returns
3043: * true if the user has permission to revise the resource identified by
3044: * the parameter. Also returns true if all of these conditions are met:
3045: * (1) the user is the creator of the specified resource, (2) the specified
3046: * resource is a temporary CitationList (as identified by the value of
3047: * the PROP_TEMPORARY_CITATION_LIST property), and (3) the user has
3048: * permission to add resources in the collection containing the
3049: * resource.
3050: * @param contentResourceId
3051: * @return
3052: */
3053: public boolean allowReviseCitationList(String contentResourceId) {
3054: boolean allowed = m_contentHostingService
3055: .allowUpdateResource(contentResourceId);
3056: if (!allowed) {
3057: try {
3058: ResourceProperties props = m_contentHostingService
3059: .getProperties(contentResourceId);
3060: String temp_res = props
3061: .getProperty(CitationService.PROP_TEMPORARY_CITATION_LIST);
3062: String creator = props
3063: .getProperty(ResourceProperties.PROP_CREATOR);
3064: String contentCollectionId = m_contentHostingService
3065: .getContainingCollectionId(contentResourceId);
3066: SessionManager sessionManager = (SessionManager) ComponentManager
3067: .get("org.sakaiproject.tool.api.SessionManager");
3068: String currentUser = sessionManager
3069: .getCurrentSessionUserId();
3070:
3071: allowed = this
3072: .allowAddCitationList(contentCollectionId)
3073: && (temp_res != null)
3074: && currentUser.equals(creator);
3075: } catch (PermissionException e) {
3076: // do nothing: return false
3077: } catch (IdUnusedException e) {
3078: // do nothing: return false
3079: }
3080: }
3081: return allowed;
3082: }
3083:
3084: /**
3085: *
3086: * @return
3087: */
3088: public boolean allowRemoveCitationList(String contentResourceId) {
3089: boolean allowed = m_contentHostingService
3090: .allowUpdateResource(contentResourceId);
3091: if (!allowed) {
3092: try {
3093: ResourceProperties props = m_contentHostingService
3094: .getProperties(contentResourceId);
3095: String temp_res = props
3096: .getProperty(CitationService.PROP_TEMPORARY_CITATION_LIST);
3097: String creator = props
3098: .getProperty(ResourceProperties.PROP_CREATOR);
3099: String contentCollectionId = m_contentHostingService
3100: .getContainingCollectionId(contentResourceId);
3101: SessionManager sessionManager = (SessionManager) ComponentManager
3102: .get("org.sakaiproject.tool.api.SessionManager");
3103: String currentUser = sessionManager
3104: .getCurrentSessionUserId();
3105:
3106: allowed = this
3107: .allowAddCitationList(contentCollectionId)
3108: && (temp_res != null)
3109: && currentUser.equals(creator);
3110: } catch (PermissionException e) {
3111: // do nothing: return false
3112: } catch (IdUnusedException e) {
3113: // do nothing: return false
3114: }
3115: }
3116: return allowed;
3117: }
3118:
3119: public Citation addCitation(String mediatype) {
3120: Citation edit = m_storage.addCitation(mediatype);
3121:
3122: return edit;
3123: }
3124:
3125: /*
3126: * (non-Javadoc)
3127: *
3128: * @see org.sakaiproject.citation.api.CitationService#addCollection()
3129: */
3130: public CitationCollection addCollection() {
3131: CitationCollection edit = m_storage.addCollection(null, null);
3132: return edit;
3133: }
3134:
3135: /*
3136: * (non-Javadoc)
3137: *
3138: * @see org.sakaiproject.entity.api.EntityProducer#archive(java.lang.String,
3139: * org.w3c.dom.Document, java.util.Stack, java.lang.String,
3140: * java.util.List)
3141: */
3142: public String archive(String siteId, Document doc, Stack stack,
3143: String archivePath, List attachments) {
3144: // TODO Auto-generated method stub
3145: return null;
3146: }
3147:
3148: /*
3149: * (non-Javadoc)
3150: *
3151: * @see org.sakaiproject.citation.api.CitationService#copyAll(java.lang.String)
3152: */
3153: public CitationCollection copyAll(String collectionId) {
3154: return m_storage.copyAll(collectionId);
3155: }
3156:
3157: /**
3158: * Returns to uninitialized state.
3159: */
3160: public void destroy() {
3161: if (m_storage != null) {
3162: m_storage.close();
3163: m_storage = null;
3164: }
3165: }
3166:
3167: /**
3168: * Access the partial URL that forms the root of calendar URLs.
3169: *
3170: * @param relative
3171: * if true, form within the access path only (i.e. starting with
3172: * /content)
3173: * @return the partial URL that forms the root of calendar URLs.
3174: */
3175: protected String getAccessPoint(boolean relative) {
3176: return (relative ? "" : m_serverConfigurationService
3177: .getAccessUrl())
3178: + m_relativeAccessPoint;
3179:
3180: } // getAccessPoint
3181:
3182: /*
3183: * (non-Javadoc)
3184: *
3185: * @see org.sakaiproject.citation.api.CitationService#getCollection(java.lang.String)
3186: */
3187: public CitationCollection getCollection(String collectionId)
3188: throws IdUnusedException {
3189: CitationCollection edit = m_storage.getCollection(collectionId);
3190: if (edit == null) {
3191: throw new IdUnusedException(collectionId);
3192: }
3193: return edit;
3194: }
3195:
3196: /*
3197: * (non-Javadoc)
3198: *
3199: * @see org.sakaiproject.citation.api.CitationService#getDefaultSchema()
3200: */
3201: public Schema getDefaultSchema() {
3202: Schema rv = null;
3203: if (m_defaultSchema != null) {
3204: rv = m_storage.getSchema(m_defaultSchema);
3205: }
3206: return rv;
3207: }
3208:
3209: /*
3210: * (non-Javadoc)
3211: *
3212: * @see org.sakaiproject.entity.api.EntityProducer#getEntity(org.sakaiproject.entity.api.Reference)
3213: */
3214: public Entity getEntity(Reference ref) {
3215: Entity entity = null;
3216: if (APPLICATION_ID.equals(ref.getType())) {
3217: if (REF_TYPE_EXPORT_RIS_SEL.equals(ref.getSubType())
3218: || REF_TYPE_EXPORT_RIS_ALL.equals(ref.getSubType())) {
3219: // these entities are citation collections
3220: String id = ref.getId();
3221: if (id == null || id.trim().equals("")) {
3222: String reference = ref.getReference();
3223: if (reference != null
3224: && reference.startsWith(REFERENCE_ROOT)) {
3225: id = reference.substring(REFERENCE_ROOT
3226: .length(), reference.length());
3227: }
3228: }
3229:
3230: if (id != null && !id.trim().equals("")) {
3231: entity = m_storage.getCollection(id);
3232: }
3233: } else if (REF_TYPE_VIEW_LIST.equals(ref.getSubType())) {
3234: // these entities are actually in /content
3235: String id = ref.getId();
3236: if (id == null || id.trim().equals("")) {
3237: String reference = ref.getReference();
3238: if (reference.startsWith(REFERENCE_ROOT)) {
3239: reference = reference.substring(REFERENCE_ROOT
3240: .length(), reference.length());
3241: }
3242: if (reference
3243: .startsWith(m_contentHostingService.REFERENCE_ROOT)) {
3244: id = reference.substring(
3245: m_contentHostingService.REFERENCE_ROOT
3246: .length(), reference.length());
3247: }
3248: }
3249:
3250: if (id != null && !id.trim().equals("")) {
3251: try {
3252: entity = m_contentHostingService
3253: .getResource(id);
3254: } catch (PermissionException e) {
3255: M_log.warn("getEntity(" + id + ") ", e);
3256: } catch (IdUnusedException e) {
3257: M_log.warn("getEntity(" + id + ") ", e);
3258: } catch (TypeException e) {
3259: M_log.warn("getEntity(" + id + ") ", e);
3260: }
3261: }
3262: }
3263: }
3264:
3265: // and maybe others are in /citation
3266:
3267: return entity;
3268: }
3269:
3270: /*
3271: * (non-Javadoc)
3272: *
3273: * @see org.sakaiproject.entity.api.EntityProducer#getEntityAuthzGroups(org.sakaiproject.entity.api.Reference,
3274: * java.lang.String)
3275: */
3276: public Collection getEntityAuthzGroups(Reference ref, String userId) {
3277: // entities that are actually in /content use the /content authz groups
3278:
3279: // those in /citation are open?
3280:
3281: return null;
3282: }
3283:
3284: /*
3285: * (non-Javadoc)
3286: *
3287: * @see org.sakaiproject.entity.api.EntityProducer#getEntityDescription(org.sakaiproject.entity.api.Reference)
3288: */
3289: public String getEntityDescription(Reference ref) {
3290: // TODO Auto-generated method stub
3291: return null;
3292: }
3293:
3294: /*
3295: * (non-Javadoc)
3296: *
3297: * @see org.sakaiproject.entity.api.EntityProducer#getEntityResourceProperties(org.sakaiproject.entity.api.Reference)
3298: */
3299: public ResourceProperties getEntityResourceProperties(Reference ref) {
3300: // if it's a /content item, return its props
3301:
3302: // otherwise return null
3303:
3304: return null;
3305: }
3306:
3307: /*
3308: * (non-Javadoc)
3309: *
3310: * @see org.sakaiproject.entity.api.EntityProducer#getEntityUrl(org.sakaiproject.entity.api.Reference)
3311: */
3312: public String getEntityUrl(Reference ref) {
3313:
3314: return null;
3315: }
3316:
3317: /*
3318: * (non-Javadoc)
3319: *
3320: * @see org.sakaiproject.entity.api.EntityProducer#getHttpAccess()
3321: */
3322: public HttpAccess getHttpAccess() {
3323: // if it's a /content item, the access is via CitationListAccessServlet
3324: return new CitationListAccessServlet();
3325: }
3326:
3327: /*
3328: * (non-Javadoc)
3329: *
3330: * @see org.sakaiproject.entity.api.EntityProducer#getLabel()
3331: */
3332: public String getLabel() {
3333: // TODO Auto-generated method stub
3334: return null;
3335: }
3336:
3337: /**
3338: * @return
3339: */
3340: public Set getMultivalued() {
3341: Set multivalued = new TreeSet();
3342: Iterator schemaIt = m_storage.getSchemas().iterator();
3343: while (schemaIt.hasNext()) {
3344: Schema schema = (Schema) schemaIt.next();
3345: {
3346: Iterator fieldIt = schema.getFields().iterator();
3347: while (fieldIt.hasNext()) {
3348: Field field = (Field) fieldIt.next();
3349: if (field.getMaxCardinality() > 1) {
3350: multivalued.add(field.getIdentifier());
3351: }
3352: }
3353: }
3354: }
3355:
3356: return multivalued;
3357: }
3358:
3359: /**
3360: * @return
3361: */
3362: public Set getMultivalued(String type) {
3363: Set multivalued = new TreeSet();
3364: Schema schema = m_storage.getSchema(type);
3365: {
3366: Iterator fieldIt = schema.getFields().iterator();
3367: while (fieldIt.hasNext()) {
3368: Field field = (Field) fieldIt.next();
3369: if (field.getMaxCardinality() > 1) {
3370: multivalued.add(field.getIdentifier());
3371: }
3372: }
3373: }
3374:
3375: return multivalued;
3376: }
3377:
3378: public Schema getSchema(String name) {
3379: Schema schema = m_storage.getSchema(name);
3380: return schema;
3381: }
3382:
3383: /*
3384: * (non-Javadoc)
3385: *
3386: * @see org.sakaiproject.citation.api.CitationService#getSchemas()
3387: */
3388: public List getSchemas() {
3389: List schemas = new Vector(m_storage.getSchemas());
3390: return schemas;
3391: }
3392:
3393: /*
3394: * (non-Javadoc)
3395: *
3396: * @see org.sakaiproject.citation.api.Schema#getSynonyms(java.lang.String)
3397: */
3398: protected Set getSynonyms(String mediatype) {
3399: Set synonyms = new TreeSet();
3400: if (mediatype.equalsIgnoreCase("article")) {
3401: synonyms.add("article");
3402: synonyms.add("journal article");
3403: synonyms.add("journal");
3404: synonyms.add("periodical");
3405: synonyms.add("newspaper article");
3406: synonyms.add("magazine article");
3407: synonyms.add("editorial");
3408: synonyms.add("peer reviewed article");
3409: synonyms.add("peer reviewed journal article");
3410: synonyms.add("book review");
3411: synonyms.add("review");
3412: synonyms.add("meeting");
3413: synonyms.add("wire feed");
3414: synonyms.add("wire story");
3415: synonyms.add("journal article (cije)");
3416: } else if (mediatype.equalsIgnoreCase("book")) {
3417: synonyms.add("book");
3418:
3419: } else if (mediatype.equalsIgnoreCase("chapter")) {
3420: synonyms.add("chapter");
3421: synonyms.add("book chapter");
3422: synonyms.add("book section");
3423: } else if (mediatype.equalsIgnoreCase("report")) {
3424: synonyms.add("report");
3425: synonyms.add("editorial material");
3426: synonyms.add("technical report");
3427: synonyms.add("se");
3428: synonyms.add("document (rie)");
3429: }
3430:
3431: return synonyms;
3432: }
3433:
3434: public Citation getTemporaryCitation() {
3435: return new BasicCitation();
3436: }
3437:
3438: public Citation getTemporaryCitation(Asset asset) {
3439: return new BasicCitation(asset);
3440: }
3441:
3442: public CitationCollection getTemporaryCollection() {
3443: return new BasicCitationCollection(true);
3444: }
3445:
3446: /*
3447: * (non-Javadoc)
3448: *
3449: * @see org.sakaiproject.citation.api.CitationService#getValidPropertyNames()
3450: */
3451: public Set getValidPropertyNames() {
3452: Set names = new TreeSet();
3453: Iterator schemaIt = m_storage.getSchemas().iterator();
3454: while (schemaIt.hasNext()) {
3455: Schema schema = (Schema) schemaIt.next();
3456: {
3457: Iterator fieldIt = schema.getFields().iterator();
3458: while (fieldIt.hasNext()) {
3459: Field field = (Field) fieldIt.next();
3460: names.add(field.getIdentifier());
3461: }
3462: }
3463: }
3464:
3465: return names;
3466:
3467: } // getValidPropertyNames
3468:
3469: public class CitationListCreateAction extends BaseInteractionAction {
3470:
3471: /**
3472: * @param id
3473: * @param actionType
3474: * @param typeId
3475: * @param helperId
3476: * @param requiredPropertyKeys
3477: */
3478: public CitationListCreateAction(String id,
3479: ActionType actionType, String typeId, String helperId,
3480: List requiredPropertyKeys) {
3481: super (id, actionType, typeId, helperId,
3482: requiredPropertyKeys);
3483: }
3484:
3485: /* (non-Javadoc)
3486: * @see org.sakaiproject.content.util.BaseResourceAction#available(org.sakaiproject.content.api.ContentEntity)
3487: */
3488: @Override
3489: public boolean available(ContentEntity entity) {
3490: return super .available(entity);
3491: }
3492:
3493: }
3494:
3495: /**
3496: *
3497: *
3498: */
3499: public void init() {
3500: if (m_configService.isCitationsEnabledByDefault()
3501: || m_configService.isAllowSiteBySiteOverride()) {
3502: m_storage = newStorage();
3503: m_nextSerialNumber = new Integer(0);
3504:
3505: m_relativeAccessPoint = CitationService.REFERENCE_ROOT;
3506:
3507: // register as an entity producer
3508: m_entityManager
3509: .registerEntityProducer(this , REFERENCE_ROOT);
3510:
3511: rb = new ResourceLoader("citations");
3512:
3513: //initializeSchemas();
3514: m_defaultSchema = "article";
3515:
3516: registerResourceType();
3517: }
3518: }
3519:
3520: /**
3521: *
3522: */
3523: protected void registerResourceType() {
3524: ResourceTypeRegistry registry = getResourceTypeRegistry();
3525:
3526: List requiredPropertyKeys = new Vector();
3527: requiredPropertyKeys
3528: .add(ContentHostingService.PROP_ALTERNATE_REFERENCE);
3529: requiredPropertyKeys.add(ResourceProperties.PROP_CONTENT_TYPE);
3530:
3531: BaseInteractionAction createAction = new CitationListCreateAction(
3532: ResourceToolAction.CREATE,
3533: ResourceToolAction.ActionType.CREATE,
3534: CitationService.CITATION_LIST_ID,
3535: CitationService.HELPER_ID, new Vector());
3536:
3537: createAction.setLocalizer(new BaseResourceAction.Localizer() {
3538: public String getLabel() {
3539: return rb.getString("action.create");
3540: }
3541: });
3542:
3543: BaseInteractionAction reviseAction = new BaseInteractionAction(
3544: ResourceToolAction.REVISE_CONTENT,
3545: ResourceToolAction.ActionType.REVISE_CONTENT,
3546: CitationService.CITATION_LIST_ID,
3547: CitationService.HELPER_ID, new Vector());
3548:
3549: reviseAction.setLocalizer(new BaseResourceAction.Localizer() {
3550: public String getLabel() {
3551: return rb.getString("action.revise");
3552: }
3553: });
3554:
3555: BaseServiceLevelAction moveAction = new BaseServiceLevelAction(
3556: ResourceToolAction.MOVE,
3557: ResourceToolAction.ActionType.MOVE,
3558: CitationService.CITATION_LIST_ID, true);
3559:
3560: BaseServiceLevelAction revisePropsAction = new BaseServiceLevelAction(
3561: ResourceToolAction.REVISE_METADATA,
3562: ResourceToolAction.ActionType.REVISE_METADATA,
3563: CitationService.CITATION_LIST_ID, false);
3564:
3565: BasicSiteSelectableResourceType typedef = new BasicSiteSelectableResourceType(
3566: CitationService.CITATION_LIST_ID);
3567: typedef.setLocalizer(new CitationLocalizer());
3568: typedef.addAction(createAction);
3569: typedef.addAction(reviseAction);
3570: typedef.addAction(new CitationListDeleteAction());
3571: typedef.addAction(new CitationListCopyAction());
3572: typedef.addAction(new CitationListDuplicateAction());
3573: typedef.addAction(revisePropsAction);
3574: typedef.addAction(moveAction);
3575: typedef.setEnabledByDefault(m_configService
3576: .isCitationsEnabledByDefault());
3577: typedef.setIconLocation("sakai/citationlist.gif");
3578: typedef.setHasRightsDialog(false);
3579:
3580: registry.register(typedef);
3581: }
3582:
3583: /**
3584: *
3585: */
3586: protected void initializeSchemas() {
3587: BasicSchema unknown = new BasicSchema();
3588: unknown.setIdentifier(CitationService.UNKNOWN_TYPE);
3589:
3590: BasicSchema article = new BasicSchema();
3591: article.setIdentifier("article");
3592:
3593: BasicSchema book = new BasicSchema();
3594: book.setIdentifier("book");
3595:
3596: BasicSchema chapter = new BasicSchema();
3597: chapter.setIdentifier("chapter");
3598:
3599: BasicSchema report = new BasicSchema();
3600: report.setIdentifier("report");
3601:
3602: /* schema ordering is different for different types */
3603:
3604: /*
3605: * UNKNOWN (GENERIC)
3606: */
3607: unknown.addField(Schema.CREATOR, Schema.SHORTTEXT, true, false,
3608: 0, Schema.UNLIMITED);
3609: unknown.addAlternativeIdentifier(Schema.CREATOR, RIS_FORMAT,
3610: "A1");
3611:
3612: unknown.addField(Schema.TITLE, Schema.SHORTTEXT, true, true, 1,
3613: 1);
3614: unknown
3615: .addAlternativeIdentifier(Schema.TITLE, RIS_FORMAT,
3616: "T1");
3617:
3618: unknown.addField(Schema.YEAR, Schema.NUMBER, true, false, 0, 1);
3619:
3620: unknown.addField("date", Schema.NUMBER, true, false, 0, 1);
3621: unknown.addAlternativeIdentifier("date", RIS_FORMAT, "Y1");
3622:
3623: unknown.addField(Schema.PUBLISHER, Schema.SHORTTEXT, true,
3624: false, 0, 1);
3625: unknown.addAlternativeIdentifier(Schema.PUBLISHER, RIS_FORMAT,
3626: "PB");
3627:
3628: unknown.addField("publicationLocation", Schema.SHORTTEXT, true,
3629: false, 0, 1);
3630: unknown.addAlternativeIdentifier("publicationLocation",
3631: RIS_FORMAT, "CY");
3632:
3633: unknown.addField(Schema.VOLUME, Schema.NUMBER, true, false, 0,
3634: 1);
3635: unknown.addAlternativeIdentifier(Schema.VOLUME, RIS_FORMAT,
3636: "VL");
3637:
3638: unknown
3639: .addField(Schema.ISSUE, Schema.NUMBER, true, false, 0,
3640: 1);
3641: unknown
3642: .addAlternativeIdentifier(Schema.ISSUE, RIS_FORMAT,
3643: "IS");
3644:
3645: unknown
3646: .addField(Schema.PAGES, Schema.NUMBER, true, false, 0,
3647: 1);
3648: unknown
3649: .addAlternativeIdentifier(Schema.PAGES, RIS_FORMAT,
3650: "SP");
3651:
3652: unknown.addField("startPage", Schema.NUMBER, true, false, 0, 1);
3653: unknown.addAlternativeIdentifier("startPage", RIS_FORMAT, "SP");
3654:
3655: unknown.addField("endPage", Schema.NUMBER, true, false, 0, 1);
3656: unknown.addAlternativeIdentifier("endPage", RIS_FORMAT, "EP");
3657:
3658: unknown.addField("edition", Schema.NUMBER, true, false, 0, 1);
3659: unknown.addAlternativeIdentifier("edition", RIS_FORMAT, "VL");
3660:
3661: unknown.addField("editor", Schema.SHORTTEXT, true, false, 0,
3662: Schema.UNLIMITED);
3663: unknown.addAlternativeIdentifier("editor", RIS_FORMAT, "A3");
3664:
3665: unknown.addField(Schema.SOURCE_TITLE, Schema.SHORTTEXT, true,
3666: false, 0, 1);
3667: unknown.addAlternativeIdentifier(Schema.SOURCE_TITLE,
3668: RIS_FORMAT, "T3");
3669:
3670: unknown.addField("Language", Schema.NUMBER, true, false, 0, 1);
3671:
3672: unknown
3673: .addField("abstract", Schema.LONGTEXT, true, false, 0,
3674: 1);
3675: unknown.addAlternativeIdentifier("abstract", RIS_FORMAT, "N2");
3676:
3677: unknown.addField("note", Schema.SHORTTEXT, true, false, 0,
3678: Schema.UNLIMITED);
3679: unknown.addAlternativeIdentifier("note", RIS_FORMAT, "N1");
3680:
3681: unknown.addField(Schema.ISN, Schema.SHORTTEXT, true, false, 0,
3682: 1);
3683: unknown.addAlternativeIdentifier(Schema.ISN, RIS_FORMAT, "SN");
3684:
3685: unknown.addField("subject", Schema.SHORTTEXT, true, false, 0,
3686: Schema.UNLIMITED);
3687: unknown.addAlternativeIdentifier("subject", RIS_FORMAT, "KW");
3688:
3689: unknown.addField("locIdentifier", Schema.SHORTTEXT, true,
3690: false, 0, 1);
3691: unknown.addAlternativeIdentifier("locIdentifier", RIS_FORMAT,
3692: "M1");
3693:
3694: unknown.addField("dateRetrieved", Schema.DATE, false, false, 0,
3695: 1);
3696:
3697: unknown.addField("openURL", Schema.SHORTTEXT, false, false, 0,
3698: 1);
3699:
3700: unknown.addField("doi", Schema.NUMBER, true, false, 0, 1);
3701:
3702: unknown.addField("rights", Schema.SHORTTEXT, true, false, 0,
3703: Schema.UNLIMITED);
3704:
3705: /*
3706: * ARTICLE
3707: */
3708: article.addField(Schema.CREATOR, Schema.SHORTTEXT, true, false,
3709: 0, Schema.UNLIMITED);
3710: article.addAlternativeIdentifier(Schema.CREATOR, RIS_FORMAT,
3711: "A1");
3712:
3713: article.addField(Schema.TITLE, Schema.SHORTTEXT, true, true, 1,
3714: 1);
3715: article
3716: .addAlternativeIdentifier(Schema.TITLE, RIS_FORMAT,
3717: "T1");
3718:
3719: article.addField(Schema.SOURCE_TITLE, Schema.SHORTTEXT, true,
3720: false, 0, 1);
3721: article.addAlternativeIdentifier(Schema.SOURCE_TITLE,
3722: RIS_FORMAT, "JF");
3723:
3724: article.addField(Schema.YEAR, Schema.NUMBER, true, false, 0, 1);
3725:
3726: article.addField("date", Schema.NUMBER, true, false, 0, 1);
3727: article.addAlternativeIdentifier("date", RIS_FORMAT, "Y1");
3728:
3729: article.addField(Schema.VOLUME, Schema.NUMBER, true, false, 0,
3730: 1);
3731: article.addAlternativeIdentifier(Schema.VOLUME, RIS_FORMAT,
3732: "VL");
3733:
3734: article
3735: .addField(Schema.ISSUE, Schema.NUMBER, true, false, 0,
3736: 1);
3737: article
3738: .addAlternativeIdentifier(Schema.ISSUE, RIS_FORMAT,
3739: "IS");
3740:
3741: article
3742: .addField(Schema.PAGES, Schema.NUMBER, true, false, 0,
3743: 1);
3744:
3745: article.addField("startPage", Schema.NUMBER, true, false, 0, 1);
3746: article.addAlternativeIdentifier("startPage", RIS_FORMAT, "SP");
3747:
3748: article.addField("endPage", Schema.NUMBER, true, false, 0, 1);
3749: article.addAlternativeIdentifier("endPage", RIS_FORMAT, "EP");
3750:
3751: article
3752: .addField("abstract", Schema.LONGTEXT, true, false, 0,
3753: 1);
3754: article.addAlternativeIdentifier("abstract", RIS_FORMAT, "N2");
3755:
3756: article.addField("note", Schema.SHORTTEXT, true, false, 0,
3757: Schema.UNLIMITED);
3758: article.addAlternativeIdentifier("note", RIS_FORMAT, "N1");
3759:
3760: article.addField(Schema.ISN, Schema.SHORTTEXT, true, false, 0,
3761: 1);
3762: article.addAlternativeIdentifier(Schema.ISN, RIS_FORMAT, "SN");
3763:
3764: article.addField("subject", Schema.SHORTTEXT, true, false, 0,
3765: Schema.UNLIMITED);
3766: article.addAlternativeIdentifier("subject", RIS_FORMAT, "KW");
3767:
3768: article.addField("Language", Schema.NUMBER, true, false, 0, 1);
3769:
3770: article.addField("locIdentifier", Schema.SHORTTEXT, true,
3771: false, 0, 1);
3772: article.addAlternativeIdentifier("locIdentifier", RIS_FORMAT,
3773: "M1");
3774:
3775: article.addField("dateRetrieved", Schema.DATE, false, false, 0,
3776: 1);
3777:
3778: article.addField("openURL", Schema.SHORTTEXT, false, false, 0,
3779: 1);
3780:
3781: article.addField("doi", Schema.NUMBER, true, false, 0, 1);
3782:
3783: article.addField("rights", Schema.SHORTTEXT, true, false, 0,
3784: Schema.UNLIMITED);
3785:
3786: /*
3787: * BOOK
3788: */
3789: book.addField(Schema.CREATOR, Schema.SHORTTEXT, true, true, 1,
3790: Schema.UNLIMITED);
3791: book.addAlternativeIdentifier(Schema.CREATOR, RIS_FORMAT, "A1");
3792:
3793: book.addField(Schema.TITLE, Schema.SHORTTEXT, true, true, 1, 1);
3794: book.addAlternativeIdentifier(Schema.TITLE, RIS_FORMAT, "BT");
3795:
3796: book.addField(Schema.YEAR, Schema.NUMBER, true, false, 0, 1);
3797:
3798: book.addField("date", Schema.NUMBER, true, false, 0, 1);
3799: book.addAlternativeIdentifier("date", RIS_FORMAT, "Y1");
3800:
3801: book.addField(Schema.PUBLISHER, Schema.SHORTTEXT, true, false,
3802: 0, 1);
3803: book.addAlternativeIdentifier(Schema.PUBLISHER, RIS_FORMAT,
3804: "PB");
3805:
3806: book.addField("publicationLocation", Schema.SHORTTEXT, true,
3807: false, 0, 1);
3808: book.addAlternativeIdentifier("publicationLocation",
3809: RIS_FORMAT, "CY");
3810:
3811: book.addField("edition", Schema.NUMBER, true, false, 0, 1);
3812: book.addAlternativeIdentifier("edition", RIS_FORMAT, "VL");
3813:
3814: book.addField("editor", Schema.SHORTTEXT, true, false, 0,
3815: Schema.UNLIMITED);
3816: book.addAlternativeIdentifier("editor", RIS_FORMAT, "A3");
3817:
3818: book.addField(Schema.SOURCE_TITLE, Schema.SHORTTEXT, true,
3819: false, 0, 1);
3820: book.addAlternativeIdentifier(Schema.SOURCE_TITLE, RIS_FORMAT,
3821: "T3");
3822:
3823: book.addField("abstract", Schema.LONGTEXT, true, false, 0, 1);
3824: book.addAlternativeIdentifier("abstract", RIS_FORMAT, "N2");
3825:
3826: book.addField("note", Schema.SHORTTEXT, true, false, 0,
3827: Schema.UNLIMITED);
3828: book.addAlternativeIdentifier("note", RIS_FORMAT, "N1");
3829:
3830: book.addField(Schema.ISN, Schema.SHORTTEXT, true, false, 0, 1);
3831: book.addAlternativeIdentifier(Schema.ISN, RIS_FORMAT, "SN");
3832:
3833: book.addField("subject", Schema.SHORTTEXT, true, false, 0,
3834: Schema.UNLIMITED);
3835: book.addAlternativeIdentifier("subject", RIS_FORMAT, "KW");
3836:
3837: book.addField("Language", Schema.NUMBER, true, false, 0, 1);
3838:
3839: book.addField("locIdentifier", Schema.SHORTTEXT, true, false,
3840: 0, 1);
3841: book
3842: .addAlternativeIdentifier("locIdentifier", RIS_FORMAT,
3843: "M1");
3844:
3845: book.addField("dateRetrieved", Schema.DATE, false, false, 0, 1);
3846:
3847: book.addField("openURL", Schema.SHORTTEXT, false, false, 0, 1);
3848:
3849: book.addField("doi", Schema.NUMBER, true, false, 0, 1);
3850:
3851: book.addField("rights", Schema.SHORTTEXT, true, false, 0,
3852: Schema.UNLIMITED);
3853:
3854: book.addAlternativeIdentifier(Schema.PAGES, RIS_FORMAT, "SP");
3855:
3856: /*
3857: * CHAPTER
3858: */
3859: chapter.addField(Schema.CREATOR, Schema.SHORTTEXT, true, true,
3860: 1, Schema.UNLIMITED);
3861: chapter.addAlternativeIdentifier(Schema.CREATOR, RIS_FORMAT,
3862: "A1");
3863:
3864: chapter.addField(Schema.TITLE, Schema.SHORTTEXT, true, true, 1,
3865: 1);
3866: chapter
3867: .addAlternativeIdentifier(Schema.TITLE, RIS_FORMAT,
3868: "CT");
3869:
3870: chapter.addField(Schema.YEAR, Schema.NUMBER, true, false, 0, 1);
3871:
3872: chapter.addField("date", Schema.NUMBER, true, false, 0, 1);
3873: chapter.addAlternativeIdentifier("date", RIS_FORMAT, "Y1");
3874:
3875: chapter.addField(Schema.PUBLISHER, Schema.SHORTTEXT, true,
3876: false, 0, 1);
3877: chapter.addAlternativeIdentifier(Schema.PUBLISHER, RIS_FORMAT,
3878: "PB");
3879:
3880: chapter.addField("publicationLocation", Schema.SHORTTEXT, true,
3881: false, 0, 1);
3882: chapter.addAlternativeIdentifier("publicationLocation",
3883: RIS_FORMAT, "CY");
3884:
3885: chapter.addField("edition", Schema.NUMBER, true, false, 0, 1);
3886: chapter.addAlternativeIdentifier("edition", RIS_FORMAT, "VL");
3887:
3888: chapter.addField("editor", Schema.SHORTTEXT, true, false, 0,
3889: Schema.UNLIMITED);
3890: chapter.addAlternativeIdentifier("editor", RIS_FORMAT, "ED");
3891:
3892: chapter.addField(Schema.SOURCE_TITLE, Schema.SHORTTEXT, true,
3893: false, 0, 1);
3894: chapter.addAlternativeIdentifier(Schema.SOURCE_TITLE,
3895: RIS_FORMAT, "BT");
3896:
3897: chapter
3898: .addField(Schema.PAGES, Schema.NUMBER, true, false, 0,
3899: 1);
3900: chapter
3901: .addAlternativeIdentifier(Schema.PAGES, RIS_FORMAT,
3902: "SP");
3903:
3904: chapter.addField("startPage", Schema.NUMBER, true, false, 0, 1);
3905: chapter.addAlternativeIdentifier("startPage", RIS_FORMAT, "SP");
3906:
3907: chapter.addField("endPage", Schema.NUMBER, true, false, 0, 1);
3908: chapter.addAlternativeIdentifier("endPage", RIS_FORMAT, "EP");
3909:
3910: chapter
3911: .addField("abstract", Schema.LONGTEXT, true, false, 0,
3912: 1);
3913: chapter.addAlternativeIdentifier("abstract", RIS_FORMAT, "N2");
3914:
3915: chapter.addField("note", Schema.SHORTTEXT, true, false, 0,
3916: Schema.UNLIMITED);
3917: chapter.addAlternativeIdentifier("note", RIS_FORMAT, "N1");
3918:
3919: chapter.addField(Schema.ISN, Schema.SHORTTEXT, true, false, 0,
3920: 1);
3921: chapter.addAlternativeIdentifier(Schema.ISN, RIS_FORMAT, "SN");
3922:
3923: chapter.addField("subject", Schema.SHORTTEXT, true, false, 0,
3924: Schema.UNLIMITED);
3925: chapter.addAlternativeIdentifier("subject", RIS_FORMAT, "KW");
3926:
3927: chapter.addField("Language", Schema.NUMBER, true, false, 0, 1);
3928:
3929: chapter.addField("locIdentifier", Schema.SHORTTEXT, true,
3930: false, 0, 1);
3931: chapter.addAlternativeIdentifier("locIdentifier", RIS_FORMAT,
3932: "M1");
3933:
3934: chapter.addField("dateRetrieved", Schema.DATE, false, false, 0,
3935: 1);
3936:
3937: chapter.addField("openURL", Schema.SHORTTEXT, false, false, 0,
3938: 1);
3939:
3940: chapter.addField("doi", Schema.NUMBER, true, false, 0, 1);
3941:
3942: chapter.addField("rights", Schema.SHORTTEXT, true, false, 0,
3943: Schema.UNLIMITED);
3944:
3945: /*
3946: * REPORT
3947: */
3948: report.addField(Schema.CREATOR, Schema.SHORTTEXT, true, true,
3949: 1, Schema.UNLIMITED);
3950: report.addAlternativeIdentifier(Schema.CREATOR, RIS_FORMAT,
3951: "A1");
3952:
3953: report.addField(Schema.TITLE, Schema.SHORTTEXT, true, true, 1,
3954: 1);
3955: report.addAlternativeIdentifier(Schema.TITLE, RIS_FORMAT, "T1");
3956:
3957: report.addField(Schema.YEAR, Schema.NUMBER, true, false, 0, 1);
3958:
3959: report.addField("date", Schema.NUMBER, true, false, 0, 1);
3960: report.addAlternativeIdentifier("date", RIS_FORMAT, "Y1");
3961:
3962: report.addField(Schema.PUBLISHER, Schema.SHORTTEXT, true,
3963: false, 0, 1);
3964: report.addAlternativeIdentifier(Schema.PUBLISHER, RIS_FORMAT,
3965: "PB");
3966:
3967: report.addField("publicationLocation", Schema.SHORTTEXT, true,
3968: false, 0, 1);
3969: report.addAlternativeIdentifier("publicationLocation",
3970: RIS_FORMAT, "CY");
3971:
3972: report.addField("editor", Schema.SHORTTEXT, true, false, 0,
3973: Schema.UNLIMITED);
3974: report.addAlternativeIdentifier("editor", RIS_FORMAT, "A3");
3975:
3976: report.addField("edition", Schema.NUMBER, true, false, 0, 1);
3977: report.addAlternativeIdentifier("edition", RIS_FORMAT, "VL");
3978:
3979: report.addField(Schema.SOURCE_TITLE, Schema.SHORTTEXT, true,
3980: false, 0, 1);
3981: report.addAlternativeIdentifier(Schema.SOURCE_TITLE,
3982: RIS_FORMAT, "T3");
3983:
3984: report.addField(Schema.PAGES, Schema.NUMBER, true, false, 0, 1);
3985: report.addAlternativeIdentifier(Schema.PAGES, RIS_FORMAT, "SP");
3986:
3987: report.addField("abstract", Schema.LONGTEXT, true, false, 0, 1);
3988: report.addAlternativeIdentifier("abstract", RIS_FORMAT, "N2");
3989:
3990: report
3991: .addField(Schema.ISN, Schema.SHORTTEXT, true, false, 0,
3992: 1);
3993: report.addAlternativeIdentifier(Schema.ISN, RIS_FORMAT, "SN");
3994:
3995: report.addField("note", Schema.SHORTTEXT, true, false, 0,
3996: Schema.UNLIMITED);
3997: report.addAlternativeIdentifier("note", RIS_FORMAT, "N1");
3998:
3999: report.addField("subject", Schema.SHORTTEXT, true, false, 0,
4000: Schema.UNLIMITED);
4001: report.addAlternativeIdentifier("subject", RIS_FORMAT, "KW");
4002:
4003: report.addField("Language", Schema.NUMBER, true, false, 0, 1);
4004:
4005: report.addField("locIdentifier", Schema.SHORTTEXT, true, false,
4006: 0, 1);
4007: report.addAlternativeIdentifier("locIdentifier", RIS_FORMAT,
4008: "M1");
4009:
4010: report.addField("dateRetrieved", Schema.DATE, false, false, 0,
4011: 1);
4012:
4013: report
4014: .addField("openURL", Schema.SHORTTEXT, false, false, 0,
4015: 1);
4016:
4017: report.addField("doi", Schema.NUMBER, true, false, 0, 1);
4018:
4019: report.addField("rights", Schema.SHORTTEXT, true, false, 0,
4020: Schema.UNLIMITED);
4021:
4022: /* IGNORING 'Citation' field for now...
4023: unknown.addField("inlineCitation", Schema.SHORTTEXT, false, false, 0, Schema.UNLIMITED);
4024: article.addField("inlineCitation", Schema.SHORTTEXT, false, false, 0, Schema.UNLIMITED);
4025: book.addField("inlineCitation", Schema.SHORTTEXT, false, false, 0, Schema.UNLIMITED);
4026: chapter.addField("inlineCitation", Schema.SHORTTEXT, false, false, 0, Schema.UNLIMITED);
4027: report.addField("inlineCitation", Schema.SHORTTEXT, false, false, 0, Schema.UNLIMITED);
4028: */
4029:
4030: if (m_storage.checkSchema(unknown.getIdentifier())) {
4031: m_storage.updateSchema(unknown);
4032: } else {
4033: m_storage.addSchema(unknown);
4034: }
4035:
4036: if (m_storage.checkSchema(article.getIdentifier())) {
4037: m_storage.updateSchema(article);
4038: } else {
4039: m_storage.addSchema(article);
4040: }
4041:
4042: if (m_storage.checkSchema(book.getIdentifier())) {
4043: m_storage.updateSchema(book);
4044: } else {
4045: m_storage.addSchema(book);
4046: }
4047:
4048: if (m_storage.checkSchema(chapter.getIdentifier())) {
4049: m_storage.updateSchema(chapter);
4050: } else {
4051: m_storage.addSchema(chapter);
4052: }
4053:
4054: if (m_storage.checkSchema(report.getIdentifier())) {
4055: m_storage.updateSchema(report);
4056: } else {
4057: m_storage.addSchema(report);
4058: }
4059:
4060: }
4061:
4062: public class CitationListDeleteAction extends
4063: BaseServiceLevelAction {
4064: public CitationListDeleteAction() {
4065: super (ResourceToolAction.DELETE,
4066: ResourceToolAction.ActionType.DELETE,
4067: CitationService.CITATION_LIST_ID, true);
4068: }
4069:
4070: public void finalizeAction(Reference reference) {
4071: try {
4072: ContentResource resource = (ContentResource) reference
4073: .getEntity();
4074: String collectionId = new String(resource.getContent());
4075: CitationCollection collection = getCollection(collectionId);
4076: removeCollection(collection);
4077: } catch (IdUnusedException e) {
4078: M_log.warn("IdUnusedException ", e);
4079: } catch (ServerOverloadException e) {
4080: M_log.warn("ServerOverloadException ", e);
4081: }
4082: }
4083: }
4084:
4085: public class CitationLocalizer implements
4086: BasicResourceType.Localizer {
4087: /**
4088: *
4089: * @return
4090: */
4091: public String getLabel() {
4092: return rb.getString("list.title");
4093: }
4094:
4095: /**
4096: *
4097: * @param member
4098: * @return
4099: */
4100: public String getLocalizedHoverText(ContentEntity member) {
4101:
4102: return rb.getString("list.title");
4103: }
4104:
4105: }
4106:
4107: public class CitationListCopyAction extends BaseServiceLevelAction {
4108:
4109: public CitationListCopyAction() {
4110: super (ResourceToolAction.COPY,
4111: ResourceToolAction.ActionType.COPY,
4112: CitationService.CITATION_LIST_ID, true);
4113: }
4114:
4115: @Override
4116: public void finalizeAction(Reference reference) {
4117: ContentHostingService contentService = (ContentHostingService) ComponentManager
4118: .get(ContentHostingService.class);
4119: try {
4120: ContentResourceEdit edit = contentService
4121: .editResource(reference.getId());
4122: String collectionId = new String(edit.getContent());
4123: CitationCollection oldCollection = getCollection(collectionId);
4124: BasicCitationCollection newCollection = new BasicCitationCollection();
4125: newCollection
4126: .copy((BasicCitationCollection) oldCollection);
4127: save(newCollection);
4128: edit.setContent(newCollection.getId().getBytes());
4129: contentService.commitResource(edit);
4130: } catch (IdUnusedException e) {
4131: M_log.warn("IdUnusedException ", e);
4132: } catch (ServerOverloadException e) {
4133: M_log.warn("ServerOverloadException ", e);
4134: } catch (PermissionException e) {
4135: M_log.warn("PermissionException ", e);
4136: } catch (TypeException e) {
4137: M_log.warn("TypeException ", e);
4138: } catch (InUseException e) {
4139: M_log.warn("InUseException ", e);
4140: } catch (OverQuotaException e) {
4141: M_log.warn("OverQuotaException ", e);
4142: }
4143: }
4144:
4145: }
4146:
4147: public class CitationListDuplicateAction extends
4148: BaseServiceLevelAction {
4149:
4150: public CitationListDuplicateAction() {
4151: super (ResourceToolAction.DUPLICATE,
4152: ResourceToolAction.ActionType.DUPLICATE,
4153: CitationService.CITATION_LIST_ID, false);
4154: }
4155:
4156: @Override
4157: public void finalizeAction(Reference reference) {
4158: ContentHostingService contentService = (ContentHostingService) ComponentManager
4159: .get(ContentHostingService.class);
4160: try {
4161: ContentResourceEdit edit = contentService
4162: .editResource(reference.getId());
4163: String collectionId = new String(edit.getContent());
4164: CitationCollection oldCollection = getCollection(collectionId);
4165: BasicCitationCollection newCollection = new BasicCitationCollection();
4166: newCollection
4167: .copy((BasicCitationCollection) oldCollection);
4168: save(newCollection);
4169: edit.setContent(newCollection.getId().getBytes());
4170: contentService.commitResource(edit);
4171: } catch (IdUnusedException e) {
4172: M_log.warn("IdUnusedException ", e);
4173: } catch (ServerOverloadException e) {
4174: M_log.warn("ServerOverloadException ", e);
4175: } catch (PermissionException e) {
4176: M_log.warn("PermissionException ", e);
4177: } catch (TypeException e) {
4178: M_log.warn("TypeException ", e);
4179: } catch (InUseException e) {
4180: M_log.warn("InUseException ", e);
4181: } catch (OverQuotaException e) {
4182: M_log.warn("OverQuotaException ", e);
4183: }
4184: }
4185:
4186: }
4187:
4188: /**
4189: * @param schemaId
4190: * @param fieldId
4191: * @return
4192: */
4193: public boolean isMultivalued(String schemaId, String fieldId) {
4194: Schema schema = getSchema(schemaId.toLowerCase());
4195: if (schema == null) {
4196: if (getSynonyms("article").contains(schemaId.toLowerCase())) {
4197: schema = getSchema("article");
4198: } else if (getSynonyms("book").contains(
4199: schemaId.toLowerCase())) {
4200: schema = getSchema("book");
4201: } else if (getSynonyms("chapter").contains(
4202: schemaId.toLowerCase())) {
4203: schema = getSchema("chapter");
4204: } else if (getSynonyms("report").contains(
4205: schemaId.toLowerCase())) {
4206: schema = getSchema("report");
4207: } else {
4208: schema = this .getSchema("unknown");
4209: }
4210: }
4211: Field field = schema.getField(fieldId);
4212: if (field == null) {
4213: return false;
4214: }
4215: return (field.isMultivalued());
4216: }
4217:
4218: /**
4219: * Access a list of all schemas that have been defined (other than the
4220: * "unknown" type).
4221: *
4222: * @return A list of Strings representing the identifiers for known schemas.
4223: */
4224: public List listSchemas() {
4225: Set names = (Set) m_storage.listSchemas();
4226: return new Vector(names);
4227: }
4228:
4229: /*
4230: * (non-Javadoc)
4231: *
4232: * @see org.sakaiproject.entity.api.EntityProducer#merge(java.lang.String,
4233: * org.w3c.dom.Element, java.lang.String, java.lang.String,
4234: * java.util.Map, java.util.Map, java.util.Set)
4235: */
4236: public String merge(String siteId, Element root,
4237: String archivePath, String fromSiteId, Map attachmentNames,
4238: Map userIdTrans, Set userListAllowImport) {
4239: // TODO Auto-generated method stub
4240: return null;
4241: }
4242:
4243: /**
4244: * Construct a Storage object.
4245: *
4246: * @return The new storage object.
4247: */
4248: public abstract Storage newStorage();
4249:
4250: /**
4251: * @return
4252: */
4253: protected Integer nextSerialNumber() {
4254: Integer number;
4255: synchronized (m_nextSerialNumber) {
4256: number = m_nextSerialNumber;
4257: m_nextSerialNumber = new Integer(number.intValue() + 1);
4258: }
4259:
4260: return number;
4261: }
4262:
4263: /*
4264: * (non-Javadoc)
4265: *
4266: * @see org.sakaiproject.entity.api.EntityProducer#parseEntityReference(java.lang.String,
4267: * org.sakaiproject.entity.api.Reference)
4268: */
4269: public boolean parseEntityReference(String reference, Reference ref) {
4270: boolean citationEntity = false;
4271: if (reference.startsWith(CitationService.REFERENCE_ROOT)) {
4272: citationEntity = true;
4273: String[] parts = StringUtil.split(reference,
4274: Entity.SEPARATOR);
4275:
4276: String subType = null;
4277: String context = null;
4278: String id = null;
4279: String container = null;
4280:
4281: // the first part will be null, then next the service, the third
4282: // will be "export_ris", "content" or "list"
4283: if (parts.length > 2) {
4284: subType = parts[2];
4285: if (CitationService.REF_TYPE_EXPORT_RIS_ALL
4286: .equals(subType)
4287: || CitationService.REF_TYPE_EXPORT_RIS_SEL
4288: .equals(subType)) {
4289: context = parts[3];
4290: id = parts[3];
4291: ref.set(APPLICATION_ID, subType, id, container,
4292: context);
4293: } else if ("content".equals(subType)) {
4294: String wrappedRef = reference
4295: .substring(REFERENCE_ROOT.length(),
4296: reference.length());
4297: Reference wrapped = m_entityManager
4298: .newReference(wrappedRef);
4299: ref.set(APPLICATION_ID, REF_TYPE_VIEW_LIST, wrapped
4300: .getId(), wrapped.getContainer(), wrapped
4301: .getContext());
4302: } else {
4303: M_log
4304: .warn(".parseEntityReference(): unknown citation subtype: "
4305: + subType + " in ref: " + reference);
4306: citationEntity = false;
4307: }
4308: } else {
4309: citationEntity = false;
4310: }
4311: }
4312:
4313: return citationEntity;
4314: }
4315:
4316: /*
4317: * (non-Javadoc)
4318: *
4319: * @see org.sakaiproject.citation.api.CitationService#removeCollection(org.sakaiproject.citation.api.CitationCollection)
4320: */
4321: public void removeCollection(CitationCollection edit) {
4322: // TODO Auto-generated method stub
4323:
4324: }
4325:
4326: /*
4327: * (non-Javadoc)
4328: *
4329: * @see org.sakaiproject.citation.api.CitationService#save(org.sakaiproject.citation.api.Citation)
4330: */
4331: public void save(Citation citation) {
4332: if (citation instanceof BasicCitation
4333: && ((BasicCitation) citation).isTemporary()) {
4334: ((BasicCitation) citation).m_id = IdManager.createUuid();
4335: ((BasicCitation) citation).m_temporary = false;
4336: ((BasicCitation) citation).m_serialNumber = null;
4337: }
4338: this .m_storage.saveCitation(citation);
4339: }
4340:
4341: /*
4342: * (non-Javadoc)
4343: *
4344: * @see org.sakaiproject.citation.api.CitationService#save(org.sakaiproject.citation.api.CitationCollection)
4345: */
4346: public void save(CitationCollection collection) {
4347: this .m_storage.saveCollection(collection);
4348: }
4349:
4350: /**
4351: * Dependency: ConfigurationService.
4352: *
4353: * @param service
4354: * The ConfigurationService.
4355: */
4356: public void setConfigurationService(ConfigurationService service) {
4357: m_configService = service;
4358: }
4359:
4360: /**
4361: * Dependency: ContentHostingService.
4362: *
4363: * @param service
4364: * The ContentHostingService.
4365: */
4366: public void setContentHostingService(ContentHostingService service) {
4367: m_contentHostingService = service;
4368: }
4369:
4370: /**
4371: * Dependency: EntityManager.
4372: *
4373: * @param service
4374: * The EntityManager.
4375: */
4376: public void setEntityManager(EntityManager service) {
4377: m_entityManager = service;
4378: }
4379:
4380: /**
4381: * Dependency: ServerConfigurationService.
4382: *
4383: * @param service
4384: * The ServerConfigurationService.
4385: */
4386: public void setServerConfigurationService(
4387: ServerConfigurationService service) {
4388: m_serverConfigurationService = service;
4389: }
4390:
4391: /*
4392: * (non-Javadoc)
4393: *
4394: * @see org.sakaiproject.entity.api.EntityProducer#willArchiveMerge()
4395: */
4396: public boolean willArchiveMerge() {
4397: // TODO Auto-generated method stub
4398: return false;
4399: }
4400:
4401: public final class Counter {
4402: private int value;
4403: private Integer lock = new Integer(0);
4404:
4405: public Counter() {
4406: value = 0;
4407: }
4408:
4409: public Counter(int val) {
4410: value = val;
4411: }
4412:
4413: public void increment() {
4414: synchronized (lock) {
4415: value++;
4416: }
4417: }
4418:
4419: public void decrement() {
4420: synchronized (lock) {
4421: value--;
4422: }
4423: }
4424:
4425: public int intValue() {
4426: return value;
4427: }
4428: }
4429:
4430: /**
4431: * @return the attemptToMatchSchema
4432: */
4433: public boolean isAttemptToMatchSchema() {
4434: return attemptToMatchSchema;
4435: }
4436:
4437: /**
4438: * @param attemptToMatchSchema the attemptToMatchSchema to set
4439: */
4440: public void setAttemptToMatchSchema(boolean attemptToMatchSchema) {
4441: this .attemptToMatchSchema = attemptToMatchSchema;
4442: }
4443:
4444: } // BaseCitationService
|