Source Code Cross Referenced for DocumentVariantImpl.java in  » Content-Management-System » daisy » org » outerj » daisy » repository » commonimpl » 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 » Content Management System » daisy » org.outerj.daisy.repository.commonimpl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2004 Outerthought bvba and Schaubroeck nv
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *     http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package org.outerj.daisy.repository.commonimpl;
0017:
0018:        import java.util.ArrayList;
0019:        import java.util.Arrays;
0020:        import java.util.Date;
0021:        import java.util.GregorianCalendar;
0022:        import java.util.HashMap;
0023:        import java.util.Iterator;
0024:        import java.util.List;
0025:        import java.util.Map;
0026:
0027:        import org.outerj.daisy.repository.ByteArrayPartDataSource;
0028:        import org.outerj.daisy.repository.ChangeType;
0029:        import org.outerj.daisy.repository.DocumentCollection;
0030:        import org.outerj.daisy.repository.DocumentCollections;
0031:        import org.outerj.daisy.repository.DocumentTypeInconsistencyException;
0032:        import org.outerj.daisy.repository.Field;
0033:        import org.outerj.daisy.repository.FieldNotFoundException;
0034:        import org.outerj.daisy.repository.Fields;
0035:        import org.outerj.daisy.repository.HierarchyPath;
0036:        import org.outerj.daisy.repository.Link;
0037:        import org.outerj.daisy.repository.Links;
0038:        import org.outerj.daisy.repository.LockInfo;
0039:        import org.outerj.daisy.repository.LockType;
0040:        import org.outerj.daisy.repository.Part;
0041:        import org.outerj.daisy.repository.PartDataSource;
0042:        import org.outerj.daisy.repository.PartNotFoundException;
0043:        import org.outerj.daisy.repository.Parts;
0044:        import org.outerj.daisy.repository.RepositoryException;
0045:        import org.outerj.daisy.repository.RepositoryRuntimeException;
0046:        import org.outerj.daisy.repository.ValueType;
0047:        import org.outerj.daisy.repository.VariantKey;
0048:        import org.outerj.daisy.repository.Version;
0049:        import org.outerj.daisy.repository.VersionKey;
0050:        import org.outerj.daisy.repository.VersionNotFoundException;
0051:        import org.outerj.daisy.repository.VersionState;
0052:        import org.outerj.daisy.repository.Versions;
0053:        import org.outerj.daisy.repository.acl.AccessDetails;
0054:        import org.outerj.daisy.repository.acl.AclDetailPermission;
0055:        import org.outerj.daisy.repository.commonimpl.schema.CommonRepositorySchema;
0056:        import org.outerj.daisy.repository.commonimpl.variant.CommonVariantManager;
0057:        import org.outerj.daisy.repository.schema.DocumentType;
0058:        import org.outerj.daisy.repository.schema.FieldType;
0059:        import org.outerj.daisy.repository.schema.FieldTypeUse;
0060:        import org.outerj.daisy.repository.schema.PartType;
0061:        import org.outerj.daisy.repository.schema.PartTypeUse;
0062:        import org.outerx.daisy.x10.DocumentDocument;
0063:
0064:        /**
0065:         * Encapsulates all variant-specific data of a document.
0066:         * An instance of this class is contained by {@link DocumentImpl}.
0067:         */
0068:        public class DocumentVariantImpl {
0069:            private DocumentImpl ownerDocument;
0070:            private DocumentStrategy documentStrategy;
0071:            private CommonRepository repository;
0072:            private AuthenticatedUser currentUser;
0073:            /** The parts mapped by PartType ID. */
0074:            private Map<Long, Part> parts = new HashMap<Long, Part>();
0075:            private boolean partChanges = false;
0076:            private long documentTypeId;
0077:            private boolean documentTypeChanged = false;
0078:            private String name;
0079:            private boolean nameUpdated = false;
0080:            private long branchId;
0081:            private long languageId;
0082:            private boolean isNew;
0083:            private Date lastModified;
0084:            private long lastModifier = -1;
0085:            private boolean retired = false;
0086:            private boolean retiredChanged = false;
0087:            private VersionImpl[] versions;
0088:            /** Cached reference to the live version. */
0089:            private Version liveVersion;
0090:            /** Indicates if the variable liveVersion has been initialiased. */
0091:            private boolean liveVersionLoaded = false;
0092:            /** Cached reference to the last version. */
0093:            private Version lastVersion;
0094:            /** Indicates if the variable lastVersion has been initialiased. */
0095:            private boolean lastVersionLoaded = false;
0096:            private long lastVersionId = -1;
0097:            private long liveVersionId = -1;
0098:            /** The fields mapped by FieldType ID. */
0099:            private Map<Long, Field> fields = new HashMap<Long, Field>();
0100:            private boolean fieldChanges = false;
0101:            private List<Link> links = new ArrayList<Link>(3);
0102:            private boolean linkChanges = false;
0103:            private Map<String, String> customFields = new HashMap<String, String>();
0104:            private boolean customFieldChanges = false;
0105:            private Map<Long, DocumentCollection> documentCollections = new HashMap<Long, DocumentCollection>();
0106:            private boolean documentCollectionChanges = false;
0107:            private LockInfoImpl lockInfo = new LockInfoImpl();
0108:            private VersionState versionState = VersionState.PUBLISH;
0109:            private String summary;
0110:            private long updateCount = 0;
0111:            private IntimateAccess intimateAccess = new IntimateAccess();
0112:            private long createdFromBranchId = -1;
0113:            private long createdFromLanguageId = -1;
0114:            private long createdFromVersionId = -1;
0115:            // the variables below are values we need to store to be able to pass them on
0116:            // from the remote implementation
0117:            private boolean validateOnSave = true;
0118:            private boolean documentTypeChecksEnabled = true;
0119:            private long startBranchId = -1;
0120:            private long startLanguageId = -1;
0121:            private VersionKey syncedWith;
0122:            private ChangeType changeType = ChangeType.MAJOR;
0123:            private String changeComment;
0124:            private long lastMajorChangeVersionId = -1;
0125:            private long liveMajorChangeVersionId = -1;
0126:
0127:            public static final String ERROR_ACCESSING_REPOSITORY_SCHEMA = "Error accessing repository schema information.";
0128:            private static final String READ_ONLY_MESSAGE = "This document object is read-only.";
0129:
0130:            public DocumentVariantImpl(DocumentImpl ownerDocument,
0131:                    DocumentStrategy documentStrategy,
0132:                    CommonRepository repository, AuthenticatedUser currentUser,
0133:                    long documentTypeId, long branchId, long languageId) {
0134:                this .ownerDocument = ownerDocument;
0135:                this .documentStrategy = documentStrategy;
0136:                this .repository = repository;
0137:                this .currentUser = currentUser;
0138:                this .documentTypeId = documentTypeId;
0139:                this .branchId = branchId;
0140:                this .languageId = languageId;
0141:                this .isNew = true;
0142:            }
0143:
0144:            public DocumentVariantImpl.IntimateAccess getIntimateAccess(
0145:                    DocumentStrategy strategy) {
0146:                if (this .documentStrategy == strategy)
0147:                    return intimateAccess;
0148:                return null;
0149:            }
0150:
0151:            public long getBranchId() {
0152:                return branchId;
0153:            }
0154:
0155:            public long getLanguageId() {
0156:                return languageId;
0157:            }
0158:
0159:            public boolean isNew() {
0160:                return isNew;
0161:            }
0162:
0163:            public long getDocumentTypeId() {
0164:                return documentTypeId;
0165:            }
0166:
0167:            public String getDocumentId() {
0168:                return ownerDocument.getId();
0169:            }
0170:
0171:            public long getDocSeqId() {
0172:                return ownerDocument.getSeqId();
0173:            }
0174:
0175:            public String getDocNamespace() {
0176:                return ownerDocument.getNamespace();
0177:            }
0178:
0179:            public VariantKey getKey() {
0180:                if (ownerDocument.isNew())
0181:                    throw new IllegalStateException(
0182:                            "Cannot get variant key: document is new and thus has no ID assigned just yet.");
0183:                return new VariantKey(ownerDocument.getId(), getBranchId(),
0184:                        getLanguageId());
0185:            }
0186:
0187:            public void setValidateOnSave(boolean validateOnSave) {
0188:                this .validateOnSave = validateOnSave;
0189:            }
0190:
0191:            public void changeDocumentType(long documentTypeId)
0192:                    throws RepositoryException {
0193:                if (ownerDocument.isReadOnly())
0194:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0195:
0196:                if (documentTypeId != this .documentTypeId) {
0197:                    // fetch the document type to be sure it exists
0198:                    // the method below will throw an exception if it doesn't exist
0199:                    repository.getRepositorySchema().getDocumentTypeById(
0200:                            documentTypeId, false, currentUser);
0201:
0202:                    this .documentTypeId = documentTypeId;
0203:                    this .documentTypeChanged = true;
0204:                }
0205:            }
0206:
0207:            public void changeDocumentType(String documentTypeName)
0208:                    throws RepositoryException {
0209:                if (ownerDocument.isReadOnly())
0210:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0211:
0212:                DocumentType documentType = repository.getRepositorySchema()
0213:                        .getDocumentTypeByName(documentTypeName, false,
0214:                                currentUser);
0215:                changeDocumentType(documentType.getId());
0216:            }
0217:
0218:            public Field getField(String name) throws FieldNotFoundException {
0219:                FieldType fieldType;
0220:                try {
0221:                    fieldType = repository.getRepositorySchema()
0222:                            .getFieldTypeByName(name, false, currentUser);
0223:                } catch (RepositoryException e) {
0224:                    throw new RuntimeException(
0225:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0226:                }
0227:                return getField(fieldType.getId());
0228:            }
0229:
0230:            public Field getField(long fieldTypeId)
0231:                    throws FieldNotFoundException {
0232:                Field field = fields.get(fieldTypeId);
0233:                if (field == null)
0234:                    throw new FieldNotFoundException(fieldTypeId);
0235:                else
0236:                    return field;
0237:            }
0238:
0239:            public boolean hasField(long fieldTypeId) {
0240:                Field field = fields.get(fieldTypeId);
0241:                return field != null;
0242:            }
0243:
0244:            public boolean hasField(String fieldTypeName) {
0245:                FieldType fieldType;
0246:                try {
0247:                    fieldType = repository.getRepositorySchema()
0248:                            .getFieldTypeByName(fieldTypeName, false,
0249:                                    currentUser);
0250:                } catch (RepositoryException e) {
0251:                    throw new RuntimeException(
0252:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0253:                }
0254:                return hasField(fieldType.getId());
0255:            }
0256:
0257:            public Fields getFields() {
0258:                return new FieldsImpl(fields.values().toArray(new Field[0]));
0259:            }
0260:
0261:            public Fields getFieldsInOrder() {
0262:                return new FieldsImpl(orderFields(fields.values().toArray(
0263:                        new Field[0])));
0264:            }
0265:
0266:            public void setField(String name, Object value)
0267:                    throws DocumentTypeInconsistencyException {
0268:                if (ownerDocument.isReadOnly())
0269:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0270:
0271:                FieldType fieldType;
0272:                try {
0273:                    fieldType = repository.getRepositorySchema()
0274:                            .getFieldTypeByName(name, false, currentUser);
0275:                } catch (RepositoryException e) {
0276:                    throw new RuntimeException(
0277:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0278:                }
0279:                setField(fieldType.getId(), value);
0280:            }
0281:
0282:            public void setField(long fieldTypeId, Object value)
0283:                    throws DocumentTypeInconsistencyException {
0284:                if (ownerDocument.isReadOnly())
0285:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0286:
0287:                if (value == null)
0288:                    throw new NullPointerException(
0289:                            "Field value cannot be null.");
0290:
0291:                DocumentType documentType;
0292:                try {
0293:                    documentType = repository.getRepositorySchema()
0294:                            .getDocumentTypeById(documentTypeId, false,
0295:                                    currentUser);
0296:                } catch (RepositoryException e) {
0297:                    throw new RuntimeException(
0298:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0299:                }
0300:
0301:                FieldType fieldType;
0302:                try {
0303:                    fieldType = repository.getRepositorySchema()
0304:                            .getFieldTypeById(fieldTypeId, false, currentUser);
0305:                } catch (RepositoryException e) {
0306:                    throw new RuntimeException(
0307:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0308:                }
0309:
0310:                if (documentTypeChecksEnabled
0311:                        && !documentType.hasFieldType(fieldTypeId))
0312:                    throw new DocumentTypeInconsistencyException(
0313:                            "The FieldType \"" + fieldType.getName()
0314:                                    + "\" (ID: " + fieldTypeId
0315:                                    + ") is not allowed on this document.");
0316:
0317:                // For multivalue fields, make sure the array is a clone so that it's unmodifiable from the outside
0318:                if (value instanceof  Object[])
0319:                    value = ((Object[]) value).clone();
0320:
0321:                value = checkAndNormalizeFieldValue(fieldType, value);
0322:
0323:                FieldImpl field = (FieldImpl) fields.get(new Long(fieldTypeId));
0324:
0325:                // if the value didn't change, don't update it
0326:                if (field != null
0327:                        && (fieldType.isMultiValue() ? Arrays.equals(
0328:                                (Object[]) field.getValue(), (Object[]) value)
0329:                                : field.getValue().equals(value)))
0330:                    return;
0331:
0332:                field = new FieldImpl(intimateAccess, fieldTypeId, value);
0333:                fields.put(new Long(fieldTypeId), field);
0334:                fieldChanges = true;
0335:            }
0336:
0337:            private Object checkAndNormalizeFieldValue(FieldType fieldType,
0338:                    Object value) throws DocumentTypeInconsistencyException {
0339:                if (fieldType.isMultiValue()) {
0340:                    if (!value.getClass().isArray())
0341:                        throw new DocumentTypeInconsistencyException(
0342:                                "The value for the multivalue-field \""
0343:                                        + fieldType.getName()
0344:                                        + "\" should be an array.");
0345:                    Object[] values = (Object[]) value;
0346:                    if (values.length == 0)
0347:                        throw new DocumentTypeInconsistencyException(
0348:                                "The value supplied for the multivalue field \""
0349:                                        + fieldType.getName()
0350:                                        + "\" is a zero-length array, it should be an array of at least one element.");
0351:                    for (int i = 0; i < values.length; i++) {
0352:                        values[i] = checkAndNormalizeHierarchyValue(fieldType,
0353:                                values[i], i);
0354:                    }
0355:                    return values;
0356:                } else {
0357:                    return checkAndNormalizeHierarchyValue(fieldType, value, -1);
0358:                }
0359:            }
0360:
0361:            private Object checkAndNormalizeHierarchyValue(FieldType fieldType,
0362:                    Object value, int multiValueIndex)
0363:                    throws DocumentTypeInconsistencyException {
0364:                if (fieldType.isHierarchical()) {
0365:                    if (!(value instanceof  HierarchyPath))
0366:                        throw new DocumentTypeInconsistencyException(
0367:                                "The supplied value for hierarchical field \""
0368:                                        + fieldType.getName()
0369:                                        + "\" should be a HierarchyPath object.");
0370:                    HierarchyPath hierarchyPath = (HierarchyPath) value;
0371:                    Object[] values = hierarchyPath.getElements();
0372:                    if (values.length == 0)
0373:                        throw new DocumentTypeInconsistencyException(
0374:                                "The supplied HierarchyPath object for hierarchical field \""
0375:                                        + fieldType.getName()
0376:                                        + "\" should contain at least one element.");
0377:                    for (int i = 0; i < values.length; i++) {
0378:                        values[i] = checkAndNormalizePrimitiveValue(fieldType,
0379:                                values[i], multiValueIndex, i);
0380:                    }
0381:                    return new HierarchyPath(values);
0382:                } else {
0383:                    return checkAndNormalizePrimitiveValue(fieldType, value,
0384:                            multiValueIndex, -1);
0385:                }
0386:            }
0387:
0388:            private Object checkAndNormalizePrimitiveValue(FieldType fieldType,
0389:                    Object value, int multiValueIndex, int hierarchyPathIndex)
0390:                    throws DocumentTypeInconsistencyException {
0391:                ValueType valueType = fieldType.getValueType();
0392:                if (!valueType.getTypeClass()
0393:                        .isAssignableFrom(value.getClass()))
0394:                    throw new DocumentTypeInconsistencyException(
0395:                            "The supplied value for the field \""
0396:                                    + fieldType.getName()
0397:                                    + "\" is not of the correct type. Expected was a "
0398:                                    + valueType.toString()
0399:                                    + " ("
0400:                                    + valueType.getTypeClass().getName()
0401:                                    + ") but got a "
0402:                                    + value.getClass().getName()
0403:                                    + getFieldValuePositionDetails(
0404:                                            multiValueIndex, hierarchyPathIndex));
0405:
0406:                // perform normalization of values for certain value types
0407:                if (valueType == ValueType.DATE
0408:                        || valueType == ValueType.DATETIME) {
0409:                    boolean keepTime = fieldType.getValueType() == ValueType.DATETIME;
0410:                    value = DateUtil.getNormalizedDate((Date) value, keepTime);
0411:                } else if (valueType == ValueType.LINK) {
0412:                    VariantKey variantKey = (VariantKey) value;
0413:                    value = new VariantKey(repository
0414:                            .normalizeDocumentId(variantKey.getDocumentId()),
0415:                            variantKey.getBranchId(), variantKey
0416:                                    .getLanguageId());
0417:                }
0418:
0419:                return value;
0420:            }
0421:
0422:            private String getFieldValuePositionDetails(int multiValueIndex,
0423:                    int hierarchyPathIndex) {
0424:                StringBuilder builder = new StringBuilder();
0425:                if (multiValueIndex != -1 || hierarchyPathIndex != -1)
0426:                    builder.append(" (");
0427:                if (multiValueIndex != -1)
0428:                    builder.append("multi value index: ").append(
0429:                            multiValueIndex);
0430:                if (hierarchyPathIndex != -1) {
0431:                    if (multiValueIndex != -1)
0432:                        builder.append(", ");
0433:                    builder.append("hierarchy path index: ").append(
0434:                            hierarchyPathIndex);
0435:                }
0436:                if (builder.length() > 0)
0437:                    builder.append(")");
0438:                return builder.toString();
0439:            }
0440:
0441:            public void deleteField(String name) {
0442:                if (ownerDocument.isReadOnly())
0443:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0444:
0445:                FieldType fieldType;
0446:                try {
0447:                    fieldType = repository.getRepositorySchema()
0448:                            .getFieldTypeByName(name, false, currentUser);
0449:                } catch (RepositoryException e) {
0450:                    throw new RuntimeException(
0451:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0452:                }
0453:                deleteField(fieldType.getId());
0454:            }
0455:
0456:            public void deleteField(long fieldTypeId) {
0457:                if (ownerDocument.isReadOnly())
0458:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0459:
0460:                Long key = new Long(fieldTypeId);
0461:                if (fields.containsKey(key)) {
0462:                    fields.remove(new Long(fieldTypeId));
0463:                    fieldChanges = true;
0464:                }
0465:            }
0466:
0467:            public LockInfo getLockInfo(boolean fresh)
0468:                    throws RepositoryException {
0469:                LockInfoImpl lockInfo = this .lockInfo;
0470:                if ((fresh || lockInfo == null) && !isNew) {
0471:                    synchronized (this ) {
0472:                        lockInfo = documentStrategy.getLockInfo(this );
0473:                        this .lockInfo = lockInfo;
0474:                    }
0475:                }
0476:                return lockInfo;
0477:            }
0478:
0479:            // This method is by purpose not in the Document interface. It is used to clear lock
0480:            // info in cached document objects. If it would be in the interface, then the method
0481:            // getLockInfo should cover the case where lockInfo is null and id is -1.
0482:            public void clearLockInfo() {
0483:                this .lockInfo = null;
0484:            }
0485:
0486:            public boolean lock(long duration, LockType lockType)
0487:                    throws RepositoryException {
0488:                if (ownerDocument.isReadOnly())
0489:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0490:
0491:                if (isNew)
0492:                    throw new RepositoryException(
0493:                            "Can't take a lock on a new, non-saved document variant.");
0494:
0495:                lockInfo = documentStrategy.lock(this , duration, lockType);
0496:
0497:                if (!lockInfo.hasLock())
0498:                    return false;
0499:
0500:                return lockInfo.getUserId() == currentUser.getId();
0501:            }
0502:
0503:            public boolean releaseLock() throws RepositoryException {
0504:                if (ownerDocument.isReadOnly())
0505:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0506:
0507:                if (isNew)
0508:                    return true;
0509:
0510:                lockInfo = documentStrategy.releaseLock(this );
0511:                return !lockInfo.hasLock();
0512:            }
0513:
0514:            public void addXml(DocumentDocument.Document documentXml,
0515:                    AccessDetails accessDetails) throws RepositoryException {
0516:                addNonVersionedDataToXml(documentXml, accessDetails);
0517:
0518:                documentXml.setDataVersionId(-1); // -1 indicates "current data in object, whether it's saved or not"
0519:                documentXml.setName(name);
0520:                documentXml
0521:                        .setFields(VersionedDataAccessWrapper.filterFields(
0522:                                getFieldsInOrder(), accessDetails).getXml()
0523:                                .getFields());
0524:                documentXml.setParts(VersionedDataAccessWrapper.filterParts(
0525:                        getPartsInOrder(), accessDetails).getXml().getParts());
0526:                documentXml.setLinks(getLinks().getXml().getLinks());
0527:                documentXml.setValidateOnSave(validateOnSave);
0528:            }
0529:
0530:            public void addXml(DocumentDocument.Document documentXml,
0531:                    long versionId, AccessDetails accessDetails)
0532:                    throws RepositoryException {
0533:                Version version = getVersion(versionId);
0534:
0535:                addNonVersionedDataToXml(documentXml, accessDetails);
0536:                documentXml.setDataVersionId(versionId);
0537:                documentXml.setName(version.getDocumentName());
0538:                documentXml.setFields(VersionedDataAccessWrapper.filterFields(
0539:                        version.getFieldsInOrder(), accessDetails).getXml()
0540:                        .getFields());
0541:                documentXml.setParts(VersionedDataAccessWrapper.filterParts(
0542:                        version.getPartsInOrder(), accessDetails).getXml()
0543:                        .getParts());
0544:                documentXml.setLinks(version.getLinks().getXml().getLinks());
0545:            }
0546:
0547:            public void addNonVersionedDataToXml(
0548:                    DocumentDocument.Document documentXml,
0549:                    AccessDetails accessDetails) {
0550:                if (!isNew) {
0551:                    GregorianCalendar lastModified = new GregorianCalendar();
0552:                    lastModified.setTime(this .lastModified);
0553:                    documentXml.setVariantLastModified(lastModified);
0554:                    documentXml.setVariantLastModifier(lastModifier);
0555:                    if (liveVersionId != -1)
0556:                        documentXml.setLiveVersionId(liveVersionId);
0557:                }
0558:
0559:                documentXml.setBranchId(branchId);
0560:                documentXml.setLanguageId(languageId);
0561:                documentXml.setTypeId(documentTypeId);
0562:                documentXml.setLastVersionId(lastVersionId);
0563:                documentXml.setRetired(retired);
0564:                documentXml
0565:                        .setNewVersionState(DocumentDocument.Document.NewVersionState.Enum
0566:                                .forString(versionState.toString()));
0567:                if (syncedWith != null) {
0568:                    documentXml.setNewSyncedWithLanguageId(syncedWith
0569:                            .getLanguageId());
0570:                    documentXml.setNewSyncedWithVersionId(syncedWith
0571:                            .getVersionId());
0572:                }
0573:                documentXml
0574:                        .setNewChangeType(DocumentDocument.Document.NewChangeType.Enum
0575:                                .forString(changeType.toString()));
0576:                documentXml.setNewChangeComment(changeComment);
0577:                documentXml.setVariantUpdateCount(updateCount);
0578:                if ((accessDetails == null || accessDetails
0579:                        .isGranted(AclDetailPermission.SUMMARY))
0580:                        && summary != null)
0581:                    documentXml.setSummary(summary);
0582:                documentXml.setCreatedFromBranchId(createdFromBranchId);
0583:                documentXml.setCreatedFromLanguageId(createdFromLanguageId);
0584:                documentXml.setCreatedFromVersionId(createdFromVersionId);
0585:                documentXml
0586:                        .setDocumentTypeChecksEnabled(documentTypeChecksEnabled);
0587:                documentXml
0588:                        .setLastMajorChangeVersionId(lastMajorChangeVersionId);
0589:                documentXml
0590:                        .setLiveMajorChangeVersionId(liveMajorChangeVersionId);
0591:
0592:                DocumentDocument.Document.CustomFields customFieldsXml = documentXml
0593:                        .addNewCustomFields();
0594:                for (Map.Entry<String, String> customField : customFields
0595:                        .entrySet()) {
0596:                    DocumentDocument.Document.CustomFields.CustomField customFieldXml = customFieldsXml
0597:                            .addNewCustomField();
0598:                    customFieldXml.setName(customField.getKey());
0599:                    customFieldXml.setValue(customField.getValue());
0600:                }
0601:
0602:                LockInfo lockInfo;
0603:                try {
0604:                    lockInfo = getLockInfo(false);
0605:                } catch (RepositoryException e) {
0606:                    throw new RuntimeException(e);
0607:                }
0608:                documentXml.setLockInfo(lockInfo.getXml().getLockInfo());
0609:
0610:                long[] collectionIds = new long[documentCollections.size()];
0611:                Iterator collectionsIt = documentCollections.values()
0612:                        .iterator();
0613:                int i = 0;
0614:                while (collectionsIt.hasNext()) {
0615:                    DocumentCollection collection = (DocumentCollection) collectionsIt
0616:                            .next();
0617:                    collectionIds[i] = collection.getId();
0618:                    i++;
0619:                }
0620:                documentXml.addNewCollectionIds().setCollectionIdArray(
0621:                        collectionIds);
0622:            }
0623:
0624:            public void setName(String name) {
0625:                if (ownerDocument.isReadOnly())
0626:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0627:
0628:                if (name == null)
0629:                    throw new NullPointerException("name may not be null.");
0630:
0631:                if (!name.equals(this .name)) {
0632:                    this .name = name;
0633:                    nameUpdated = true;
0634:                }
0635:            }
0636:
0637:            public String getName() {
0638:                return name;
0639:            }
0640:
0641:            public void setPart(String partTypeName, String mimeType,
0642:                    byte[] data) throws DocumentTypeInconsistencyException {
0643:                if (ownerDocument.isReadOnly())
0644:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0645:
0646:                if (data == null)
0647:                    throw new NullPointerException(
0648:                            "data argument cannot be null.");
0649:
0650:                setPart(partTypeName, mimeType, new ByteArrayPartDataSource(
0651:                        data));
0652:
0653:            }
0654:
0655:            public void setPart(long partTypeId, String mimeType, byte[] data)
0656:                    throws DocumentTypeInconsistencyException {
0657:                if (ownerDocument.isReadOnly())
0658:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0659:
0660:                if (data == null)
0661:                    throw new NullPointerException(
0662:                            "data argument cannot be null.");
0663:
0664:                setPart(partTypeId, mimeType, new ByteArrayPartDataSource(data));
0665:            }
0666:
0667:            public void setPart(String partTypeName, String mimeType,
0668:                    PartDataSource partDataSource)
0669:                    throws DocumentTypeInconsistencyException {
0670:                if (ownerDocument.isReadOnly())
0671:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0672:
0673:                PartType partType;
0674:                try {
0675:                    partType = repository
0676:                            .getRepositorySchema()
0677:                            .getPartTypeByName(partTypeName, false, currentUser);
0678:                } catch (RepositoryException e) {
0679:                    throw new RuntimeException(
0680:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0681:                }
0682:
0683:                setPart(partType.getId(), mimeType, partDataSource);
0684:            }
0685:
0686:            public void setPart(long partTypeId, String mimeType,
0687:                    PartDataSource partDataSource)
0688:                    throws DocumentTypeInconsistencyException {
0689:                if (ownerDocument.isReadOnly())
0690:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0691:
0692:                // first check with the DocumentType if this part is allowed
0693:                DocumentType documentType;
0694:                try {
0695:                    documentType = repository.getRepositorySchema()
0696:                            .getDocumentTypeById(documentTypeId, false,
0697:                                    currentUser);
0698:                } catch (RepositoryException e) {
0699:                    throw new RuntimeException(
0700:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0701:                }
0702:
0703:                PartType partType;
0704:                try {
0705:                    partType = repository.getRepositorySchema()
0706:                            .getPartTypeById(partTypeId, false, currentUser);
0707:                } catch (RepositoryException e) {
0708:                    throw new RuntimeException(
0709:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0710:                }
0711:
0712:                if (mimeType == null || mimeType.length() == 0)
0713:                    throw new NullPointerException(
0714:                            "mimeType argument cannot be null or an empty string");
0715:
0716:                if (partDataSource == null)
0717:                    throw new NullPointerException(
0718:                            "partDataSource argument cannot be null.");
0719:
0720:                if (documentTypeChecksEnabled
0721:                        && !documentType.hasPartType(partTypeId))
0722:                    throw new DocumentTypeInconsistencyException(
0723:                            "The PartType \"" + partType.getName() + "\" (ID: "
0724:                                    + partTypeId
0725:                                    + ") is not allowed on this document.");
0726:
0727:                if (documentTypeChecksEnabled
0728:                        && !partType.mimeTypeAllowed(mimeType))
0729:                    throw new DocumentTypeInconsistencyException(
0730:                            "The mime-type \""
0731:                                    + mimeType
0732:                                    + "\" isn't part of the allowed mime types ("
0733:                                    + partType.getMimeTypes()
0734:                                    + ") required by the PartType \""
0735:                                    + partType.getName() + "\" (ID: "
0736:                                    + partTypeId + ").");
0737:
0738:                PartImpl part = new PartImpl(intimateAccess, partTypeId,
0739:                        lastVersionId, -1);
0740:                PartImpl.IntimateAccess partInt = part
0741:                        .getIntimateAccess(documentStrategy);
0742:                partInt.setMimeType(mimeType);
0743:                partInt.setData(partDataSource);
0744:                partInt.setNewOrUpdated(true, true);
0745:
0746:                parts.put(new Long(partTypeId), part);
0747:                partChanges = true;
0748:            }
0749:
0750:            public void setPartFileName(String partTypeName, String fileName) {
0751:                if (ownerDocument.isReadOnly())
0752:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0753:
0754:                PartType partType;
0755:                try {
0756:                    partType = repository
0757:                            .getRepositorySchema()
0758:                            .getPartTypeByName(partTypeName, false, currentUser);
0759:                } catch (RepositoryException e) {
0760:                    throw new RuntimeException(
0761:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0762:                }
0763:
0764:                setPartFileName(partType.getId(), fileName);
0765:            }
0766:
0767:            public void setPartFileName(long partTypeId, String fileName) {
0768:                if (ownerDocument.isReadOnly())
0769:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0770:
0771:                PartImpl part = (PartImpl) parts.get(new Long(partTypeId));
0772:                if (part == null)
0773:                    throw new RepositoryRuntimeException(
0774:                            "The document does not have a part for part type ID "
0775:                                    + partTypeId);
0776:
0777:                if ((part.getFileName() == null && fileName == null)
0778:                        || (part.getFileName() != null && part.getFileName()
0779:                                .equals(fileName)))
0780:                    return;
0781:
0782:                PartImpl.IntimateAccess partInt = part
0783:                        .getIntimateAccess(documentStrategy);
0784:                partInt.setFileName(fileName);
0785:                partInt.setNewOrUpdated(true, partInt.isDataUpdated());
0786:                partChanges = true;
0787:            }
0788:
0789:            public void setPartMimeType(String partTypeName, String mimeType) {
0790:                if (ownerDocument.isReadOnly())
0791:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0792:
0793:                PartType partType;
0794:                try {
0795:                    partType = repository
0796:                            .getRepositorySchema()
0797:                            .getPartTypeByName(partTypeName, false, currentUser);
0798:                } catch (RepositoryException e) {
0799:                    throw new RuntimeException(
0800:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0801:                }
0802:
0803:                setPartMimeType(partType.getId(), mimeType);
0804:            }
0805:
0806:            public void setPartMimeType(long partTypeId, String mimeType) {
0807:                if (ownerDocument.isReadOnly())
0808:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0809:
0810:                if (mimeType == null)
0811:                    throw new IllegalArgumentException(
0812:                            "Part mime-type cannot be set to null value.");
0813:
0814:                PartImpl part = (PartImpl) parts.get(new Long(partTypeId));
0815:                if (part == null)
0816:                    throw new RepositoryRuntimeException(
0817:                            "The document does not have a part for part type ID "
0818:                                    + partTypeId);
0819:
0820:                if (part.getMimeType().equals(mimeType))
0821:                    return;
0822:
0823:                PartImpl.IntimateAccess partInt = part
0824:                        .getIntimateAccess(documentStrategy);
0825:                partInt.setMimeType(mimeType);
0826:                partInt.setNewOrUpdated(true, partInt.isDataUpdated());
0827:                partChanges = true;
0828:            }
0829:
0830:            public Parts getParts() {
0831:                return new PartsImpl(parts.values().toArray(new Part[0]));
0832:            }
0833:
0834:            public Parts getPartsInOrder() {
0835:                return new PartsImpl(orderParts(parts.values().toArray(
0836:                        new Part[0])));
0837:            }
0838:
0839:            private Part[] orderParts(Part[] parts) {
0840:                Part[] resultList = new Part[parts.length];
0841:                boolean[] handled = new boolean[parts.length];
0842:
0843:                DocumentType documentType;
0844:                try {
0845:                    documentType = repository.getRepositorySchema()
0846:                            .getDocumentTypeById(documentTypeId, false,
0847:                                    currentUser);
0848:                } catch (RepositoryException e) {
0849:                    throw new RuntimeException(
0850:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0851:                }
0852:                PartTypeUse[] partTypeUses = documentType.getPartTypeUses();
0853:
0854:                int resultListPos = -1;
0855:                for (PartTypeUse partTypeUse : partTypeUses) {
0856:                    long id = partTypeUse.getPartType().getId();
0857:                    for (int k = 0; k < parts.length; k++) {
0858:                        if (parts[k].getTypeId() == id) {
0859:                            handled[k] = true;
0860:                            resultListPos++;
0861:                            resultList[resultListPos] = parts[k];
0862:                            break;
0863:                        }
0864:                    }
0865:                }
0866:
0867:                for (int i = 0; i < handled.length; i++) {
0868:                    if (!handled[i]) {
0869:                        resultListPos++;
0870:                        resultList[resultListPos] = parts[i];
0871:                    }
0872:                }
0873:
0874:                return resultList;
0875:            }
0876:
0877:            private Field[] orderFields(Field[] fields) {
0878:                Field[] resultList = new Field[fields.length];
0879:                boolean[] handled = new boolean[fields.length];
0880:
0881:                DocumentType documentType;
0882:                try {
0883:                    documentType = repository.getRepositorySchema()
0884:                            .getDocumentTypeById(documentTypeId, false,
0885:                                    currentUser);
0886:                } catch (RepositoryException e) {
0887:                    throw new RuntimeException(
0888:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0889:                }
0890:                FieldTypeUse[] fieldTypeUses = documentType.getFieldTypeUses();
0891:
0892:                int resultListPos = -1;
0893:                for (FieldTypeUse fieldTypeUse : fieldTypeUses) {
0894:                    long id = fieldTypeUse.getFieldType().getId();
0895:                    for (int k = 0; k < fields.length; k++) {
0896:                        if (fields[k].getTypeId() == id) {
0897:                            handled[k] = true;
0898:                            resultListPos++;
0899:                            resultList[resultListPos] = fields[k];
0900:                            break;
0901:                        }
0902:                    }
0903:                }
0904:
0905:                for (int i = 0; i < handled.length; i++) {
0906:                    if (!handled[i]) {
0907:                        resultListPos++;
0908:                        resultList[resultListPos] = fields[i];
0909:                    }
0910:                }
0911:
0912:                return resultList;
0913:            }
0914:
0915:            public void deletePart(long partTypeId) {
0916:                if (ownerDocument.isReadOnly())
0917:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0918:
0919:                Long key = new Long(partTypeId);
0920:                if (parts.containsKey(key)) {
0921:                    parts.remove(key);
0922:                    partChanges = true;
0923:                }
0924:            }
0925:
0926:            public void deletePart(String name) {
0927:                if (ownerDocument.isReadOnly())
0928:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0929:
0930:                PartType partType;
0931:                try {
0932:                    partType = repository.getRepositorySchema()
0933:                            .getPartTypeByName(name, false, currentUser);
0934:                } catch (RepositoryException e) {
0935:                    throw new RuntimeException(
0936:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0937:                }
0938:                deletePart(partType.getId());
0939:            }
0940:
0941:            public Part getPart(long partTypeId) throws PartNotFoundException {
0942:                Part part = parts.get(new Long(partTypeId));
0943:                if (part == null)
0944:                    throw new PartNotFoundException(partTypeId);
0945:                else
0946:                    return part;
0947:            }
0948:
0949:            public Part getPart(String name) throws PartNotFoundException {
0950:                PartType partType;
0951:                try {
0952:                    partType = repository.getRepositorySchema()
0953:                            .getPartTypeByName(name, false, currentUser);
0954:                } catch (RepositoryException e) {
0955:                    throw new RuntimeException(
0956:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0957:                }
0958:                return getPart(partType.getId());
0959:            }
0960:
0961:            public boolean hasPart(long partTypeId) {
0962:                Part part = parts.get(new Long(partTypeId));
0963:                return part != null;
0964:            }
0965:
0966:            public boolean hasPart(String name) {
0967:                PartType partType;
0968:                try {
0969:                    partType = repository.getRepositorySchema()
0970:                            .getPartTypeByName(name, false, currentUser);
0971:                } catch (RepositoryException e) {
0972:                    throw new RuntimeException(
0973:                            ERROR_ACCESSING_REPOSITORY_SCHEMA, e);
0974:                }
0975:                return hasPart(partType.getId());
0976:            }
0977:
0978:            public void setCustomField(String name, String value) {
0979:                if (ownerDocument.isReadOnly())
0980:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0981:
0982:                if (name == null)
0983:                    throw new RuntimeException("name argument cannot be null.");
0984:                if (value == null)
0985:                    throw new RuntimeException("value argument cannot be null.");
0986:
0987:                customFields.put(name, value);
0988:                customFieldChanges = true;
0989:            }
0990:
0991:            public void deleteCustomField(String name) {
0992:                if (ownerDocument.isReadOnly())
0993:                    throw new RuntimeException(READ_ONLY_MESSAGE);
0994:
0995:                if (name == null)
0996:                    throw new RuntimeException("name argument cannot be null.");
0997:
0998:                customFields.remove(name);
0999:                customFieldChanges = true;
1000:            }
1001:
1002:            public void clearCustomFields() {
1003:                if (ownerDocument.isReadOnly())
1004:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1005:
1006:                customFields.clear();
1007:                customFieldChanges = true;
1008:            }
1009:
1010:            public void clearCollections() {
1011:                if (ownerDocument.isReadOnly())
1012:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1013:
1014:                documentCollections.clear();
1015:                documentCollectionChanges = true;
1016:            }
1017:
1018:            public Map<String, String> getCustomFields() {
1019:                return new HashMap<String, String>(customFields);
1020:            }
1021:
1022:            public String getCustomField(String name) {
1023:                if (name == null)
1024:                    throw new NullPointerException(
1025:                            "name argument cannot be null.");
1026:
1027:                return customFields.get(name);
1028:            }
1029:
1030:            public boolean hasCustomField(String name) {
1031:                if (name == null)
1032:                    throw new NullPointerException(
1033:                            "name argument cannot be null.");
1034:
1035:                return customFields.containsKey(name);
1036:            }
1037:
1038:            public Links getLinks() {
1039:                return new LinksImpl(links.toArray(new Link[links.size()]));
1040:            }
1041:
1042:            public void addLink(String title, String target) {
1043:                if (ownerDocument.isReadOnly())
1044:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1045:
1046:                links.add(new LinkImpl(title, target));
1047:                linkChanges = true;
1048:            }
1049:
1050:            public void deleteLink(int index) {
1051:                if (ownerDocument.isReadOnly())
1052:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1053:
1054:                links.remove(index);
1055:                linkChanges = true;
1056:            }
1057:
1058:            public void clearLinks() {
1059:                if (ownerDocument.isReadOnly())
1060:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1061:
1062:                links.clear();
1063:                linkChanges = true;
1064:            }
1065:
1066:            public void validate() throws DocumentTypeInconsistencyException {
1067:                fullConsistencyCheck();
1068:            }
1069:
1070:            public void setNewVersionState(VersionState versionState) {
1071:                if (ownerDocument.isReadOnly())
1072:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1073:
1074:                if (versionState == null)
1075:                    throw new NullPointerException(
1076:                            "versionState argument cannot be null.");
1077:
1078:                this .versionState = versionState;
1079:            }
1080:
1081:            public VersionState getNewVersionState() {
1082:                return versionState;
1083:            }
1084:
1085:            public synchronized Version getVersion(long versionId)
1086:                    throws RepositoryException {
1087:                if (isNew)
1088:                    throw new RepositoryException(
1089:                            "A new document variant has no versions.");
1090:                if (versionId < 1 || versionId > lastVersionId)
1091:                    throw new VersionNotFoundException(String
1092:                            .valueOf(versionId), ownerDocument.getId(), String
1093:                            .valueOf(branchId), String.valueOf(languageId));
1094:
1095:                checkVersionsArray();
1096:
1097:                int arrayPos = (int) versionId - 1;
1098:                if (versions[arrayPos] == null) {
1099:                    versions[arrayPos] = documentStrategy.loadVersion(this ,
1100:                            versionId);
1101:                }
1102:
1103:                return versions[arrayPos];
1104:            }
1105:
1106:            public Version getLastVersion() throws RepositoryException {
1107:                if (isNew)
1108:                    return null;
1109:
1110:                if (lastVersionLoaded)
1111:                    return lastVersion;
1112:
1113:                Version[] versions = getVersions().getArray();
1114:                lastVersion = versions[versions.length - 1];
1115:                lastVersionLoaded = true;
1116:                return lastVersion;
1117:            }
1118:
1119:            public Version getLiveVersion() throws RepositoryException {
1120:                if (isNew || liveVersionId == -1)
1121:                    return null;
1122:
1123:                if (liveVersionLoaded)
1124:                    return liveVersion;
1125:
1126:                checkVersionsArray();
1127:                int liveVersionPos = (int) liveVersionId - 1; // position in the versions array
1128:                if (versions[(int) liveVersionId - 1] != null) {
1129:                    liveVersion = versions[liveVersionPos];
1130:                } else {
1131:                    VersionImpl newLiveVersion = documentStrategy.loadVersion(
1132:                            this , liveVersionId);
1133:                    versions[liveVersionPos] = newLiveVersion;
1134:                    liveVersion = newLiveVersion;
1135:                }
1136:                liveVersionLoaded = true;
1137:                return liveVersion;
1138:            }
1139:
1140:            public long getLiveVersionId() {
1141:                return liveVersionId;
1142:            }
1143:
1144:            public synchronized Versions getVersions()
1145:                    throws RepositoryException {
1146:                if (isNew)
1147:                    return new VersionsImpl(new Version[0]);
1148:
1149:                loadVersions();
1150:
1151:                return new VersionsImpl(versions.clone());
1152:            }
1153:
1154:            private void loadVersions() throws RepositoryException {
1155:                checkVersionsArray();
1156:
1157:                VersionImpl[] loadedVersions = null;
1158:
1159:                // check if all versions are loaded, if not load them
1160:                // note that we don't simply replace the whole version array because some
1161:                // versions may already be loaded fully, and otherwise that work would be lost.
1162:                for (int i = 0; i < versions.length; i++) {
1163:                    if (versions[i] == null) {
1164:                        if (loadedVersions == null)
1165:                            loadedVersions = documentStrategy
1166:                                    .loadShallowVersions(this );
1167:                        versions[i] = loadedVersions[i];
1168:                    }
1169:                }
1170:            }
1171:
1172:            public long getLastVersionId() {
1173:                return lastVersionId;
1174:            }
1175:
1176:            private void checkVersionsArray() {
1177:                if (versions == null) {
1178:                    versions = new VersionImpl[(int) lastVersionId];
1179:                } else if (versions.length != lastVersionId) {
1180:                    VersionImpl[] oldVersions = versions;
1181:                    versions = new VersionImpl[(int) lastVersionId];
1182:                    System.arraycopy(oldVersions, 0, versions, 0,
1183:                            oldVersions.length);
1184:                }
1185:            }
1186:
1187:            private void fullConsistencyCheck()
1188:                    throws DocumentTypeInconsistencyException {
1189:                DocumentType documentType;
1190:                try {
1191:                    documentType = repository.getRepositorySchema()
1192:                            .getDocumentTypeById(documentTypeId, false,
1193:                                    currentUser);
1194:                } catch (RepositoryException e) {
1195:                    throw new RuntimeException(
1196:                            ERROR_ACCESSING_REPOSITORY_SCHEMA);
1197:                }
1198:
1199:                // check the parts
1200:                PartTypeUse[] partTypeUses = documentType.getPartTypeUses();
1201:                boolean[] hasPartType = new boolean[partTypeUses.length];
1202:
1203:                Part[] parts = getParts().getArray();
1204:                for (Part part : parts) {
1205:                    long partTypeId = part.getTypeId();
1206:                    int partTypeIndex = -1;
1207:                    for (int j = 0; j < partTypeUses.length; j++) {
1208:                        if (partTypeUses[j].getPartType().getId() == partTypeId) {
1209:                            partTypeIndex = j;
1210:                        }
1211:                    }
1212:                    if (partTypeIndex == -1)
1213:                        throw new DocumentTypeInconsistencyException(
1214:                                "The document contains a not-allowed part (PartType ID: "
1215:                                        + partTypeId + ").");
1216:                    hasPartType[partTypeIndex] = true;
1217:                    if (!partTypeUses[partTypeIndex].getPartType()
1218:                            .mimeTypeAllowed(part.getMimeType()))
1219:                        throw new DocumentTypeInconsistencyException(
1220:                                "The mime-type for the part \""
1221:                                        + partTypeUses[partTypeIndex]
1222:                                                .getPartType().getName()
1223:                                        + "\" isn't part of the allowed mime types (PartType ID: "
1224:                                        + partTypeId + ").");
1225:                }
1226:
1227:                for (int i = 0; i < partTypeUses.length; i++) {
1228:                    if (partTypeUses[i].isRequired() && !hasPartType[i])
1229:                        throw new DocumentTypeInconsistencyException(
1230:                                "The document doesn't have the required part \""
1231:                                        + partTypeUses[i].getPartType()
1232:                                                .getName() + "\" (ID: "
1233:                                        + partTypeUses[i].getPartType().getId()
1234:                                        + ").");
1235:                }
1236:
1237:                // check the fields
1238:                FieldTypeUse[] fieldTypeUses = documentType.getFieldTypeUses();
1239:                boolean[] hasFieldType = new boolean[fieldTypeUses.length];
1240:
1241:                Field[] fields = getFields().getArray();
1242:                for (Field field : fields) {
1243:                    long fieldTypeId = field.getTypeId();
1244:                    int fieldTypeIndex = -1;
1245:                    for (int j = 0; j < fieldTypeUses.length; j++) {
1246:                        if (fieldTypeUses[j].getFieldType().getId() == fieldTypeId) {
1247:                            fieldTypeIndex = j;
1248:                        }
1249:                    }
1250:                    if (fieldTypeIndex == -1)
1251:                        throw new DocumentTypeInconsistencyException(
1252:                                "The document contains a not-allowed field (FieldType ID: "
1253:                                        + fieldTypeId + ").");
1254:                    hasFieldType[fieldTypeIndex] = true;
1255:                }
1256:
1257:                for (int i = 0; i < fieldTypeUses.length; i++) {
1258:                    if (fieldTypeUses[i].isRequired() && !hasFieldType[i])
1259:                        throw new DocumentTypeInconsistencyException(
1260:                                "The document doesn't have the required field \""
1261:                                        + fieldTypeUses[i].getFieldType()
1262:                                                .getName()
1263:                                        + "\" (ID: "
1264:                                        + fieldTypeUses[i].getFieldType()
1265:                                                .getId() + ").");
1266:                }
1267:            }
1268:
1269:            public Date getLastModified() {
1270:                if (lastModified != null)
1271:                    return (Date) lastModified.clone();
1272:                else
1273:                    return lastModified;
1274:            }
1275:
1276:            public long getLastModifier() {
1277:                return lastModifier;
1278:            }
1279:
1280:            public boolean isRetired() {
1281:                return retired;
1282:            }
1283:
1284:            public void setRetired(boolean retired) {
1285:                if (ownerDocument.isReadOnly())
1286:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1287:
1288:                if (retired != this .retired) {
1289:                    this .retired = retired;
1290:                    this .retiredChanged = true;
1291:                }
1292:            }
1293:
1294:            public DocumentCollections getCollections() {
1295:                return new DocumentCollectionsImpl(documentCollections.values()
1296:                        .toArray(new DocumentCollection[0]));
1297:            }
1298:
1299:            public boolean inCollection(DocumentCollection collection) {
1300:                return documentCollections.containsKey(new Long(collection
1301:                        .getId()));
1302:            }
1303:
1304:            public boolean inCollection(long collectionId) {
1305:                return documentCollections.containsKey(new Long(collectionId));
1306:            }
1307:
1308:            public void addToCollection(DocumentCollection c) {
1309:                if (ownerDocument.isReadOnly())
1310:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1311:
1312:                if (c.getId() == -1)
1313:                    throw new IllegalArgumentException(
1314:                            "The specified collection has not yet been saved.");
1315:
1316:                this .documentCollectionChanges = true;
1317:                this .documentCollections.put(new Long(c.getId()), c);
1318:            }
1319:
1320:            public void removeFromCollection(DocumentCollection c) {
1321:                if (ownerDocument.isReadOnly())
1322:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1323:
1324:                this .documentCollectionChanges = true;
1325:                documentCollections.remove(new Long(c.getId()));
1326:            }
1327:
1328:            public String getSummary() {
1329:                return summary == null ? "" : summary;
1330:            }
1331:
1332:            public long getLastMajorChangeVersionId() {
1333:                return lastMajorChangeVersionId;
1334:            }
1335:
1336:            public long getLiveMajorChangeVersionId() {
1337:                return liveMajorChangeVersionId;
1338:            }
1339:
1340:            public long getUpdateCount() {
1341:                return updateCount;
1342:            }
1343:
1344:            public long getCreatedFromBranchId() {
1345:                return createdFromBranchId;
1346:            }
1347:
1348:            public long getCreatedFromLanguageId() {
1349:                return createdFromLanguageId;
1350:            }
1351:
1352:            public long getCreatedFromVersionId() {
1353:                return createdFromVersionId;
1354:            }
1355:
1356:            public void setDocumentTypeChecksEnabled(
1357:                    boolean documentTypeChecksEnabled) {
1358:                if (ownerDocument.isReadOnly())
1359:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1360:
1361:                this .documentTypeChecksEnabled = documentTypeChecksEnabled;
1362:            }
1363:
1364:            public void setNewSyncedWithVersion(long syncedWithLanguageId,
1365:                    long syncedWithVersionId) throws RepositoryException {
1366:                if (ownerDocument.isReadOnly())
1367:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1368:
1369:                // NOTE: similar code to VersionImpl.setSyncedWithVersion
1370:
1371:                if (syncedWithLanguageId == -1 || syncedWithVersionId == -1) {
1372:                    if (syncedWithLanguageId != -1 || syncedWithVersionId != -1)
1373:                        throw new IllegalArgumentException(
1374:                                "The languageId and versionId arguments should both be -1 or not be -1 at all.");
1375:
1376:                    syncedWith = null;
1377:                    return;
1378:                }
1379:
1380:                if (syncedWithLanguageId == this .languageId) {
1381:                    throw new IllegalArgumentException(
1382:                            "You can not make a document synced with a version in the same language");
1383:                }
1384:
1385:                // Check the language exists
1386:                repository.getVariantManager().getLanguage(languageId, false,
1387:                        currentUser);
1388:
1389:                syncedWith = new VersionKey(this .getDocumentId(), branchId,
1390:                        syncedWithLanguageId, syncedWithVersionId);
1391:            }
1392:
1393:            public VersionKey getNewSyncedWith() {
1394:                return syncedWith;
1395:            }
1396:
1397:            public void setNewChangeType(ChangeType changeType) {
1398:                if (ownerDocument.isReadOnly())
1399:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1400:
1401:                if (changeType == null)
1402:                    throw new IllegalArgumentException(
1403:                            "Null argument: changeType");
1404:
1405:                this .changeType = changeType;
1406:            }
1407:
1408:            public ChangeType getNewChangeType() {
1409:                return changeType;
1410:            }
1411:
1412:            public void setNewChangeComment(String changeComment) {
1413:                if (ownerDocument.isReadOnly())
1414:                    throw new RuntimeException(READ_ONLY_MESSAGE);
1415:
1416:                if (changeComment != null) {
1417:                    changeComment = changeComment.trim();
1418:                    if (changeComment.length() == 0)
1419:                        changeComment = null;
1420:                }
1421:
1422:                this .changeComment = changeComment;
1423:            }
1424:
1425:            public String getNewChangeComment() {
1426:                return changeComment;
1427:            }
1428:
1429:            /**
1430:             * Checks whether this document needs a new version. This is the case when:
1431:             */
1432:            public boolean needsNewVersion() {
1433:                // a new document always needs an initial version
1434:                if (isNew)
1435:                    return true;
1436:
1437:                return nameUpdated || fieldChanges || linkChanges
1438:                        || partChanges;
1439:            }
1440:
1441:            public boolean needsSaving() {
1442:                boolean nonVersionedChanges = documentCollectionChanges
1443:                        || customFieldChanges || documentTypeChanged
1444:                        || retiredChanged;
1445:                if (nonVersionedChanges)
1446:                    return true;
1447:                else
1448:                    return needsNewVersion();
1449:            }
1450:
1451:            public class IntimateAccess {
1452:
1453:                private IntimateAccess() {
1454:                }
1455:
1456:                public void setLockInfo(LockInfoImpl lockInfo) {
1457:                    DocumentVariantImpl.this .lockInfo = lockInfo;
1458:                }
1459:
1460:                public long getLastVersionId() {
1461:                    return lastVersionId;
1462:                }
1463:
1464:                public boolean hasCustomFieldChanges() {
1465:                    return customFieldChanges;
1466:                }
1467:
1468:                public void setIsNew(boolean isNew) {
1469:                    DocumentVariantImpl.this .isNew = isNew;
1470:                }
1471:
1472:                public boolean isNameUpdated() {
1473:                    return nameUpdated;
1474:                }
1475:
1476:                public boolean hasFieldChanges() {
1477:                    return fieldChanges;
1478:                }
1479:
1480:                public boolean hasLinkChanges() {
1481:                    return linkChanges;
1482:                }
1483:
1484:                public boolean hasPartChanges() {
1485:                    return partChanges;
1486:                }
1487:
1488:                public boolean hasCollectionChanges() {
1489:                    return documentCollectionChanges;
1490:                }
1491:
1492:                /**
1493:                 * Intialises required fields when loading an existing document variant.
1494:                 */
1495:                public void load(long documentTypeId, boolean retired,
1496:                        long lastVersionId, long liveVersionId,
1497:                        Date lastModified, long lastModifier,
1498:                        long createdFromBranchId, long createdFromLanguageId,
1499:                        long createdFromVersionId,
1500:                        long lastMajorChangeVersionId,
1501:                        long liveMajorChangeVersionId, long updateCount) {
1502:                    DocumentVariantImpl.this .documentTypeId = documentTypeId;
1503:                    DocumentVariantImpl.this .retired = retired;
1504:                    DocumentVariantImpl.this .lastVersionId = lastVersionId;
1505:                    DocumentVariantImpl.this .liveVersionId = liveVersionId;
1506:                    DocumentVariantImpl.this .lastModified = lastModified;
1507:                    DocumentVariantImpl.this .lastModifier = lastModifier;
1508:                    DocumentVariantImpl.this .createdFromBranchId = createdFromBranchId;
1509:                    DocumentVariantImpl.this .createdFromLanguageId = createdFromLanguageId;
1510:                    DocumentVariantImpl.this .createdFromVersionId = createdFromVersionId;
1511:                    DocumentVariantImpl.this .lastMajorChangeVersionId = lastMajorChangeVersionId;
1512:                    DocumentVariantImpl.this .liveMajorChangeVersionId = liveMajorChangeVersionId;
1513:                    DocumentVariantImpl.this .updateCount = updateCount;
1514:                    isNew = false;
1515:                }
1516:
1517:                /**
1518:                 * Updates the state of this Document object after saving it, also resets
1519:                 * all 'dirty' flags.
1520:                 */
1521:                public void saved(long lastVersionId, long liveVersionId,
1522:                        Date lastModified, String summary, long updateCount) {
1523:                    DocumentVariantImpl.this .lastVersionId = lastVersionId;
1524:                    DocumentVariantImpl.this .liveVersionId = liveVersionId;
1525:                    DocumentVariantImpl.this .lastModified = lastModified;
1526:                    DocumentVariantImpl.this .lastModifier = currentUser.getId();
1527:                    DocumentVariantImpl.this .updateCount = updateCount;
1528:                    DocumentVariantImpl.this .summary = summary;
1529:
1530:                    nameUpdated = false;
1531:                    partChanges = false;
1532:                    linkChanges = false;
1533:                    documentCollectionChanges = false;
1534:
1535:                    PartImpl[] parts = getPartImpls();
1536:                    for (PartImpl part : parts) {
1537:                        PartImpl.IntimateAccess partInt = part
1538:                                .getIntimateAccess(documentStrategy);
1539:                        partInt.setVersionId(lastVersionId);
1540:                        if (partInt.isDataUpdated())
1541:                            partInt.setDataChangedInVersion(lastVersionId);
1542:                        partInt.setNewOrUpdated(false, false);
1543:                        partInt.setData(null);
1544:                    }
1545:                    fieldChanges = false;
1546:                    customFieldChanges = false;
1547:
1548:                    // last/live version might have changed
1549:                    liveVersion = null;
1550:                    liveVersionLoaded = false;
1551:                    lastVersion = null;
1552:                    lastVersionLoaded = false;
1553:                    isNew = false;
1554:                    retiredChanged = false;
1555:                    documentTypeChanged = false;
1556:                }
1557:
1558:                public DocumentStrategy getDocumentStrategy() {
1559:                    return documentStrategy;
1560:                }
1561:
1562:                public AuthenticatedUser getCurrentUser() {
1563:                    return currentUser;
1564:                }
1565:
1566:                /**
1567:                 * Sets a user field without marking the user fields as modified.
1568:                 */
1569:                public void setCustomField(String name, String value) {
1570:                    customFields.put(name, value);
1571:                }
1572:
1573:                public PartImpl[] getPartImpls() {
1574:                    return parts.values().toArray(new PartImpl[0]);
1575:                }
1576:
1577:                public DocumentCollectionImpl[] getDocumentCollectionImpls() {
1578:                    return documentCollections.values().toArray(
1579:                            new DocumentCollectionImpl[0]);
1580:                }
1581:
1582:                public void addPart(PartImpl part) {
1583:                    parts.put(new Long(part.getTypeId()), part);
1584:                }
1585:
1586:                /**
1587:                 * Adds a link without marking the links as being modified.
1588:                 */
1589:                public void addLink(LinkImpl link) {
1590:                    links.add(link);
1591:                }
1592:
1593:                /**
1594:                 * Sets the name of the document without altering the "name dirty" flag.
1595:                 */
1596:                public void setName(String name) {
1597:                    if (name == null)
1598:                        throw new NullPointerException("name may not be null.");
1599:                    DocumentVariantImpl.this .name = name;
1600:                }
1601:
1602:                /**
1603:                 * Adds the given field. This method will not change the flag indicating
1604:                 * whether there were field changes.
1605:                 */
1606:                public void addField(FieldImpl field) {
1607:                    fields.put(new Long(field.getTypeId()), field);
1608:                }
1609:
1610:                public DocumentImpl getDocument() {
1611:                    return ownerDocument;
1612:                }
1613:
1614:                public DocId getDocId() {
1615:                    return ownerDocument.getIntimateAccess(documentStrategy)
1616:                            .getDocId();
1617:                }
1618:
1619:                public CommonRepositorySchema getRepositorySchema() {
1620:                    return repository.getRepositorySchema();
1621:                }
1622:
1623:                public CommonVariantManager getVariantManager() {
1624:                    return repository.getVariantManager();
1625:                }
1626:
1627:                /**
1628:                 * Adds the specified collection. This method will not change the flag indicating
1629:                 * whether there were collection changes.
1630:                 */
1631:                public void addCollection(DocumentCollectionImpl collection) {
1632:                    documentCollections.put(new Long(collection.getId()),
1633:                            collection);
1634:                }
1635:
1636:                public Part[] orderParts(Part[] parts) {
1637:                    return DocumentVariantImpl.this .orderParts(parts);
1638:                }
1639:
1640:                public Field[] orderFields(Field[] fields) {
1641:                    return DocumentVariantImpl.this .orderFields(fields);
1642:                }
1643:
1644:                public void setSummary(String summary) {
1645:                    DocumentVariantImpl.this .summary = summary;
1646:                }
1647:
1648:                public DocumentVariantImpl getVariant() {
1649:                    return DocumentVariantImpl.this ;
1650:                }
1651:
1652:                public void setCreatedFrom(long branchId, long languageId,
1653:                        long versionId) {
1654:                    createdFromBranchId = branchId;
1655:                    createdFromLanguageId = languageId;
1656:                    createdFromVersionId = versionId;
1657:                }
1658:
1659:                public void setStartFrom(long branchId, long languageId) {
1660:                    startBranchId = branchId;
1661:                    startLanguageId = languageId;
1662:                }
1663:
1664:                public long getStartBranchId() {
1665:                    return startBranchId;
1666:                }
1667:
1668:                public long getStartLanguageId() {
1669:                    return startLanguageId;
1670:                }
1671:            }
1672:
1673:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.