Source Code Cross Referenced for BaseCitationService.java in  » ERP-CRM-Financial » sakai » org » sakaiproject » citation » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » sakai » org.sakaiproject.citation.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.