Changeset 3977
- Timestamp:
- 2010-04-06 13:37:14 (3 years ago)
- Location:
- projects/lily/trunk
- Files:
-
- 15 added
- 1 deleted
- 18 edited
-
indexer/src/main/java/org/lilycms/indexer/conf/IndexerConfBuilder.java (modified) (4 diffs)
-
indexer/src/main/java/org/lilycms/indexer/conf/Value.java (modified) (1 diff)
-
indexer/src/test/java/org/lilycms/indexer/test/IndexerTest.java (modified) (5 diffs)
-
linkmgmt/src/main/java/org/lilycms/linkmgmt/RecordLinkExtractor.java (modified) (1 diff)
-
linkmgmt/src/test/java/org/lilycms/linkmgmt/test/LinkManagerTest.java (modified) (4 diffs)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldDescriptor.java (modified) (2 diffs)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldDescriptorExistsException.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldDescriptorNotFoundException.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldDescriptorUpdateException.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldGroup.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldGroupEntry.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldGroupExistsException.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/FieldGroupNotFoundException.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/PrimitiveValueType.java (modified) (1 diff)
-
repository/api/src/main/java/org/lilycms/repository/api/Record.java (modified) (3 diffs)
-
repository/api/src/main/java/org/lilycms/repository/api/RecordType.java (modified) (2 diffs)
-
repository/api/src/main/java/org/lilycms/repository/api/RecordTypeExistsException.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/RecordTypeNotFoundException.java (added)
-
repository/api/src/main/java/org/lilycms/repository/api/Repository.java (modified) (5 diffs)
-
repository/api/src/main/java/org/lilycms/repository/api/TypeManager.java (modified) (4 diffs)
-
repository/impl/src/main/java/org/lilycms/repository/impl/FieldDescriptorImpl.java (modified) (7 diffs)
-
repository/impl/src/main/java/org/lilycms/repository/impl/FieldGroupEntryImpl.java (added)
-
repository/impl/src/main/java/org/lilycms/repository/impl/FieldGroupImpl.java (added)
-
repository/impl/src/main/java/org/lilycms/repository/impl/HBaseRepository.java (modified) (9 diffs)
-
repository/impl/src/main/java/org/lilycms/repository/impl/HBaseTypeManager.java (modified) (6 diffs)
-
repository/impl/src/main/java/org/lilycms/repository/impl/RecordImpl.java (modified) (11 diffs)
-
repository/impl/src/main/java/org/lilycms/repository/impl/RecordTypeImpl.java (modified) (3 diffs)
-
repository/impl/src/test/java/org/lilycms/repository/impl/test/FieldDescriptorImplTest.java (added)
-
repository/impl/src/test/java/org/lilycms/repository/impl/test/HBaseRepositoryTest.java (modified) (6 diffs)
-
repository/impl/src/test/java/org/lilycms/repository/impl/test/HBaseTypeManagerTest.java (deleted)
-
repository/impl/src/test/java/org/lilycms/repository/impl/test/TypeManagerFieldDescriptorTest.java (added)
-
repository/impl/src/test/java/org/lilycms/repository/impl/test/TypeManagerFieldGroupTest.java (added)
-
repository/impl/src/test/java/org/lilycms/repository/impl/test/TypeManagerRecordTypeTest.java (added)
-
repository/impl/src/test/java/org/lilycms/repository/impl/test/ValueTypeTest.java (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
projects/lily/trunk/indexer/src/main/java/org/lilycms/indexer/conf/IndexerConfBuilder.java
r3950 r3977 163 163 List<Element> indexFieldEls = FIELD_CHILDREN.get().evalAsNativeElementList(caseEl); 164 164 for (Element indexFieldEl : indexFieldEls) { 165 mapping.indexFieldBindings.add(buildIndexFieldBinding(indexFieldEl ));165 mapping.indexFieldBindings.add(buildIndexFieldBinding(indexFieldEl, true)); 166 166 } 167 167 … … 181 181 List<Element> indexFieldEls = FIELD_CHILDREN.get().evalAsNativeElementList(caseEl); 182 182 for (Element indexFieldEl : indexFieldEls) { 183 mapping.indexFieldBindings.add(buildIndexFieldBinding(indexFieldEl ));183 mapping.indexFieldBindings.add(buildIndexFieldBinding(indexFieldEl, false)); 184 184 } 185 185 … … 188 188 } 189 189 190 private IndexFieldBinding buildIndexFieldBinding(Element indexFieldEl ) throws Exception {190 private IndexFieldBinding buildIndexFieldBinding(Element indexFieldEl, boolean versioned) throws Exception { 191 191 String name = DocumentHelper.getAttribute(indexFieldEl, "name", false); 192 192 String ref = DocumentHelper.getAttribute(indexFieldEl, "ref", false); … … 211 211 212 212 213 Value value = buildValue(DocumentHelper.getElementChild(indexFieldEl, "value", true) );213 Value value = buildValue(DocumentHelper.getElementChild(indexFieldEl, "value", true), versioned); 214 214 215 215 return new IndexFieldBinding(field, value); 216 216 } 217 217 218 private Value buildValue(Element valueEl ) throws Exception {218 private Value buildValue(Element valueEl, boolean versioned) throws Exception { 219 219 Element fieldEl = DocumentHelper.getElementChild(valueEl, "field", true); 220 220 String name = DocumentHelper.getAttribute(fieldEl, "name", true); 221 return new Value(name );221 return new Value(name, versioned); 222 222 } 223 223 -
projects/lily/trunk/indexer/src/main/java/org/lilycms/indexer/conf/Value.java
r3952 r3977 1 1 package org.lilycms.indexer.conf; 2 2 3 import org.apache.hadoop.hbase.util.Bytes; 3 import java.util.Set; 4 4 5 import org.lilycms.repository.api.FieldNotFoundException; 5 6 import org.lilycms.repository.api.Record; 6 7 7 import java.util.Set;8 9 8 public class Value { 10 9 private String fieldName; 10 private final boolean versioned; 11 11 12 public Value(String fieldName ) {12 public Value(String fieldName, boolean versioned) { 13 13 this.fieldName = fieldName; 14 this.versioned = versioned; 14 15 } 15 16 16 17 public String eval(Record record) { 17 18 try { 18 return (String)record.getField(fieldName); 19 if (versioned) { 20 return (String)record.getVersionableField(fieldName); 21 } else { 22 return (String)record.getNonVersionableField(fieldName); 23 } 19 24 } catch (FieldNotFoundException e) { 20 25 // TODO -
projects/lily/trunk/indexer/src/test/java/org/lilycms/indexer/test/IndexerTest.java
r3959 r3977 24 24 import org.lilycms.queue.api.QueueListener; 25 25 import org.lilycms.queue.api.QueueMessage; 26 import org.lilycms.repository.api.FieldGroup; 26 27 import org.lilycms.repository.api.IdGenerator; 27 28 import org.lilycms.repository.api.Record; … … 31 32 import org.lilycms.repository.api.TypeManager; 32 33 import org.lilycms.repository.api.ValueType; 33 import org.lilycms.repository.impl.FieldDescriptorImpl;34 34 import org.lilycms.repository.impl.HBaseRepository; 35 35 import org.lilycms.repository.impl.HBaseTypeManager; 36 36 import org.lilycms.repository.impl.IdGeneratorImpl; 37 import org.lilycms.repository.impl.RecordImpl;38 import org.lilycms.repository.impl.RecordTypeImpl;39 37 import org.lilycms.testfw.TestHelper; 40 38 … … 69 67 public void testIndexer() throws Exception { 70 68 IdGenerator idGenerator = new IdGeneratorImpl(); 71 TypeManager typeManager = new HBaseTypeManager(idGenerator, RecordTypeImpl.class, FieldDescriptorImpl.class,TEST_UTIL.getConfiguration());72 Repository repository = new HBaseRepository(typeManager, idGenerator, RecordImpl.class,TEST_UTIL.getConfiguration());69 TypeManager typeManager = new HBaseTypeManager(idGenerator, TEST_UTIL.getConfiguration()); 70 Repository repository = new HBaseRepository(typeManager, idGenerator, TEST_UTIL.getConfiguration()); 73 71 SolrServer solrServer = SOLR_TEST_UTIL.getSolrServer(); 74 72 TestLilyQueue queue = new TestLilyQueue(); … … 76 74 77 75 // Create a record type 76 ValueType stringValueType = typeManager.getValueType("STRING", false, false); 77 typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("field1", stringValueType, "field1GN")); 78 typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("field2", stringValueType, "field2GN")); 79 typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("field3", stringValueType, "field3GN")); 80 FieldGroup fieldGroup1 = typeManager.newFieldGroup("fieldGroup1"); 81 fieldGroup1.setFieldGroupEntry(typeManager.newFieldGroupEntry("field1", Long.valueOf(1), true, "alias1")); 82 fieldGroup1.setFieldGroupEntry(typeManager.newFieldGroupEntry("field2", Long.valueOf(1), true, "alias2")); 83 fieldGroup1.setFieldGroupEntry(typeManager.newFieldGroupEntry("field3", Long.valueOf(1), true, "alias3")); 84 fieldGroup1 = typeManager.createFieldGroup(fieldGroup1); 85 86 typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("nvfield1", stringValueType, "nvfield1GN")); 87 FieldGroup fieldGroup2 = typeManager.newFieldGroup("fieldGroup2"); 88 fieldGroup2.setFieldGroupEntry(typeManager.newFieldGroupEntry("nvfield1", Long.valueOf(1), true, "nvalias1")); 89 fieldGroup2 = typeManager.createFieldGroup(fieldGroup2); 90 78 91 RecordType recordType = typeManager.newRecordType("RecordType1"); 79 ValueType stringValueType = typeManager.getValueType("STRING", false, false); 80 recordType.addFieldDescriptor(typeManager.newFieldDescriptor("field1", stringValueType, true, true)); 81 recordType.addFieldDescriptor(typeManager.newFieldDescriptor("field2", stringValueType, true, true)); 82 recordType.addFieldDescriptor(typeManager.newFieldDescriptor("field3", stringValueType, true, true)); 83 recordType.addFieldDescriptor(typeManager.newFieldDescriptor("nvfield1", stringValueType, true, false)); 84 typeManager.createRecordType(recordType); 85 86 // TODO need to re-retrieve the record type because its version property is not updated 87 recordType = typeManager.getRecordType("RecordType1"); 92 recordType.setVersionableFieldGroupId(fieldGroup1.getId()); 93 recordType.setVersionableFieldGroupVersion(fieldGroup1.getVersion()); 94 recordType.setNonVersionableFieldGroupId(fieldGroup2.getId()); 95 recordType.setNonVersionableFieldGroupVersion(fieldGroup2.getVersion()); 96 recordType = typeManager.createRecordType(recordType); 88 97 89 98 // Create a document 90 Record record = repository.newRecord( );99 Record record = repository.newRecord(idGenerator.newRecordId()); 91 100 record.setRecordType("RecordType1", recordType.getVersion()); 92 record.set Field("field1", "apple");93 record.set Field("field2", "pear");94 record.set Field("field3", "orange");95 record.set Field("nvfield1", "banana");101 record.setVersionableField("field1", "apple"); 102 record.setVersionableField("field2", "pear"); 103 record.setVersionableField("field3", "orange"); 104 record.setNonVersionableField("nvfield1", "banana"); 96 105 repository.create(record); 97 106 … … 114 123 record = repository.newRecord(record.getId()); 115 124 record.setRecordType(recordType.getId(), recordType.getVersion()); 116 record.set Field("field1", "peach");125 record.setVersionableField("field1", "peach"); 117 126 repository.update(record); 118 127 record = repository.read(record.getId()); -
projects/lily/trunk/linkmgmt/src/main/java/org/lilycms/linkmgmt/RecordLinkExtractor.java
r3966 r3977 14 14 // run over all fields, check using the typemanager if it is a link field, if so put 15 15 // the resolved link into the collector. 16 for(Map.Entry<String, Object> field : record.get Fields().entrySet()) {16 for(Map.Entry<String, Object> field : record.getVersionableFields().entrySet()) { 17 17 } 18 18 -
projects/lily/trunk/linkmgmt/src/test/java/org/lilycms/linkmgmt/test/LinkManagerTest.java
r3966 r3977 1 1 package org.lilycms.linkmgmt.test; 2 3 import static org.junit.Assert.*; 4 5 import java.util.HashSet; 6 import java.util.Set; 2 7 3 8 import org.apache.hadoop.hbase.HBaseTestingUtility; … … 5 10 import org.junit.BeforeClass; 6 11 import org.junit.Test; 7 import static org.junit.Assert.*;8 12 import org.lilycms.hbaseindex.IndexManager; 9 13 import org.lilycms.linkmgmt.FieldedLink; … … 13 17 import org.lilycms.repository.api.Repository; 14 18 import org.lilycms.repository.api.TypeManager; 15 import org.lilycms.repository.impl.*; 19 import org.lilycms.repository.impl.HBaseRepository; 20 import org.lilycms.repository.impl.HBaseTypeManager; 21 import org.lilycms.repository.impl.IdGeneratorImpl; 16 22 import org.lilycms.testfw.TestHelper; 17 18 import java.util.HashSet;19 import java.util.Set;20 23 21 24 public class LinkManagerTest { … … 38 41 public void test() throws Exception { 39 42 IdGenerator idGenerator = new IdGeneratorImpl(); 40 TypeManager typeManager = new HBaseTypeManager(idGenerator, RecordTypeImpl.class, FieldDescriptorImpl.class,TEST_UTIL.getConfiguration());41 Repository repository = new HBaseRepository(typeManager, idGenerator, RecordImpl.class,TEST_UTIL.getConfiguration());43 TypeManager typeManager = new HBaseTypeManager(idGenerator, TEST_UTIL.getConfiguration()); 44 Repository repository = new HBaseRepository(typeManager, idGenerator, TEST_UTIL.getConfiguration()); 42 45 IdGenerator ids = repository.getIdGenerator(); 43 46 IndexManager indexManager = new IndexManager(TEST_UTIL.getConfiguration()); -
projects/lily/trunk/repository/api/src/main/java/org/lilycms/repository/api/FieldDescriptor.java
r3955 r3977 31 31 public interface FieldDescriptor { 32 32 /** 33 * The id of the {@link FieldDescriptor} is also the id to be used by the corresponding {@link Field} 33 * The id of the {@link FieldDescriptor} is also the id to be used by the corresponding {@link Field} 34 * The id is system generated and unique. 34 35 * @return the id of the {@link FieldDescriptor} 35 36 */ 36 37 String getId(); 37 38 39 /** 40 * Set the version of the {@link FieldDescriptor} 41 */ 42 void setVersion(Long version); 43 38 44 /** 39 45 * @return the version of the {@link FieldDescriptor} … … 42 48 43 49 /** 50 * Set the global unique name of the {@link FieldDescriptor}. 51 * The name can be chose by the user. 52 */ 53 void setGlobalName(String name); 54 55 /** 56 * @return the global unique name of the {@link FieldDescriptor} 57 */ 58 String getGlobalName(); 59 60 /** 61 * Set the {@link ValueType} of the {@link Field} 62 * @param valueType 63 */ 64 void setValueType(ValueType valueType); 65 66 /** 44 67 * @return the {@link ValueType} of the {@link Field} 45 68 */ 46 69 ValueType getValueType(); 47 70 48 /** 49 * @return if the {@link Field} is mandatory 50 */ 51 boolean isMandatory(); 71 boolean equals(Object obj); 52 72 53 /** 54 * @return if the {@link Field} is versionable 55 */ 56 boolean isVersionable(); 57 58 boolean equals(Object obj); 73 FieldDescriptor clone(); 59 74 } -
projects/lily/trunk/repository/api/src/main/java/org/lilycms/repository/api/PrimitiveValueType.java
r3959 r3977 50 50 */ 51 51 Class getType(); 52 53 @Override 54 boolean equals(Object obj); 52 55 } -
projects/lily/trunk/repository/api/src/main/java/org/lilycms/repository/api/Record.java
r3955 r3977 16 16 package org.lilycms.repository.api; 17 17 18 import java.util.List; 18 19 import java.util.Map; 19 import java.util.Set;20 20 21 21 /** … … 34 34 * Fields to be deleted need to be added explicitly with their fieldId 35 35 * 36 * <p>37 * A record can either be an ordinary record or a variant record, in which case38 * the variantProperties need to be provided, and the {@link RecordId} should39 * point to the master record.40 36 */ 41 37 public interface Record { … … 48 44 Long getVersion(); 49 45 50 void setRecordType(String recordTypeId, long recordTypeVersion);46 void setRecordType(String id, Long version); 51 47 52 48 String getRecordTypeId(); 53 49 54 long getRecordTypeVersion(); 50 Long getRecordTypeVersion(); 51 52 void setNonVersionableRecordType(String id, Long version); 53 54 String getNonVersionableRecordTypeId(); 55 56 Long getNonVersionableRecordTypeVersion(); 57 58 void setVersionableRecordType(String id, Long version); 59 60 String getVersionableRecordTypeId(); 61 62 Long getVersionableRecordTypeVersion(); 63 64 void setVersionableMutableRecordType(String id, Long version); 65 66 String getVersionableMutableRecordTypeId(); 67 68 Long getVersionableMutableRecordTypeVersion(); 55 69 56 void set Field(String fieldId, Object value);70 void setNonVersionableField(String fieldId, Object value); 57 71 58 Object get Field(String fieldId) throws FieldNotFoundException;72 Object getNonVersionableField(String fieldId) throws FieldNotFoundException; 59 73 60 Map<String, Object> getFields();74 void setVersionableField(String fieldId, Object value); 61 75 62 void deleteField(String fieldId);76 Object getVersionableField(String fieldId) throws FieldNotFoundException; 63 77 64 Set<String> getDeleteFields(); 78 void setVersionableMutableField(String fieldId, Object value); 79 80 Object getVersionableMutableField(String fieldId) throws FieldNotFoundException; 81 82 Map<String, Object> getNonVersionableFields(); 83 84 Map<String, Object> getVersionableFields(); 85 86 Map<String, Object> getVersionableMutableFields(); 87 88 void addNonVersionableFieldsToDelete(List<String> fieldIds); 89 90 void removeNonVersionableFieldsToDelete(List<String> fieldIds); 91 92 List<String> getNonVersionableFieldsToDelete(); 93 94 void addVersionableFieldsToDelete(List<String> fieldIds); 95 96 void removeVersionableFieldsToDelete(List<String> fieldIds); 97 98 List<String> getVersionableFieldsToDelete(); 99 100 void addVersionableMutableFieldsToDelete(List<String> fieldIds); 101 102 void removeVersionableMutableFieldsToDelete(List<String> fieldIds); 103 104 List<String> getVersionableMutableFieldsToDelete(); 105 106 Record clone(); 65 107 66 108 boolean equals(Object obj); -
projects/lily/trunk/repository/api/src/main/java/org/lilycms/repository/api/RecordType.java
r3955 r3977 16 16 package org.lilycms.repository.api; 17 17 18 import java.util.Collection;19 18 20 19 /** … … 36 35 37 36 Long getVersion(); 37 38 void setNonVersionableFieldGroupId(String id); 39 40 void setNonVersionableFieldGroupVersion(Long version); 41 42 void setVersionableFieldGroupId(String id); 43 44 void setVersionableFieldGroupVersion(Long version); 45 46 void setVersionableMutableFieldGroupId(String id); 47 48 void setVersionableMutableFieldGroupVersion(Long version); 49 50 String getNonVersionableFieldGroupId(); 51 52 Long getNonVersionableFieldGroupVersion(); 53 54 String getVersionableFieldGroupId(); 55 56 Long getVersionableFieldGroupVersion(); 57 58 String getVersionableMutableFieldGroupId(); 59 60 Long getVersionableMutableFieldGroupVersion(); 38 61 39 void addFieldDescriptor(FieldDescriptor fieldDescriptor); 40 41 void removeFieldDescriptor(String removeFieldDescriptorId); 42 43 FieldDescriptor getFieldDescriptor(String fieldDescriptorId); 44 45 Collection<FieldDescriptor> getFieldDescriptors(); 46 62 RecordType clone(); 63 47 64 boolean equals(Object obj); 48 65 } -
projects/lily/trunk/repository/api/src/main/java/org/lilycms/repository/api/Repository.java
r3952 r3977 16 16 package org.lilycms.repository.api; 17 17 18 import java.util.List; 19 18 20 19 21 /** … … 24 26 * Creates a new {@link Record} object. 25 27 */ 26 Record newRecord() throws RepositoryException;28 Record newRecord(); 27 29 28 30 /** … … 30 32 * filled in. 31 33 */ 32 Record newRecord(RecordId recordId) throws RepositoryException;34 Record newRecord(RecordId recordId); 33 35 34 36 /** … … 48 50 * @throws InvalidRecordException 49 51 * if an empty record is being created 52 * @throws FieldDescriptorNotFoundException 53 * @throws FieldGroupNotFoundException 54 * @throws RecordTypeNotFoundException 50 55 * @throws RepostioryException 51 56 * TBD 52 57 */ 53 void create(Record record) throws RecordExistsException, RecordNotFoundException, InvalidRecordException,54 Re positoryException;58 Record create(Record record) throws RecordExistsException, RecordNotFoundException, InvalidRecordException, 59 RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException; 55 60 56 61 /** … … 75 80 * @throws RepositoryException 76 81 * TBD 82 * @throws FieldDescriptorNotFoundException 83 * @throws FieldGroupNotFoundException 84 * @throws RecordTypeNotFoundException 77 85 */ 78 void update(Record record) throws RecordNotFoundException, InvalidRecordException, RepositoryException;86 Record update(Record record) throws RecordNotFoundException, InvalidRecordException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException; 79 87 80 /** 81 * Read the latest version of a {@link Record} from the repository. 82 * 83 * @param recordId 84 * the id of the {@link Record} to read 85 * @param fieldIds 86 * the fields to read from the {@link Record}, an empty list 87 * results in reading all fields 88 * @throws RecordNotFoundException 89 * if the {@link Record} does not exist 90 * @throws RepositoryException 91 * TBD 92 */ 93 Record read(RecordId recordId, String... fieldIds) throws RecordNotFoundException, RepositoryException; 88 Record read(RecordId recordId) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException; 94 89 95 /** 96 * Read a specific version of a {@link Record} 97 * 98 * @param version 99 * the versionNumber to read 100 * 101 */ 102 Record read(RecordId recordId, Long version, String... fieldIds) throws RecordNotFoundException, 103 RepositoryException; 90 Record read(RecordId recordId, List<String> nonVersionableFieldIds, List<String> versionableFieldIds, List<String> versionableMutableFieldIds) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException; 91 92 Record read(RecordId recordId, Long version) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException; 93 94 Record read(RecordId recordId, Long version, List<String> nonVersionableFieldIds, List<String> versionableFieldIds, List<String> versionableMutableFieldIds) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException; 104 95 105 96 /** -
projects/lily/trunk/repository/api/src/main/java/org/lilycms/repository/api/TypeManager.java
r3955 r3977 16 16 package org.lilycms.repository.api; 17 17 18 import java.util.List; 19 18 20 19 21 /** … … 26 28 * Creates a new {@link RecordType} object. 27 29 */ 28 RecordType newRecordType(String recordTypeId) throws RepositoryException;30 RecordType newRecordType(String recordTypeId); 29 31 30 32 /** 31 * Creates a new {@link FieldDescriptor} object. 33 * Creates a {@link RecordType} on the repository with the properties defined in the {@link RecordType} object. 34 * @throws RecordTypeExistsException when a recordType with the same id already exists on the repository 35 * @throws FieldGroupNotFoundException when the recordType refers to a non-existing {@link FieldGroup} 36 * @throws RepositoryException when an unexpected exception occurs on the repository 32 37 */ 33 FieldDescriptor newFieldDescriptor(String fieldDescriptorId, ValueType valueType, boolean mandatory, boolean versionable) throwsRepositoryException;38 RecordType createRecordType(RecordType recordType) throws RecordTypeExistsException, FieldGroupNotFoundException, RepositoryException; 34 39 35 40 /** 36 * Creates a new {@link FieldDescriptor} object. 41 * Retrieves the latest version of a {@link RecordType} from the repository. 42 * @throws RecordTypeNotFoundException when the recordType does not exist 43 * @throws RepositoryException when an unexpected exception occurs on the repository 37 44 */ 38 FieldDescriptor newFieldDescriptor(String fieldDescriptorId, Long version, ValueType valueType, boolean mandatory, boolean versionable) throws RepositoryException; 39 40 /** 41 * Creates a {@link RecordType} on the repository with the properties defined in the {@link RecordType} object. 42 */ 43 void createRecordType(RecordType recordType) throws RepositoryException; 44 45 /** 46 * Retrieves the latest version of a {@link RecordType} from the repository. 47 */ 48 RecordType getRecordType(String recordTypeId) throws RepositoryException; 49 50 /** 51 * Retrieves a specific version of a {@link RecordType} from the repository. 52 * If no version is given, the latest version is retrieved. 53 */ 54 RecordType getRecordType(String recordTypeId, Long recordTypeVersion) throws RepositoryException; 45 RecordType getRecordType(String recordTypeId, Long recordTypeVersion) throws RecordTypeNotFoundException, RepositoryException; 55 46 56 47 /** … … 59 50 * be deleted it should be left out of the {@link RecordType}'s list of 60 51 * {@link FieldDescriptor}s. 52 * @throws RecordTypeNotFoundException when the recordType to be updated does not exist 53 * @throws FieldGroupNotFoundException when a {@link FieldGroup} referred to by the recordType does not exist 54 * @throws RepositoryException when an unexpected exception occurs on the repository 61 55 */ 62 void updateRecordType(RecordType recordType) throwsRepositoryException;56 RecordType updateRecordType(RecordType recordType) throws RecordTypeNotFoundException, FieldGroupNotFoundException, RepositoryException; 63 57 58 /** 59 * Removes fieldGroups from the recordType. If no fieldGroup existed it is ignored. 60 * @param recordTypeId the id of the {@link RecordType} 61 * @param nonVersionable if the non-versionable fieldGroup should be removed 62 * @param versionable if the versionable fieldGroup should be removed 63 * @param versionableMutable if the versionable-mutable fieldGroup should be removed 64 * @return a {@link RecordType} with an updated version number and the requested fieldGroups removed 65 * @throws RecordTypeNotFoundException when the recordType does not exist 66 * @throws RepositoryException when an unexpected exception occurs on the repository 67 */ 68 RecordType removeFieldGroups(String recordTypeId, boolean nonVersionable, boolean versionable, boolean versionableMutable) throws RecordTypeNotFoundException, RepositoryException; 69 70 /** 71 * Creates a new {@link FieldGroup} object. 72 */ 73 FieldGroup newFieldGroup(String id); 74 75 FieldGroupEntry newFieldGroupEntry(String fieldDescriptorId, Long fieldDescriptorVersion, boolean mandatory, String alias); 76 77 /** 78 * Creates a {@link FieldGroup} on the repository with the properties defined in the {@link FieldGroup} object. 79 * @return a {@link FieldGroup} object containing the updated version number of the fieldGroup 80 * @throws FieldGroupExistsException when a fieldGroup with the same id already exists on the repository 81 * @throws FieldDescriptorNotFoundException when the fieldGroup refers to a non-existing {@link FieldDescriptor} 82 * @throws RepositoryException when an unexpected exception occurs on the repository 83 */ 84 FieldGroup createFieldGroup(FieldGroup fieldGroup) throws FieldGroupExistsException, FieldDescriptorNotFoundException, RepositoryException; 85 86 /** 87 * Updates a {@link FieldGroup} on the repository with the properties defined in the {@link FieldGroup} object. 88 * @return a {@link FieldGroup} object containing the updated version number of the fieldGroup 89 * @throws FieldGroupNotFoundException when the fieldGroup to update does not exist 90 * @throws FieldDescriptorNotFoundException when the updated fieldGroup refers to a non-existing {@link FieldDescriptor} 91 * @throws RepositoryException when an unexpected exception occurs on the repository 92 */ 93 FieldGroup updateFieldGroup(FieldGroup fieldGroup) throws FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException; 94 95 /** 96 * Removes fieldDescriptors from fieldGroup. This operation is performed towards the latest version of the fieldGroup. 97 * FieldDescriptors that are not known by the fieldGroup are ignored. 98 * @param fieldGroupId the id of the {@link FieldGroup} to perform this operation on 99 * @param fieldDescriptorIds a list of {@link FieldDescriptors} to remove 100 * @return a new {@link FieldGroup} with an updated version number and the remaining fieldDescriptors 101 * @throws FieldGroupNotFoundException when the fieldGroup does not exist 102 * @throws RepositoryException when an unexpected exception occurs in the repository 103 */ 104 FieldGroup removeFieldDescriptors(String fieldGroupId, List<String> fieldDescriptorIds) throws FieldGroupNotFoundException, RepositoryException; 105 106 /** 107 * Gets a {@link FieldGroup} from the repository 108 * @param version is the version of the {@link FieldGroup} to get. If null, the latest existing version is taken. 109 * @return a {@link FieldGroup} object 110 * @throws FieldGroupNotFoundException when no fieldGroup with id and version exists 111 * @throws RepositoryException when an unexpected exception occurs on the repository 112 */ 113 FieldGroup getFieldGroup(String id, Long version) throws FieldGroupNotFoundException, RepositoryException; 114 115 // Field Descriptors 116 /** 117 * Creates a new {@link FieldDescriptor} object. 118 */ 119 FieldDescriptor newFieldDescriptor(String id, ValueType valueType, String globalName); 120 121 /** 122 * Creates a {@link FieldDescriptor} on the repository with the properties defined in the {@link FieldDescriptor} object. 123 * @return a {@link FieldDescriptor} object containing the updated version number of the fieldDescriptor 124 * @throws FieldDescriptorExistsException if a fieldDescriptor with the same id already exists on the repository 125 * @throws RepositoryException when an unexpected exception occurs on the repository 126 */ 127 FieldDescriptor createFieldDescriptor(FieldDescriptor fieldDescriptor) throws FieldDescriptorExistsException, RepositoryException; 128 129 /** 130 * Updates a {@link FieldDescriptor} on the repository with the properties defined in the {@link FieldDescriptor} object. 131 * The version number in the given fieldDescriptor is ignored, a new version number will be assigned. 132 * @return a {@link FieldDescriptor} object containing the new version number of the fieldDescriptor 133 * @throws FieldDescriptorNotFoundException when no fieldDescriptor with id and version exists 134 * @throws FieldDescriptorUpdateException an exception occured while updating the FieldDescriptor 135 * @throws RepositoryException when an unexpected exception occurs on the repository 136 */ 137 FieldDescriptor updateFieldDescriptor(FieldDescriptor fieldDescriptor) throws FieldDescriptorNotFoundException, FieldDescriptorUpdateException, RepositoryException; 138 139 /** 140 * Gets a {@link FieldDescriptor} from the repository 141 * @param version is the version of the {@link FieldDescriptor} to get. If null, the latest existing version is taken. 142 * @return a {@link FieldDescriptor} object 143 * @throws FieldDescriptorNotFoundException when no fieldDescriptor with id and version exists 144 * @throws RepositoryException when an unexpected exception occurs on the repository 145 */ 146 FieldDescriptor getFieldDescriptor(String id, Long version) throws FieldDescriptorNotFoundException, RepositoryException; 147 148 149 // Value Types 150 151 /** 152 * A new {@link PrimitiveValueType} should be registered by calling this method before it can be used. 153 */ 154 void registerPrimitiveValueType(PrimitiveValueType primitiveValueType); 155 64 156 /** 65 157 * This method should be called to get a {@link ValueType} instance … … 69 161 */ 70 162 ValueType getValueType(String primitiveValueTypeName, boolean multiValue, boolean hierarchical); 71 72 /**73 * A new {@link PrimitiveValueType} should be registered by calling this method before it can be used.74 */75 void registerPrimitiveValueType(PrimitiveValueType primitiveValueType);76 163 } -
projects/lily/trunk/repository/impl/src/main/java/org/lilycms/repository/impl/FieldDescriptorImpl.java
r3952 r3977 22 22 public class FieldDescriptorImpl implements FieldDescriptor { 23 23 24 private final String fieldDescriptorId;24 private final String id; 25 25 private Long version; 26 private final boolean mandatory; 27 private final boolean versionable; 28 private final ValueType valueType; 26 private ValueType valueType; 27 private String globalName; 29 28 30 29 /** … … 32 31 * @use {@link TypeManager#newFieldDescriptor} instead 33 32 */ 34 public FieldDescriptorImpl(String fieldDescriptorId, ValueType valueType, boolean mandatory, boolean versionable) { 35 this(fieldDescriptorId, null, valueType, mandatory, versionable); 33 public FieldDescriptorImpl(String id, ValueType valueType, String globalName) { 34 this.id = id; 35 this.valueType = valueType; 36 this.globalName = globalName; 36 37 } 37 38 38 /** 39 * This constructor should not be called directly. 40 * @use {@link TypeManager#newFieldDescriptor} instead 41 */ 42 public FieldDescriptorImpl(String fieldDescriptorId, Long version, ValueType valueType, boolean mandatory, boolean versionable) { 43 this.fieldDescriptorId = fieldDescriptorId; 44 this.version = version; 45 this.valueType = valueType; 46 this.mandatory = mandatory; 47 this.versionable = versionable; 39 public String getGlobalName() { 40 return globalName; 41 } 42 43 public String getId() { 44 return id; 48 45 } 49 46 … … 52 49 } 53 50 54 public String getId() {55 return fieldDescriptorId;56 }57 58 51 public Long getVersion() { 59 52 return version; 60 53 } 61 62 public void setVersion(long version) { 54 55 public void setGlobalName(String name) { 56 this.globalName = name; 57 } 58 59 public void setValueType(ValueType valueType) { 60 this.valueType = valueType; 61 } 62 63 public void setVersion(Long version) { 63 64 this.version = version; 64 65 } 65 66 public boolean isMandatory() { 67 return mandatory; 68 } 69 70 public boolean isVersionable() { 71 return versionable; 66 67 public FieldDescriptor clone() { 68 FieldDescriptorImpl clone = new FieldDescriptorImpl(this.id, this.valueType, this.globalName); 69 clone.version = this.version; 70 return clone; 72 71 } 73 72 … … 76 75 final int prime = 31; 77 76 int result = 1; 78 result = prime * result + ((fieldDescriptorId == null) ? 0 : fieldDescriptorId.hashCode()); 77 result = prime * result + ((globalName == null) ? 0 : globalName.hashCode()); 78 result = prime * result + ((id == null) ? 0 : id.hashCode()); 79 79 result = prime * result + ((valueType == null) ? 0 : valueType.hashCode()); 80 result = prime * result + (mandatory ? 1231 : 1237);81 80 result = prime * result + ((version == null) ? 0 : version.hashCode()); 82 result = prime * result + (versionable ? 1231 : 1237);83 81 return result; 84 82 } … … 93 91 return false; 94 92 FieldDescriptorImpl other = (FieldDescriptorImpl) obj; 95 if ( fieldDescriptorId== null) {96 if (other. fieldDescriptorId!= null)93 if (globalName == null) { 94 if (other.globalName != null) 97 95 return false; 98 } else if (!fieldDescriptorId.equals(other.fieldDescriptorId)) 96 } else if (!globalName.equals(other.globalName)) 97 return false; 98 if (id == null) { 99 if (other.id != null) 100 return false; 101 } else if (!id.equals(other.id)) 99 102 return false; 100 103 if (valueType == null) { … … 103 106 } else if (!valueType.equals(other.valueType)) 104 107 return false; 105 if (mandatory != other.mandatory)106 return false;107 108 if (version == null) { 108 109 if (other.version != null) 109 110 return false; 110 111 } else if (!version.equals(other.version)) 111 return false;112 if (versionable != other.versionable)113 112 return false; 114 113 return true; … … 117 116 @Override 118 117 public String toString() { 119 return "FieldDescriptorImpl [ fieldDescriptorId=" + fieldDescriptorId + ", version=" + version + ", valueType="120 + valueType + ", mandatory=" + mandatory + ", versionable=" + versionable + "]";118 return "FieldDescriptorImpl [id=" + id + ", version=" + version + ", globalName=" + globalName 119 + ", valueType=" + valueType + "]"; 121 120 } 122 123 121 } -
projects/lily/trunk/repository/impl/src/main/java/org/lilycms/repository/impl/HBaseRepository.java
r3967 r3977 17 17 18 18 import java.io.IOException; 19 import java.lang.reflect.Constructor; 19 import java.util.ArrayList; 20 import java.util.List; 21 import java.util.Map; 20 22 import java.util.NavigableMap; 21 import java.util.Set;22 23 import java.util.Map.Entry; 23 24 … … 34 35 import org.apache.hadoop.hbase.util.Bytes; 35 36 import org.lilycms.repository.api.FieldDescriptor; 37 import org.lilycms.repository.api.FieldDescriptorNotFoundException; 38 import org.lilycms.repository.api.FieldGroup; 39 import org.lilycms.repository.api.FieldGroupEntry; 40 import org.lilycms.repository.api.FieldGroupNotFoundException; 36 41 import org.lilycms.repository.api.IdGenerator; 37 42 import org.lilycms.repository.api.InvalidRecordException; … … 41 46 import org.lilycms.repository.api.RecordNotFoundException; 42 47 import org.lilycms.repository.api.RecordType; 48 import org.lilycms.repository.api.RecordTypeNotFoundException; 43 49 import org.lilycms.repository.api.Repository; 44 50 import org.lilycms.repository.api.RepositoryException; … … 46 52 import org.lilycms.repository.api.ValueType; 47 53 import org.lilycms.util.ArgumentValidator; 54 import org.lilycms.util.Pair; 48 55 49 56 public class HBaseRepository implements Repository { 50 57 51 private static final byte[] SYSTEM_COLUMN_FAMILY = Bytes.toBytes("systemCF"); 52 private static final byte[] VERSIONABLE_SYSTEM_COLUMN_FAMILY = Bytes.toBytes("versionableSystemCF"); 53 private static final byte[] VERSIONABLE_COLUMN_FAMILY = Bytes.toBytes("versionableCF"); 54 private static final byte[] NON_VERSIONABLE_COLUMN_FAMILY = Bytes.toBytes("nonVersionableCF"); 55 private static final byte[] CURRENT_VERSION_COLUMN_NAME = Bytes.toBytes("currentVersion"); 58 private static final byte[] NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY = Bytes.toBytes("NonVersionableSystemCF"); 59 private static final byte[] VERSIONABLE_SYSTEM_COLUMN_FAMILY = Bytes.toBytes("VersionableSystemCF"); 60 private static final byte[] NON_VERSIONABLE_COLUMN_FAMILY = Bytes.toBytes("NonVersionableCF"); 61 private static final byte[] VERSIONABLE_COLUMN_FAMILY = Bytes.toBytes("VersionableCF"); 62 private static final byte[] VERSIONABLE_MUTABLE_COLUMN_FAMILY = Bytes.toBytes("VersionableMutableCF"); 63 private static final byte[] CURRENT_VERSION_COLUMN_NAME = Bytes.toBytes("$CurrentVersion"); 56 64 private static final byte[] RECORDTYPEID_COLUMN_NAME = Bytes.toBytes("$RecordTypeId"); 57 65 private static final byte[] RECORDTYPEVERSION_COLUMN_NAME = Bytes.toBytes("$RecordTypeVersion"); 66 private static final byte[] NON_VERSIONABLE_RECORDTYPEID_COLUMN_NAME = Bytes.toBytes("$NonVersionableRecordTypeId"); 67 private static final byte[] NON_VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME = Bytes.toBytes("$NonVersionableRecordTypeVersion"); 68 private static final byte[] VERSIONABLE_RECORDTYPEID_COLUMN_NAME = Bytes.toBytes("$VersionableRecordTypeId"); 69 private static final byte[] VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME = Bytes.toBytes("$VersionableRecordTypeVersion"); 70 private static final byte[] VERSIONABLE_MUTABLE_RECORDTYPEID_COLUMN_NAME = Bytes.toBytes("$VersionableMutableRecordTypeId"); 71 private static final byte[] VERSIONABLE_MUTABLE_RECORDTYPEVERSION_COLUMN_NAME = Bytes.toBytes("$VersionableMutableRecordTypeVersion"); 58 72 private static final String RECORD_TABLE = "recordTable"; 59 73 private HTable recordTable; 60 74 private final TypeManager typeManager; 61 75 private final IdGenerator idGenerator; 62 private Class<Record> recordClass; 63 64 public HBaseRepository(TypeManager typeManager, IdGenerator idGenerator, Class recordClass, 76 77 public HBaseRepository(TypeManager typeManager, IdGenerator idGenerator, 65 78 Configuration configuration) throws IOException { 66 79 this.typeManager = typeManager; 67 80 this.idGenerator = idGenerator; 68 this.recordClass = recordClass;69 81 try { 70 82 recordTable = new HTable(configuration, RECORD_TABLE); … … 72 84 HBaseAdmin admin = new HBaseAdmin(configuration); 73 85 HTableDescriptor tableDescriptor = new HTableDescriptor(RECORD_TABLE); 74 tableDescriptor.addFamily(new HColumnDescriptor( SYSTEM_COLUMN_FAMILY));86 tableDescriptor.addFamily(new HColumnDescriptor(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY)); 75 87 tableDescriptor.addFamily(new HColumnDescriptor(VERSIONABLE_SYSTEM_COLUMN_FAMILY, HConstants.ALL_VERSIONS, 76 88 "none", false, true, HConstants.FOREVER, false)); 89 tableDescriptor.addFamily(new HColumnDescriptor(NON_VERSIONABLE_COLUMN_FAMILY)); 77 90 tableDescriptor.addFamily(new HColumnDescriptor(VERSIONABLE_COLUMN_FAMILY, HConstants.ALL_VERSIONS, "none", 78 91 false, true, HConstants.FOREVER, false)); 79 tableDescriptor.addFamily(new HColumnDescriptor(NON_VERSIONABLE_COLUMN_FAMILY)); 92 tableDescriptor.addFamily(new HColumnDescriptor(VERSIONABLE_MUTABLE_COLUMN_FAMILY, HConstants.ALL_VERSIONS, 93 "none", false, true, HConstants.FOREVER, false)); 80 94 admin.createTable(tableDescriptor); 81 95 recordTable = new HTable(configuration, RECORD_TABLE); … … 86 100 return idGenerator; 87 101 } 88 89 public Record newRecord() throws RepositoryException { 90 try { 91 return (Record) recordClass.newInstance(); 92 } catch (Exception e) { 93 throw new RepositoryException("Exception occured while creating new Record object", e); 94 } 95 } 96 97 public Record newRecord(RecordId recordId) throws RepositoryException { 98 try { 99 Constructor<Record> constructor = recordClass.getConstructor(RecordId.class); 100 return constructor.newInstance(recordId); 101 } catch (Exception e) { 102 throw new RepositoryException("Exception occured while creating new Record object <" + recordId + ">", e); 103 } 104 } 105 106 public void create(Record record) throws RecordExistsException, RecordNotFoundException, InvalidRecordException, RepositoryException { 102 103 public Record newRecord() { 104 return new RecordImpl(); 105 } 106 107 public Record newRecord(RecordId recordId) { 108 ArgumentValidator.notNull(recordId, "recordId"); 109 return new RecordImpl(recordId); 110 } 111 112 public Record create(Record record) throws RecordExistsException, RecordNotFoundException, InvalidRecordException, 113 RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, 114 RepositoryException { 107 115 ArgumentValidator.notNull(record, "record"); 108 if (record.getFields().isEmpty()) { 116 if (record.getRecordTypeId() == null) { 117 throw new InvalidRecordException(record, "The recordType cannot be null for a record to be created."); 118 } 119 if (record.getNonVersionableFields().isEmpty() && record.getVersionableFields().isEmpty() 120 && record.getVersionableMutableFields().isEmpty()) { 109 121 throw new InvalidRecordException(record, "Creating an empty record is not allowed"); 110 122 } 111 123 112 RecordId recordId = record.getId(); 124 Record newRecord = record.clone(); 125 126 RecordId recordId = newRecord.getId(); 113 127 if (recordId == null) { 114 128 recordId = idGenerator.newRecordId(); 115 record.setId(recordId);129 newRecord.setId(recordId); 116 130 } else { 117 131 RecordId masterRecordId = recordId.getMaster(); 118 if ( masterRecordId != null) {132 if (!recordId.equals(masterRecordId)) { 119 133 Get get = new Get(masterRecordId.toBytes()); 120 134 Result masterResult; … … 122 136 masterResult = recordTable.get(get); 123 137 } catch (IOException e) { 124 throw new RepositoryException("Exception occured while checking existence of master record <"+ recordId + ">", e); 138 throw new RepositoryException("Exception occured while checking existence of master record <" 139 + recordId + ">", e); 125 140 } 126 141 if (masterResult.isEmpty()) { 127 throw new RecordNotFoundException(record); 128 } 129 } 130 } 131 132 Get get = new Get(recordId.toBytes()); 133 Result result; 142 throw new RecordNotFoundException(newRecord); 143 } 144 } 145 } 146 byte[] rowId = recordId.toBytes(); 134 147 try { 135 result = recordTable.get(get); 136 } catch (IOException e) { 137 throw new RepositoryException("Exception occured while checking if record <" + recordId + "> already exists", e); 138 } 139 if (!result.isEmpty()) { 140 throw new RecordExistsException(record); 141 } 142 Put put; 143 try { 144 put = createPut(record, Long.valueOf(1)); 148 if (recordTable.exists(new Get(rowId))) { 149 throw new RecordExistsException(newRecord); 150 } 151 Record dummyOriginalRecord = newRecord(); 152 dummyOriginalRecord.setVersion(Long.valueOf(1)); 153 Put put = new Put(record.getId().toBytes()); 154 putRecord(newRecord, dummyOriginalRecord, Long.valueOf(1), put); 145 155 recordTable.put(put); 146 156 } catch (IOException e) { 147 throw new RepositoryException("Exception occured while creating record <" + recordId +"> in HBase table", e); 148 } 149 record.setVersion(Long.valueOf(1)); 150 } 151 152 public Record read(RecordId recordId, String... fieldIds) throws RecordNotFoundException, RepositoryException { 153 return read(recordId, null, fieldIds); 154 } 155 156 public Record read(RecordId recordId, Long version, String... fieldIds) 157 throws RecordNotFoundException, RepositoryException { 157 throw new RepositoryException("Exception occured while creating record <" + recordId + "> in HBase table", 158 e); 159 } 160 newRecord.setVersion(Long.valueOf(1)); 161 return newRecord; 162 } 163 164 public Record update(Record record) throws RecordNotFoundException, InvalidRecordException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException { 165 ArgumentValidator.notNull(record, "record"); 166 if (record.getRecordTypeId() == null) { 167 throw new InvalidRecordException(record, "The recordType cannot be null for a record to be updated."); 168 } 169 Get get = new Get(record.getId().toBytes()); 170 try { 171 if (!recordTable.exists(get)) { 172 throw new RecordNotFoundException(record); 173 } 174 } catch (IOException e) { 175 throw new RepositoryException("Exception occured while retrieving original record <" + record.getId() 176 + "> from HBase table", e); 177 } 178 Record newRecord = record.clone(); 179 Record originalRecord = read(newRecord.getId()); 180 181 Put put = new Put(newRecord.getId().toBytes()); 182 if (putRecord(newRecord, originalRecord, originalRecord.getVersion() + 1, put)) { 183 try { 184 recordTable.put(put); 185 } catch (IOException e) { 186 throw new RepositoryException("Exception occured while putting updated record <" + record.getId() 187 + "> on HBase table", e); 188 } 189 } 190 return newRecord; 191 } 192 193 private boolean putRecord(Record record, Record originalRecord, Long version, Put put) throws RecordTypeNotFoundException, FieldGroupNotFoundException, 194 FieldDescriptorNotFoundException, RepositoryException { 195 String recordTypeId = record.getRecordTypeId(); 196 Long recordTypeVersion = record.getRecordTypeVersion(); 197 198 RecordType recordType = typeManager.getRecordType(recordTypeId, recordTypeVersion); 199 200 boolean changed = false; 201 boolean versionableChanged = false; 202 if (putNonVersionableFields(record, originalRecord, recordType, put)) { 203 changed = true; 204 } 205 if (putVersionableFields(record, originalRecord, recordType, version, put)) { 206 changed = true; 207 versionableChanged = true; 208 } 209 if (putVersionableMutableFields(record, originalRecord, recordType, version, put)) { 210 changed = true; 211 versionableChanged = true; 212 } 213 if (!versionableChanged) { 214 version = originalRecord.getVersion(); 215 } 216 if (changed) { 217 recordTypeId = recordType.getId(); 218 recordTypeVersion = recordType.getVersion(); 219 put.add(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEID_COLUMN_NAME, Bytes.toBytes(recordTypeId)); 220 put.add(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEVERSION_COLUMN_NAME, Bytes.toBytes(recordTypeVersion)); 221 record.setRecordType(recordTypeId, recordTypeVersion); 222 put.add(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 223 } 224 record.setVersion(version); 225 return changed; 226 } 227 private boolean putNonVersionableFields(Record record, Record originalRecord, RecordType recordType, Put put) throws FieldGroupNotFoundException, FieldDescriptorNotFoundException, 228 RepositoryException { 229 if (putFieldGroupFields(record.getNonVersionableFields(), record.getNonVersionableFieldsToDelete(), originalRecord.getNonVersionableFields(), recordType.getNonVersionableFieldGroupId(), recordType 230 .getNonVersionableFieldGroupVersion(), NON_VERSIONABLE_COLUMN_FAMILY, null, put)) { 231 put.add(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, NON_VERSIONABLE_RECORDTYPEID_COLUMN_NAME, Bytes.toBytes(recordType.getId())); 232 put.add(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, NON_VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME, Bytes.toBytes(recordType.getVersion())); 233 record.setNonVersionableRecordType(recordType.getId(), recordType.getVersion()); 234 return true; 235 } 236 return false; 237 } 238 239 private boolean putVersionableFields(Record record, Record originalRecord, RecordType recordType, Long version, 240 Put put) throws FieldGroupNotFoundException, FieldDescriptorNotFoundException, 241 RepositoryException { 242 if (putFieldGroupFields(record.getVersionableFields(), record.getVersionableFieldsToDelete(), originalRecord.getVersionableFields(), recordType.getVersionableFieldGroupId(), recordType 243 .getVersionableFieldGroupVersion(), VERSIONABLE_COLUMN_FAMILY, version, put)) { 244 put.add(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_RECORDTYPEID_COLUMN_NAME, version, Bytes.toBytes(recordType.getId())); 245 put.add(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME, version, Bytes.toBytes(recordType.getVersion())); 246 record.setVersionableRecordType(recordType.getId(), recordType.getVersion()); 247 return true; 248 } 249 return false; 250 } 251 252 private boolean putVersionableMutableFields(Record record, Record originalRecord, 253 RecordType recordType, Long version, Put put) throws FieldGroupNotFoundException, 254 FieldDescriptorNotFoundException, RepositoryException { 255 if (putFieldGroupFields(record.getVersionableMutableFields(), record.getVersionableMutableFieldsToDelete(), originalRecord.getVersionableMutableFields(), recordType.getVersionableMutableFieldGroupId(), 256 recordType.getVersionableMutableFieldGroupVersion(), VERSIONABLE_MUTABLE_COLUMN_FAMILY, 257 version, put)) { 258 put.add(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_MUTABLE_RECORDTYPEID_COLUMN_NAME, version, Bytes.toBytes(recordType.getId())); 259 put.add(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_MUTABLE_RECORDTYPEVERSION_COLUMN_NAME, version, Bytes.toBytes(recordType.getVersion())); 260 record.setVersionableMutableRecordType(recordType.getId(), recordType.getVersion()); 261 return true; 262 } 263 return false; 264 } 265 266 private boolean putFieldGroupFields(Map<String, Object> fields, List<String> fieldsToDelete, Map<String, Object> originalFields, String fieldGroupId, Long fieldGroupVersion, 267 byte[] columnFamily, Long version, Put put) throws FieldGroupNotFoundException, 268 FieldDescriptorNotFoundException, RepositoryException { 269 boolean changed = false; 270 // Update fields 271 for (Entry<String, Object> field : fields.entrySet()) { 272 String fieldId = field.getKey(); 273 Object newValue = field.getValue(); 274 Object originalValue = originalFields.get(fieldId); 275 if (((newValue == null) && (originalValue != null)) || !newValue.equals(originalValue)) { 276 byte[] fieldIdAsBytes = Bytes.toBytes(fieldId); 277 FieldGroup fieldGroup = typeManager.getFieldGroup(fieldGroupId, fieldGroupVersion); 278 FieldGroupEntry fieldGroupEntry = fieldGroup.getFieldGroupEntry(fieldId); 279 FieldDescriptor fieldDescriptor = typeManager.getFieldDescriptor(fieldGroupEntry.getFieldDescriptorId(), 280 fieldGroupEntry.getFieldDescriptorVersion()); 281 ValueType valueType = fieldDescriptor.getValueType(); 282 283 // TODO validate with Class#isAssignableFrom() 284 byte[] fieldValue = valueType.toBytes(field.getValue()); 285 byte[] prefixedValue = EncodingUtil.prefixValue(fieldValue, EncodingUtil.EXISTS_FLAG); 286 287 if (version != null) { 288 put.add(columnFamily, fieldIdAsBytes, version, prefixedValue); 289 } else { 290 put.add(columnFamily, fieldIdAsBytes, prefixedValue); 291 } 292 changed = true; 293 } 294 } 295 // Delete fields 296 for (String fieldToDelete : fieldsToDelete) { 297 if (originalFields.get(fieldToDelete) != null) { 298 if (version != null) { 299 put.add(columnFamily, Bytes.toBytes(fieldToDelete), version, new byte[]{EncodingUtil.DELETE_FLAG}); 300 } else { 301 put.add(columnFamily, Bytes.toBytes(fieldToDelete), new byte[]{EncodingUtil.DELETE_FLAG}); 302 } 303 changed = true; 304 } 305 } 306 return changed; 307 } 308 309 public Record read(RecordId recordId) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException { 310 return read(recordId, null); 311 } 312 313 public Record read(RecordId recordId, List<String> nonVersionableFieldIds, List<String> versionableFieldIds, List<String> versionableMutableFieldIds) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException { 314 return read(recordId, null, nonVersionableFieldIds, versionableFieldIds, versionableMutableFieldIds); 315 } 316 317 public Record read(RecordId recordId, Long version) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException { 318 return read(recordId, version, null, null, null); 319 } 320 321 public Record read(RecordId recordId, Long version, List<String> nonVersionableFieldIds, List<String> versionableFieldIds, List<String> versionableMutableFieldIds) throws RecordNotFoundException, RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException { 158 322 ArgumentValidator.notNull(recordId, "recordId"); 159 323 Record record = newRecord(); 160 324 record.setId(recordId); 161 record.setVersion(version);162 325 163 326 Get get = new Get(recordId.toBytes()); … … 165 328 get.setMaxVersions(); 166 329 } 167 if (fieldIds.length != 0) { 168 addFieldsToGet(get, record, fieldIds); 169 } 330 addFieldsToGet(get, nonVersionableFieldIds, versionableFieldIds, versionableMutableFieldIds); 170 331 Result result; 171 332 try { 333 if (!recordTable.exists(get)) { 334 throw new RecordNotFoundException(record); 335 } 172 336 result = recordTable.get(get); 173 337 } catch (IOException e) { 174 throw new RepositoryException("Exception occured while retrieving record <" + recordId +"> from HBase table", e); 175 } 176 if (result.isEmpty()) { 177 throw new RecordNotFoundException(record); 178 } 179 long currentVersion = Bytes.toLong(result.getValue(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME)); 338 throw new RepositoryException("Exception occured while retrieving record <" + recordId 339 + "> from HBase table", e); 340 } 341 long currentVersion = Bytes.toLong(result.getValue(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, 342 CURRENT_VERSION_COLUMN_NAME)); 180 343 if (version != null) { 181 344 if (currentVersion < version) { 182 345 throw new RecordNotFoundException(record); 183 346 } 347 record.setVersion(version); 184 348 } else { 185 349 record.setVersion(currentVersion); 186 350 } 187 351 188 extractFields(result, version, record); 352 if (extractFields(result, version, record)) { 353 Pair<String, Long> recordTypePair = extractRecordType(result, record); 354 record.setRecordType(recordTypePair.getV1(), recordTypePair.getV2()); 355 } 189 356 return record; 190 357 } 191 358 192 private void addFieldsToGet(Get get, Record record, String... fieldIds) throws RecordNotFoundException, RepositoryException { 193 String recordTypeId; 194 Long recordTypeVersion; 195 Get recordTypeGet = new Get(record.getId().toBytes()); 196 Long version = record.getVersion(); 197 if (version != null) { 198 get.getMaxVersions(); 199 } 200 get.addColumn(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME); 201 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEID_COLUMN_NAME); 202 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEVERSION_COLUMN_NAME); 203 Result recordTypeResult; 204 try { 205 recordTypeResult = recordTable.get(recordTypeGet); 206 } catch (IOException e) { 207 throw new RepositoryException("Exception occured while retrieving record <"+ record.getId() +"> from HBase table", e); 208 } 209 if (recordTypeResult.isEmpty()) { 210 throw new RecordNotFoundException(record); 211 } 212 359 private Pair<String, Long> extractRecordType(Result result, Record record) { 360 return new Pair<String, Long>(Bytes.toString(result.getValue(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, 361 RECORDTYPEID_COLUMN_NAME)), Bytes.toLong(result.getValue(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, 362 RECORDTYPEVERSION_COLUMN_NAME))); 363 } 364 365 private Pair<String, Long> extractNonVersionableRecordType(Result result, Record record) { 366 return new Pair<String, Long>(Bytes.toString(result.getValue(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, 367 NON_VERSIONABLE_RECORDTYPEID_COLUMN_NAME)), Bytes.toLong(result.getValue(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, 368 NON_VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME))); 369 } 370 371 private Pair<String, Long> extractVersionableRecordType(Result result, Long version, Record record) { 213 372 if (version == null) { 214 recordTypeId = Bytes.toString(recordTypeResult.getValue(VERSIONABLE_SYSTEM_COLUMN_FAMILY, 215 RECORDTYPEID_COLUMN_NAME)); 216 recordTypeVersion = Bytes.toLong(recordTypeResult.getValue(VERSIONABLE_SYSTEM_COLUMN_FAMILY, 217 RECORDTYPEID_COLUMN_NAME)); 373 // Get latest version 374 return new Pair<String, Long>(Bytes.toString(result.getValue(VERSIONABLE_SYSTEM_COLUMN_FAMILY, 375 VERSIONABLE_RECORDTYPEID_COLUMN_NAME)), Bytes.toLong(result.getValue(VERSIONABLE_SYSTEM_COLUMN_FAMILY, 376 VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME))); 377 218 378 } else { 219 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allVersionsMap = recordTypeResult 220 .getMap(); 221 NavigableMap<byte[], NavigableMap<Long, byte[]>> allVersionsSystemColumnFamilyMap = allVersionsMap 222 .get(VERSIONABLE_SYSTEM_COLUMN_FAMILY); 223 recordTypeId = Bytes.toString(allVersionsSystemColumnFamilyMap.get(RECORDTYPEID_COLUMN_NAME).ceilingEntry( 224 version).getValue()); 225 recordTypeVersion = Bytes.toLong(allVersionsSystemColumnFamilyMap.get(RECORDTYPEVERSION_COLUMN_NAME) 226 .ceilingEntry(version).getValue()); 227 } 228 229 RecordType recordType = typeManager.getRecordType(recordTypeId, recordTypeVersion); 230 231 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEID_COLUMN_NAME); 232 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEVERSION_COLUMN_NAME); 233 for (String fieldId : fieldIds) { 234 byte[] columnFamily = recordType.getFieldDescriptor(fieldId).isVersionable() ? VERSIONABLE_COLUMN_FAMILY 235 : NON_VERSIONABLE_COLUMN_FAMILY; 236 get.addColumn(columnFamily, Bytes.toBytes(fieldId)); 237 } 238 } 239 240 private void extractFields(Result result, Long version, Record record) throws RepositoryException { 241 if (version != null) { 242 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> mapWithVersions = result.getMap(); 243 extractRecordTypeInfoOnVersion(version, record, mapWithVersions.get(VERSIONABLE_SYSTEM_COLUMN_FAMILY)); 244 extractVersionableFieldsOnVersion(version, record, mapWithVersions.get(VERSIONABLE_COLUMN_FAMILY)); 379 // Get on version 380 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allVersionsMap = result.getMap(); 381 NavigableMap<byte[], NavigableMap<Long, byte[]>> versionableSystemCFversions = allVersionsMap.get(VERSIONABLE_SYSTEM_COLUMN_FAMILY); 382 return extractVersionRecordType(version, versionableSystemCFversions, 383 VERSIONABLE_RECORDTYPEID_COLUMN_NAME, VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME); 384 } 385 } 386 387 private Pair<String, Long> extractVersionableMutableRecordType(Result result, Long version, Record record) { 388 if (version == null) { 389 // Get latest version 390 return new Pair<String, Long>(Bytes.toString(result.getValue(VERSIONABLE_SYSTEM_COLUMN_FAMILY, 391 VERSIONABLE_MUTABLE_RECORDTYPEID_COLUMN_NAME)), Bytes.toLong(result.getValue(VERSIONABLE_SYSTEM_COLUMN_FAMILY, 392 VERSIONABLE_MUTABLE_RECORDTYPEVERSION_COLUMN_NAME))); 245 393 } else { 246 extractLatestRecordTypeInfo(result, record); 247 extractLatestVersionableFields(result, record); 248 } 249 extractNonVersionableFields(result, record); 250 } 251 252 public void update(Record record) throws RecordNotFoundException, InvalidRecordException, RepositoryException { 253 ArgumentValidator.notNull(record, "record"); 254 Get get = new Get(record.getId().toBytes()); 255 Result result; 256 try { 257 result = recordTable.get(get); 258 } catch (IOException e) { 259 throw new RepositoryException("Exception occured while retrieving original record <" + record.getId() +"> from HBase table", e); 260 } 261 if (result.isEmpty()) { 262 throw new RecordNotFoundException(record); 263 } 264 // TODO lock row 265 NavigableMap<byte[], byte[]> systemFamilyMap = result.getFamilyMap(SYSTEM_COLUMN_FAMILY); 266 long version = Bytes.toLong(systemFamilyMap.get(CURRENT_VERSION_COLUMN_NAME)); 267 if (record.getFields().isEmpty() && record.getDeleteFields().isEmpty()) { 268 throw new InvalidRecordException(record, "No fields to update or delete"); 269 } 270 long newVersion = version + 1; 271 try { 272 recordTable.put(createPut(record, newVersion)); 273 } catch (IOException e) { 274 throw new RepositoryException("Exception occured while putting updated record <" + record.getId() +"> on HBase table", e); 275 } 276 record.setVersion(newVersion); 394 // Get on version 395 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allVersionsMap = result.getMap(); 396 NavigableMap<byte[], NavigableMap<Long, byte[]>> versionableSystemCFversions = allVersionsMap.get(VERSIONABLE_SYSTEM_COLUMN_FAMILY); 397 return extractVersionRecordType(version, versionableSystemCFversions, 398 VERSIONABLE_MUTABLE_RECORDTYPEID_COLUMN_NAME, VERSIONABLE_MUTABLE_RECORDTYPEVERSION_COLUMN_NAME); 399 } 400 } 401 402 private Pair<String, Long> extractVersionRecordType(Long version, 403 NavigableMap<byte[], NavigableMap<Long, byte[]>> versionableSystemCFversions, 404 byte[] recordTypeIdColumnName, byte[] recordTypeVersionColumnName) { 405 Entry<Long, byte[]> ceilingEntry = versionableSystemCFversions.get(recordTypeIdColumnName).ceilingEntry(version); 406 String recordTypeId = null; 407 if (ceilingEntry != null) { 408 recordTypeId = Bytes.toString(ceilingEntry.getValue()); 409 } 410 Long recordTypeVersion = null; 411 ceilingEntry = versionableSystemCFversions.get(recordTypeVersionColumnName).ceilingEntry(version); 412 if (ceilingEntry != null) { 413 recordTypeVersion = Bytes.toLong(ceilingEntry.getValue()); 414 } 415 Pair<String, Long> recordType = new Pair<String, Long>(recordTypeId, recordTypeVersion); 416 return recordType; 417 } 418 419 private List<Pair<String, Object>> extractFields(NavigableMap<byte[], byte[]> familyMap) throws FieldDescriptorNotFoundException, RepositoryException { 420 List<Pair<String, Object>> fields = new ArrayList<Pair<String, Object>>(); 421 if (familyMap != null) { 422 for (Entry<byte[], byte[]> entry : familyMap.entrySet()) { 423 Pair<String, Object> field = extractField(entry.getKey(), entry.getValue()); 424 if (field != null) { 425 fields.add(field); 426 } 427 } 428 } 429 return fields; 430 } 431 432 private List<Pair<String, Object>> extractVersionFields(Long version, NavigableMap<byte[], NavigableMap<Long, byte[]>> mapWithVersions) throws FieldDescriptorNotFoundException, RepositoryException { 433 List<Pair<String, Object>> fields = new ArrayList<Pair<String, Object>>(); 434 if (mapWithVersions != null) { 435 for (Entry<byte[], NavigableMap<Long, byte[]>> columnWithAllVersions : mapWithVersions.entrySet()) { 436 NavigableMap<Long, byte[]> allValueVersions = columnWithAllVersions.getValue(); 437 Entry<Long, byte[]> ceilingEntry = allValueVersions.ceilingEntry(version); 438 if (ceilingEntry != null) { 439 Pair<String, Object> field = extractField(columnWithAllVersions.getKey(), ceilingEntry.getValue()); 440 if (field != null) { 441 fields.add(field); 442 } 443 } 444 } 445 } 446 return fields; 447 } 448 449 private Pair<String, Object> extractField(byte[] key, byte[] prefixedValue) throws FieldDescriptorNotFoundException, RepositoryException { 450 if (EncodingUtil.isDeletedField(prefixedValue)) { 451 return null; 452 } 453 String fieldId = Bytes.toString(key); 454 ValueType valueType = typeManager.getFieldDescriptor(fieldId, null).getValueType(); 455 Object value = valueType.fromBytes(EncodingUtil.stripPrefix(prefixedValue)); 456 return new Pair<String, Object>(fieldId, value); 457 } 458 459 460 private void addFieldsToGet(Get get, List<String> nonVersionableFieldIds, List<String> versionableFieldIds, List<String> versionableMutableFieldIds) 461 throws RecordNotFoundException, RepositoryException { 462 boolean added = false; 463 added |= addFieldsToGet(get, nonVersionableFieldIds, NON_VERSIONABLE_COLUMN_FAMILY); 464 added |= addFieldsToGet(get, versionableFieldIds, VERSIONABLE_COLUMN_FAMILY); 465 added |= addFieldsToGet(get, versionableMutableFieldIds, VERSIONABLE_MUTABLE_COLUMN_FAMILY); 466 if (added) { 467 addSystemColumnsToGet(get); 468 } 469 } 470 471 472 private boolean addFieldsToGet(Get get, List<String> fieldIds, byte[] columnFamily) { 473 boolean added = false; 474 if (fieldIds != null) { 475 for (String fieldId : fieldIds) { 476 get.addColumn(columnFamily, Bytes.toBytes(fieldId)); 477 } 478 added = true; 479 } 480 return added; 481 } 482 483 private void addSystemColumnsToGet(Get get) { 484 get.addColumn(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME); 485 get.addColumn(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEID_COLUMN_NAME); 486 get.addColumn(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEVERSION_COLUMN_NAME); 487 get.addColumn(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, NON_VERSIONABLE_RECORDTYPEID_COLUMN_NAME); 488 get.addColumn(NON_VERSIONABLE_SYSTEM_COLUMN_FAMILY, NON_VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME); 489 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_RECORDTYPEID_COLUMN_NAME); 490 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_RECORDTYPEVERSION_COLUMN_NAME); 491 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_MUTABLE_RECORDTYPEID_COLUMN_NAME); 492 get.addColumn(VERSIONABLE_SYSTEM_COLUMN_FAMILY, VERSIONABLE_MUTABLE_RECORDTYPEVERSION_COLUMN_NAME); 493 } 494 495 private boolean extractFields(Result result, Long version, Record record) throws RecordTypeNotFoundException, FieldGroupNotFoundException, FieldDescriptorNotFoundException, RepositoryException { 496 boolean retrieved = false; 497 retrieved |= extractNonVersionableFields(result, record); 498 retrieved |= extractVersionableFields(result, version, record); 499 retrieved |= extractVersionableMutableFields(result, version, record); 500 return retrieved; 501 } 502 503 private boolean extractNonVersionableFields(Result result, Record record) throws RecordTypeNotFoundException, 504 RepositoryException, FieldGroupNotFoundException, FieldDescriptorNotFoundException { 505 boolean retrieved = false; 506 Pair<String, Long> recordTypePair = extractNonVersionableRecordType(result, record); 507 String recordTypeId = recordTypePair.getV1(); 508 Long recordTypeVersion = recordTypePair.getV2(); 509 // If there is no recordType, there can't be any fields 510 if (recordTypeId != null) { 511 List<Pair<String, Object>> fields = extractFields(result.getFamilyMap(NON_VERSIONABLE_COLUMN_FAMILY)); 512 if (!fields.isEmpty()) { 513 for (Pair<String, Object> field : fields) { 514 record.setNonVersionableField(field.getV1(), field.getV2()); 515 } 516 record.setNonVersionableRecordType(recordTypeId, recordTypeVersion); 517 retrieved = true; 518 } 519 } 520 return retrieved; 521 } 522 523 private boolean extractVersionableFields(Result result, Long version, Record record) 524 throws RecordTypeNotFoundException, RepositoryException, FieldGroupNotFoundException, 525 FieldDescriptorNotFoundException { 526 boolean retrieved = false; 527 Pair<String, Long> recordTypePair = extractVersionableRecordType(result, version, record); 528 String recordTypeId = recordTypePair.getV1(); 529 Long recordTypeVersion = recordTypePair.getV2(); 530 // If there is no recordType, there can't be any fields 531 if (recordTypeId != null) { 532 List<Pair<String, Object>> fields; 533 if (version == null) { 534 fields = extractFields(result.getFamilyMap(VERSIONABLE_COLUMN_FAMILY)); 535 } else { 536 fields = extractVersionFields(version, result.getMap().get(VERSIONABLE_COLUMN_FAMILY)); 537 } 538 if (!fields.isEmpty()) { 539 for (Pair<String, Object> field : fields) { 540 record.setVersionableField(field.getV1(), field.getV2()); 541 } 542 record.setVersionableRecordType(recordTypeId, recordTypeVersion); 543 retrieved = true; 544 } 545 } 546 return retrieved; 547 } 548 549 private boolean extractVersionableMutableFields(Result result, Long version, Record record) 550 throws RecordTypeNotFoundException, RepositoryException, FieldGroupNotFoundException, 551 FieldDescriptorNotFoundException { 552 boolean retrieved = false; 553 Pair<String, Long> recordTypePair = extractVersionableMutableRecordType(result, version, record); 554 String recordTypeId = recordTypePair.getV1(); 555 Long recordTypeVersion = recordTypePair.getV2(); 556 // If there is no recordType, there can't be any fields 557 if (recordTypeId != null) { 558 List<Pair<String, Object>> fields; 559 if (version == null) { 560 fields = extractFields(result.getFamilyMap(VERSIONABLE_MUTABLE_COLUMN_FAMILY)); 561 } else { 562 fields = extractVersionFields(version, result.getMap().get(VERSIONABLE_MUTABLE_COLUMN_FAMILY)); 563 } 564 if (!fields.isEmpty()) { 565 for (Pair<String, Object> field : fields) { 566 record.setVersionableMutableField(field.getV1(), field.getV2()); 567 } 568 record.setVersionableMutableRecordType(recordTypeId, recordTypeVersion); 569 retrieved = true; 570 } 571 } 572 return retrieved; 277 573 } 278 574 … … 283 579 recordTable.delete(delete); 284 580 } catch (IOException e) { 285 throw new RepositoryException("Exception occured while deleting record <"+recordId+"> from HBase table", e); 286 } 287 288 } 289 290 private Put createPut(Record record, Long version) throws RepositoryException { 291 String recordTypeId = record.getRecordTypeId(); 292 long recordTypeVersion = record.getRecordTypeVersion(); 293 RecordType recordType = typeManager.getRecordType(recordTypeId, recordTypeVersion); 294 295 Put put = new Put(record.getId().toBytes()); 296 put.add(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 297 put.add(VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEID_COLUMN_NAME, version, Bytes.toBytes(recordTypeId)); 298 put.add(VERSIONABLE_SYSTEM_COLUMN_FAMILY, RECORDTYPEVERSION_COLUMN_NAME, version, Bytes 299 .toBytes(recordTypeVersion)); 300 putFields(record, version, recordType, put); 301 putDeleteFields(record, version, recordType, put); 302 return put; 303 } 304 305 private void putFields(Record record, Long version, RecordType recordType, Put put) { 306 for (Entry<String, Object> field : record.getFields().entrySet()) { 307 String fieldId = field.getKey(); 308 byte[] fieldIdAsBytes = Bytes.toBytes(fieldId); 309 FieldDescriptor fieldDescriptor = recordType.getFieldDescriptor(fieldId); 310 ValueType valueType = fieldDescriptor.getValueType(); 311 // TODO validate with Class#isAssignableFrom() 312 byte[] fieldValue = valueType.toBytes(field.getValue()); 313 byte[] prefixedValue = EncodingUtil.prefixValue(fieldValue, EncodingUtil.EXISTS_FLAG); 314 315 if (fieldDescriptor.isVersionable()) { 316 put.add(VERSIONABLE_COLUMN_FAMILY, fieldIdAsBytes, version, prefixedValue); 317 } else { 318 put.add(NON_VERSIONABLE_COLUMN_FAMILY, fieldIdAsBytes, prefixedValue); 319 } 320 } 321 } 322 323 private void putDeleteFields(Record record, Long version, RecordType recordType, Put put) { 324 for (String deleteFieldId : record.getDeleteFields()) { 325 FieldDescriptor fieldDescriptor = recordType.getFieldDescriptor(deleteFieldId); 326 if (fieldDescriptor.isVersionable()) { 327 put.add(VERSIONABLE_COLUMN_FAMILY, Bytes.toBytes(deleteFieldId), version, 328 new byte[] { EncodingUtil.DELETE_FLAG }); 329 } else { 330 put.add(NON_VERSIONABLE_COLUMN_FAMILY, Bytes.toBytes(deleteFieldId), 331 new byte[] { EncodingUtil.DELETE_FLAG }); 332 } 333 } 334 } 335 336 private void extractVersionableFieldsOnVersion(Long version, Record record, 337 NavigableMap<byte[], NavigableMap<Long, byte[]>> mapWithVersions) throws RepositoryException { 338 if (mapWithVersions != null) { 339 Set<Entry<byte[], NavigableMap<Long, byte[]>>> columnSetWithAllVersions = mapWithVersions.entrySet(); 340 for (Entry<byte[], NavigableMap<Long, byte[]>> columnWithAllVersions : columnSetWithAllVersions) { 341 NavigableMap<Long, byte[]> allValueVersions = columnWithAllVersions.getValue(); 342 Entry<Long, byte[]> ceilingEntry = allValueVersions.ceilingEntry(version); 343 if (ceilingEntry != null) { 344 extractField(record, columnWithAllVersions.getKey(), ceilingEntry.getValue()); 345 } 346 } 347 } 348 } 349 350 private void extractRecordTypeInfoOnVersion(Long version, Record record, 351 NavigableMap<byte[], NavigableMap<Long, byte[]>> mapWithVersions) { 352 NavigableMap<Long, byte[]> recordTypeIdVersions = mapWithVersions.get(RECORDTYPEID_COLUMN_NAME); 353 Entry<Long, byte[]> recordTypeIdEntry = recordTypeIdVersions.ceilingEntry(version); 354 NavigableMap<Long, byte[]> recordTypeVersionVersions = mapWithVersions.get(RECORDTYPEVERSION_COLUMN_NAME); 355 Entry<Long, byte[]> recordTypeVersionEntry = recordTypeVersionVersions.ceilingEntry(version); 356 record.setRecordType(Bytes.toString(recordTypeIdEntry.getValue()), Bytes.toLong(recordTypeVersionEntry 357 .getValue())); 358 } 359 360 private void extractLatestRecordTypeInfo(Result result, Record record) { 361 NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(VERSIONABLE_SYSTEM_COLUMN_FAMILY); 362 record.setRecordType(Bytes.toString(familyMap.get(RECORDTYPEID_COLUMN_NAME)), Bytes.toLong(familyMap 363 .get(RECORDTYPEVERSION_COLUMN_NAME))); 364 } 365 366 private void extractLatestVersionableFields(Result result, Record record) throws RepositoryException { 367 NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(VERSIONABLE_COLUMN_FAMILY); 368 extractFields(record, familyMap); 369 } 370 371 private void extractNonVersionableFields(Result result, Record record) throws RepositoryException { 372 NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(NON_VERSIONABLE_COLUMN_FAMILY); 373 extractFields(record, familyMap); 374 } 375 376 private void extractFields(Record record, NavigableMap<byte[], byte[]> familyMap) throws RepositoryException { 377 if (familyMap != null) { 378 for (Entry<byte[], byte[]> entry : familyMap.entrySet()) { 379 extractField(record, entry.getKey(), entry.getValue()); 380 } 381 } 382 } 383 384 private void extractField(Record record, byte[] key, byte[] prefixedValue) throws RepositoryException { 385 if (!EncodingUtil.isDeletedField(prefixedValue)) { 386 RecordType recordType = typeManager.getRecordType(record.getRecordTypeId()); 387 String fieldId = Bytes.toString(key); 388 FieldDescriptor fieldDescriptor = recordType.getFieldDescriptor(fieldId); 389 Object value = fieldDescriptor.getValueType().fromBytes(EncodingUtil.stripPrefix(prefixedValue)); 390 record.setField(fieldId, value); 391 } 581 throw new RepositoryException( 582 "Exception occured while deleting record <" + recordId + "> from HBase table", e); 583 } 584 392 585 } 393 586 } -
projects/lily/trunk/repository/impl/src/main/java/org/lilycms/repository/impl/HBaseTypeManager.java
r3959 r3977 17 17 18 18 import java.io.IOException; 19 import java.lang.reflect.Constructor;20 import java.util.ArrayList;21 19 import java.util.Collection; 22 20 import java.util.HashMap; 23 import java.util.HashSet;24 21 import java.util.List; 25 22 import java.util.Map; 26 23 import java.util.NavigableMap; 27 import java.util.Set;28 24 import java.util.Map.Entry; 29 25 … … 39 35 import org.apache.hadoop.hbase.util.Bytes; 40 36 import org.lilycms.repository.api.FieldDescriptor; 37 import org.lilycms.repository.api.FieldDescriptorExistsException; 38 import org.lilycms.repository.api.FieldDescriptorNotFoundException; 39 import org.lilycms.repository.api.FieldDescriptorUpdateException; 40 import org.lilycms.repository.api.FieldGroup; 41 import org.lilycms.repository.api.FieldGroupEntry; 42 import org.lilycms.repository.api.FieldGroupExistsException; 43 import org.lilycms.repository.api.FieldGroupNotFoundException; 41 44 import org.lilycms.repository.api.IdGenerator; 42 45 import org.lilycms.repository.api.PrimitiveValueType; 43 46 import org.lilycms.repository.api.RecordType; 47 import org.lilycms.repository.api.RecordTypeExistsException; 48 import org.lilycms.repository.api.RecordTypeNotFoundException; 44 49 import org.lilycms.repository.api.RepositoryException; 45 50 import org.lilycms.repository.api.TypeManager; 46 51 import org.lilycms.repository.api.ValueType; 47 52 import org.lilycms.util.ArgumentValidator; 53 import org.lilycms.util.Pair; 48 54 49 55 public class HBaseTypeManager implements TypeManager { 50 56 51 57 private static final String TYPE_TABLE = "typeTable"; 52 private static final byte[] SYSTEM_COLUMN_FAMILY = Bytes.toBytes("systemCF"); 53 private static final byte[] SYSTEM_VERSIONABLE_COLUMN_FAMILY = Bytes.toBytes("systemVersionableCF"); 54 private static final byte[] FIELDDESCRIPTOR_COLUMN_FAMILY = Bytes.toBytes("fieldDescriptorCF"); 55 private static final byte[] CURRENT_VERSION_COLUMN_NAME = Bytes.toBytes("currentVersion"); 56 private static final byte[] VALUE_TYPE_COLUMN_NAME = Bytes.toBytes("valueType"); 57 private static final byte[] MANDATORY_COLUMN_NAME = Bytes.toBytes("mandatory"); 58 private static final byte[] VERSIONABLE_COLUMN_NAME = Bytes.toBytes("versionable"); 58 private static final byte[] NON_VERSIONABLE_COLUMN_FAMILY = Bytes.toBytes("nonVersionableCF"); 59 private static final byte[] VERSIONABLE_COLUMN_FAMILY = Bytes.toBytes("versionableCF"); 60 61 private static final byte[] CURRENT_VERSION_COLUMN_NAME = Bytes.toBytes("$currentVersion"); 62 63 private static final byte[] RECORDTYPE_NONVERSIONABLEFIELDGROUP_COLUMN_NAME = Bytes.toBytes("$nonVersionableFG"); 64 private static final byte[] RECORDTYPE_VERSIONABLEFIELDGROUP_COLUMN_NAME = Bytes.toBytes("$versionableFG"); 65 private static final byte[] RECORDTYPE_VERSIONABLEMUTABLEFIELDGROUP_COLUMN_NAME = Bytes 66 .toBytes("$versionableMutableFG"); 67 private static final byte[] FIELDDESCRIPTOR_GLOBALNAME_COLUMN_NAME = Bytes.toBytes("$globalName"); 68 private static final byte[] FIELDDESCRIPTOR_VALUETYPE_COLUMN_NAME = Bytes.toBytes("$valueType"); 59 69 60 70 private HTable typeTable; 61 71 private IdGenerator idGenerator; 62 private Class<RecordType> recordTypeClass; 63 private Class<FieldDescriptor> fieldDescriptorClass; 64 65 public HBaseTypeManager(IdGenerator idGenerator, Class recordTypeClass, Class fieldDescriptorClass, Configuration configuration) 66 throws IOException { 72 73 public HBaseTypeManager(IdGenerator idGenerator, Configuration configuration) throws IOException { 67 74 this.idGenerator = idGenerator; 68 this.recordTypeClass = recordTypeClass;69 this.fieldDescriptorClass = fieldDescriptorClass;70 75 try { 71 76 typeTable = new HTable(configuration, TYPE_TABLE); … … 73 78 HBaseAdmin admin = new HBaseAdmin(configuration); 74 79 HTableDescriptor tableDescriptor = new HTableDescriptor(TYPE_TABLE); 75 tableDescriptor.addFamily(new HColumnDescriptor(SYSTEM_COLUMN_FAMILY)); 76 tableDescriptor.addFamily(new HColumnDescriptor(SYSTEM_VERSIONABLE_COLUMN_FAMILY, HConstants.ALL_VERSIONS, 77 "none", false, true, HConstants.FOREVER, false)); 78 tableDescriptor.addFamily(new HColumnDescriptor(FIELDDESCRIPTOR_COLUMN_FAMILY, HConstants.ALL_VERSIONS, 79 "none", false, true, HConstants.FOREVER, false)); 80 tableDescriptor.addFamily(new HColumnDescriptor(NON_VERSIONABLE_COLUMN_FAMILY)); 81 tableDescriptor.addFamily(new HColumnDescriptor(VERSIONABLE_COLUMN_FAMILY, HConstants.ALL_VERSIONS, "none", 82 false, true, HConstants.FOREVER, false)); 80 83 admin.createTable(tableDescriptor); 81 84 typeTable = new HTable(configuration, TYPE_TABLE); … … 84 87 } 85 88 86 public RecordType newRecordType(String recordTypeId) throws RepositoryException { 89 public RecordType newRecordType(String recordTypeId) { 90 ArgumentValidator.notNull(recordTypeId, "recordTypeId"); 91 return new RecordTypeImpl(recordTypeId); 92 } 93 94 public RecordType createRecordType(RecordType recordType) throws RecordTypeExistsException, 95 FieldGroupNotFoundException, RepositoryException { 96 ArgumentValidator.notNull(recordType, "recordType"); 97 RecordType newRecordType = recordType.clone(); 98 Long recordTypeVersion = Long.valueOf(1); 99 byte[] rowId = Bytes.toBytes(recordType.getId()); 87 100 try { 88 Constructor<RecordType> constructor = recordTypeClass.getConstructor(String.class); 89 return constructor.newInstance(recordTypeId); 90 } catch (Exception e) { 91 throw new RepositoryException("Exception occured while creating new RecordType object", e); 92 } 93 } 94 95 public FieldDescriptor newFieldDescriptor(String fieldDescriptorId, ValueType valueType, boolean mandatory, 96 boolean versionable) throws RepositoryException { 97 try { 98 Constructor<FieldDescriptor> constructor = fieldDescriptorClass.getConstructor(String.class, 99 ValueType.class, boolean.class, boolean.class); 100 return constructor.newInstance(fieldDescriptorId, valueType, mandatory, versionable); 101 } catch (Exception e) { 102 throw new RepositoryException("Exception occured while creating new FieldDescriptor object", e); 103 } 104 } 105 106 public FieldDescriptor newFieldDescriptor(String fieldDescriptorId, Long version, ValueType valueType, 107 boolean mandatory, boolean versionable) throws RepositoryException { 108 try { 109 Constructor<FieldDescriptor> constructor = fieldDescriptorClass.getConstructor(String.class, Long.class, 110 ValueType.class, boolean.class, boolean.class); 111 return constructor.newInstance(fieldDescriptorId, version, valueType, mandatory, versionable); 112 } catch (Exception e) { 113 throw new RepositoryException("Exception occured while creating new FieldDescriptor object", e); 114 } 115 } 116 117 // TODO return a new RecordType object 118 public void createRecordType(RecordType recordType) throws RepositoryException { 119 ArgumentValidator.notNull(recordType, "recordType"); 120 List<Put> puts = new ArrayList<Put>(); 121 String recordTypeId = recordType.getId(); 122 Put put = new Put(EncodingUtil.generateRecordTypeRowKey(recordTypeId)); 123 long recordTypeVersion = 1; 124 recordType.setVersion(recordTypeVersion); 125 put.add(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(recordTypeVersion)); 126 Collection<FieldDescriptor> fieldDescriptors = recordType.getFieldDescriptors(); 127 for (FieldDescriptor fieldDescriptor : fieldDescriptors) { 128 puts.add(addFieldDescriptor(fieldDescriptor, recordTypeId, recordTypeVersion, put)); 129 } 130 puts.add(put); 131 try { 132 typeTable.put(puts); 101 if (typeTable.exists(new Get(rowId))) { 102 throw new RecordTypeExistsException(recordType); 103 } 104 105 Put put = new Put(rowId); 106 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(recordTypeVersion)); 107 String fieldGroupId = recordType.getNonVersionableFieldGroupId(); 108 if (fieldGroupId != null) { 109 newRecordType.setNonVersionableFieldGroupVersion(putFieldGroupOnRecordType(recordTypeVersion, put, 110 fieldGroupId, recordType.getNonVersionableFieldGroupVersion(), 111 RECORDTYPE_NONVERSIONABLEFIELDGROUP_COLUMN_NAME)); 112 } 113 114 fieldGroupId = recordType.getVersionableFieldGroupId(); 115 if (fieldGroupId != null) { 116 newRecordType.setVersionableFieldGroupVersion(putFieldGroupOnRecordType(recordTypeVersion, put, 117 fieldGroupId, recordType.getVersionableFieldGroupVersion(), 118 RECORDTYPE_VERSIONABLEFIELDGROUP_COLUMN_NAME)); 119 } 120 121 fieldGroupId = recordType.getVersionableMutableFieldGroupId(); 122 if (fieldGroupId != null) { 123 newRecordType.setVersionableMutableFieldGroupVersion(putFieldGroupOnRecordType(recordTypeVersion, put, 124 fieldGroupId, recordType.getVersionableMutableFieldGroupVersion(), 125 RECORDTYPE_VERSIONABLEMUTABLEFIELDGROUP_COLUMN_NAME)); 126 } 127 128 typeTable.put(put); 133 129 } catch (IOException e) { 134 130 throw new RepositoryException("Exception occured while creating recordType <" + recordType.getId() 135 131 + "> on HBase", e); 136 132 } 137 } 138 139 private Put addFieldDescriptor(FieldDescriptor fieldDescriptor, String recordTypeId, Long recordTypeVersion, 140 Put recordTypePut) throws RepositoryException { 141 String fieldDescriptorId = fieldDescriptor.getId(); 142 Put put = new Put(EncodingUtil.generateFieldDescriptorRowKey(recordTypeId, fieldDescriptorId)); 143 144 long fieldDescriptorVersion = getLatestFieldDescriptorVersion(recordTypeId, fieldDescriptorId) + 1; 145 put.add(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(fieldDescriptorVersion)); 146 put.add(SYSTEM_VERSIONABLE_COLUMN_FAMILY, VALUE_TYPE_COLUMN_NAME, fieldDescriptorVersion, fieldDescriptor 147 .getValueType().toBytes()); 148 put.add(SYSTEM_VERSIONABLE_COLUMN_FAMILY, MANDATORY_COLUMN_NAME, fieldDescriptorVersion, Bytes 149 .toBytes(fieldDescriptor.isMandatory())); 150 put.add(SYSTEM_VERSIONABLE_COLUMN_FAMILY, VERSIONABLE_COLUMN_NAME, fieldDescriptorVersion, Bytes 151 .toBytes(fieldDescriptor.isVersionable())); 152 153 recordTypePut.add(FIELDDESCRIPTOR_COLUMN_FAMILY, Bytes.toBytes(fieldDescriptorId), recordTypeVersion, 154 EncodingUtil.prefixValue(Bytes.toBytes(fieldDescriptorVersion), EncodingUtil.EXISTS_FLAG)); 155 156 return put; 157 } 158 159 public void updateRecordType(RecordType recordType) throws RepositoryException { 133 newRecordType.setVersion(recordTypeVersion); 134 return newRecordType; 135 } 136 137 public RecordType updateRecordType(RecordType recordType) throws RecordTypeNotFoundException, 138 FieldGroupNotFoundException, RepositoryException { 160 139 ArgumentValidator.notNull(recordType, "recordType"); 161 List<Put> puts = new ArrayList<Put>(); 162 String recordTypeId = recordType.getId(); 163 Put recordTypePut = new Put(EncodingUtil.generateRecordTypeRowKey(recordTypeId)); 164 RecordType originalRecordType = getRecordType(recordTypeId); 165 long newRecordTypeVersion = originalRecordType.getVersion() + 1; 140 RecordType newRecordType = recordType.clone(); 141 String id = recordType.getId(); 142 Put put = new Put(Bytes.toBytes(id)); 143 144 RecordType latestRecordType = getRecordType(id, null); 145 Long latestRecordTypeVersion = latestRecordType.getVersion(); 146 Long newRecordTypeVersion = latestRecordTypeVersion + 1; 147 166 148 boolean recordTypeChanged = false; 167 Map<String, FieldDescriptor> fieldDescriptors = new HashMap<String, FieldDescriptor>(); 168 for (FieldDescriptor fieldDescriptor : recordType.getFieldDescriptors()) { 169 fieldDescriptors.put(fieldDescriptor.getId(), fieldDescriptor); 170 } 171 Collection<FieldDescriptor> originalFieldDescriptors = originalRecordType.getFieldDescriptors(); 172 Set<FieldDescriptor> originalFieldDescriptorSet = new HashSet<FieldDescriptor>(originalFieldDescriptors); 173 for (FieldDescriptor originalFieldDescriptor : originalFieldDescriptors) { 174 String fieldDescriptorId = originalFieldDescriptor.getId(); 175 FieldDescriptor fieldDescriptor = fieldDescriptors.get(fieldDescriptorId); 176 if (fieldDescriptor != null) { 177 Put updateFieldDescriptorPut = updateFieldDescriptor(fieldDescriptor, originalFieldDescriptor, 178 recordTypeId, newRecordTypeVersion, recordTypePut); 179 if (updateFieldDescriptorPut != null) { 180 recordTypeChanged = true; 181 puts.add(updateFieldDescriptorPut); 182 } 183 fieldDescriptors.remove(fieldDescriptorId); 184 originalFieldDescriptorSet.remove(originalFieldDescriptor); 185 } 186 187 } 188 if (!fieldDescriptors.isEmpty()) { 149 // non-versionable field group 150 Pair<Boolean, Long> updateResult = updateFieldGroupOnRecordType(put, newRecordTypeVersion, recordType 151 .getNonVersionableFieldGroupId(), recordType.getNonVersionableFieldGroupVersion(), 152 latestRecordType.getNonVersionableFieldGroupId(), latestRecordType 153 .getNonVersionableFieldGroupVersion(), 154 RECORDTYPE_NONVERSIONABLEFIELDGROUP_COLUMN_NAME); 155 if (updateResult.getV1()) { 156 recordTypeChanged =true; 157 newRecordType.setNonVersionableFieldGroupVersion(updateResult.getV2()); 158 } 159 160 // versionable field group 161 updateResult = updateFieldGroupOnRecordType(put, newRecordTypeVersion, recordType.getVersionableFieldGroupId(), 162 recordType.getVersionableFieldGroupVersion(), latestRecordType.getVersionableFieldGroupId(), 163 latestRecordType.getVersionableFieldGroupVersion(), 164 RECORDTYPE_VERSIONABLEFIELDGROUP_COLUMN_NAME); 165 if (updateResult.getV1()) { 189 166 recordTypeChanged = true; 190 for (FieldDescriptor fieldDescriptor : fieldDescriptors.values()) { 191 puts.add(addFieldDescriptor(fieldDescriptor, recordTypeId, newRecordTypeVersion, recordTypePut)); 192 } 193 } 194 if (!originalFieldDescriptorSet.isEmpty()) { 167 newRecordType.setVersionableFieldGroupVersion(updateResult.getV2()); 168 } 169 170 // versionable mutable field group 171 updateResult = updateFieldGroupOnRecordType(put, newRecordTypeVersion, recordType 172 .getVersionableMutableFieldGroupId(), recordType.getVersionableMutableFieldGroupVersion(), 173 latestRecordType.getVersionableMutableFieldGroupId(), latestRecordType 174 .getVersionableMutableFieldGroupVersion(), 175 RECORDTYPE_VERSIONABLEMUTABLEFIELDGROUP_COLUMN_NAME); 176 if (updateResult.getV1()) { 195 177 recordTypeChanged = true; 196 for (FieldDescriptor fieldDescriptor : originalFieldDescriptorSet) { 197 removeFieldDescriptor(fieldDescriptor, newRecordTypeVersion, recordTypePut); 198 } 178 newRecordType.setVersionableMutableFieldGroupVersion(updateResult.getV2()); 199 179 } 200 180 201 181 if (recordTypeChanged) { 202 recordTypePut.add(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(newRecordTypeVersion)); 203 puts.add(recordTypePut); 182 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(newRecordTypeVersion)); 204 183 try { 205 typeTable.put(put s);184 typeTable.put(put); 206 185 } catch (IOException e) { 207 throw new RepositoryException("Exception occured while writing updated recordType <" + recordTypeId 208 + "> to HBase table", e); 209 } 210 } 211 } 212 213 private Put updateFieldDescriptor(FieldDescriptor fieldDescriptor, FieldDescriptor originalFieldDescriptor, 214 String recordTypeId, Long recordTypeVersion, Put recordTypePut) throws RepositoryException { 215 boolean fieldDescriptorChanged = false; 216 long fieldDescriptorVersion = 0; 217 String fieldDescriptorId = fieldDescriptor.getId(); 218 Put put = new Put(EncodingUtil.generateFieldDescriptorRowKey(recordTypeId, fieldDescriptorId)); 219 220 if (!originalFieldDescriptor.getValueType().equals(fieldDescriptor.getValueType())) { 221 if (fieldDescriptorChanged == false) { 222 fieldDescriptorChanged = true; 223 fieldDescriptorVersion = getLatestFieldDescriptorVersion(recordTypeId, fieldDescriptorId) + 1; 224 } 225 put.add(SYSTEM_VERSIONABLE_COLUMN_FAMILY, VALUE_TYPE_COLUMN_NAME, fieldDescriptorVersion, fieldDescriptor 226 .getValueType().toBytes()); 227 } 228 if (fieldDescriptor.isMandatory() != originalFieldDescriptor.isMandatory()) { 229 if (fieldDescriptorChanged == false) { 230 fieldDescriptorChanged = true; 231 fieldDescriptorVersion = getLatestFieldDescriptorVersion(recordTypeId, fieldDescriptorId) + 1; 232 } 233 put.add(SYSTEM_VERSIONABLE_COLUMN_FAMILY, MANDATORY_COLUMN_NAME, fieldDescriptorVersion, Bytes 234 .toBytes(fieldDescriptor.isMandatory())); 235 } 236 if (fieldDescriptor.isVersionable() != originalFieldDescriptor.isVersionable()) { 237 if (fieldDescriptorChanged == false) { 238 fieldDescriptorChanged = true; 239 fieldDescriptorVersion = getLatestFieldDescriptorVersion(recordTypeId, fieldDescriptorId) + 1; 240 } 241 put.add(SYSTEM_VERSIONABLE_COLUMN_FAMILY, VERSIONABLE_COLUMN_NAME, fieldDescriptorVersion, Bytes 242 .toBytes(fieldDescriptor.isVersionable())); 243 } 244 if (fieldDescriptorChanged) { 245 put.add(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(fieldDescriptorVersion)); 246 recordTypePut.add(FIELDDESCRIPTOR_COLUMN_FAMILY, Bytes.toBytes(fieldDescriptorId), recordTypeVersion, 247 EncodingUtil.prefixValue(Bytes.toBytes(fieldDescriptorVersion), EncodingUtil.EXISTS_FLAG)); 248 return put; 249 } 250 return null; 251 } 252 253 private void removeFieldDescriptor(FieldDescriptor fieldDescriptor, Long recordTypeVersion, Put recordTypePut) { 254 recordTypePut.add(FIELDDESCRIPTOR_COLUMN_FAMILY, Bytes.toBytes(fieldDescriptor.getId()), recordTypeVersion, 255 new byte[] { EncodingUtil.DELETE_FLAG }); 256 } 257 258 public RecordType getRecordType(String recordTypeId) throws RepositoryException { 186 throw new RepositoryException("Exception occured while updating recordType <" + recordType.getId() 187 + "> on HBase", e); 188 } 189 newRecordType.setVersion(newRecordTypeVersion); 190 } else { 191 newRecordType.setVersion(latestRecordTypeVersion); 192 } 193 return newRecordType; 194 } 195 196 private Pair<Boolean, Long> updateFieldGroupOnRecordType(Put put, Long newRecordTypeVersion, String fieldGroupId, 197 Long fieldGroupVersion, String latestFieldGroupId, Long latestFieldGroupVersion, 198 byte[] fieldGroupColumnName) throws FieldGroupNotFoundException, RepositoryException { 199 200 if ((fieldGroupId == null) 201 || (fieldGroupId.equals(latestFieldGroupId) && (latestFieldGroupVersion 202 .equals(fieldGroupVersion)))) { 203 return new Pair<Boolean, Long>(false, null); 204 } else { 205 Long version = putFieldGroupOnRecordType(newRecordTypeVersion, put, fieldGroupId, fieldGroupVersion, 206 fieldGroupColumnName); 207 return new Pair<Boolean, Long>(true, version); 208 } 209 } 210 211 private Long putFieldGroupOnRecordType(Long recordTypeVersion, Put put, String fieldGroupId, 212 Long fieldGroupVersion, byte[] fieldGroupColumnName) throws FieldGroupNotFoundException, 213 RepositoryException { 214 // Validate if the fieldGroup exists and use the latest version if none 215 // was given. 216 Long newFieldGroupVersion = getFieldGroup(fieldGroupId, fieldGroupVersion).getVersion(); 217 put.add(VERSIONABLE_COLUMN_FAMILY, fieldGroupColumnName, recordTypeVersion, encodeFieldGroup(fieldGroupId, 218 newFieldGroupVersion)); 219 return newFieldGroupVersion; 220 } 221 222 public RecordType removeFieldGroups(String recordTypeId, boolean nonVersionable, boolean versionable, boolean versionableMutable) throws RecordTypeNotFoundException, RepositoryException { 223 RecordType recordType = getRecordType(recordTypeId, null); 224 Long version = recordType.getVersion() + 1; 225 Put put = new Put(Bytes.toBytes(recordTypeId)); 226 boolean changed = false; 227 if (nonVersionable) { 228 if (recordType.getNonVersionableFieldGroupId() != null) { 229 put.add(VERSIONABLE_COLUMN_FAMILY, RECORDTYPE_NONVERSIONABLEFIELDGROUP_COLUMN_NAME, new byte[]{EncodingUtil.DELETE_FLAG}); 230 recordType.setNonVersionableFieldGroupId(null); 231 recordType.setNonVersionableFieldGroupVersion(null); 232 changed = true; 233 } 234 } 235 if (versionable) { 236 if (recordType.getVersionableFieldGroupId() != null) { 237 put.add(VERSIONABLE_COLUMN_FAMILY, RECORDTYPE_VERSIONABLEFIELDGROUP_COLUMN_NAME, new byte[]{EncodingUtil.DELETE_FLAG}); 238 recordType.setVersionableFieldGroupId(null); 239 recordType.setVersionableFieldGroupVersion(null); 240 changed = true; 241 } 242 } 243 if (versionableMutable) { 244 if (recordType.getVersionableMutableFieldGroupId() != null) { 245 put.add(VERSIONABLE_COLUMN_FAMILY, RECORDTYPE_VERSIONABLEMUTABLEFIELDGROUP_COLUMN_NAME, new byte[]{EncodingUtil.DELETE_FLAG}); 246 recordType.setVersionableMutableFieldGroupId(null); 247 recordType.setVersionableMutableFieldGroupVersion(null); 248 changed = true; 249 } 250 } 251 if (changed) { 252 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 253 try { 254 typeTable.put(put); 255 } catch (IOException e) { 256 throw new RepositoryException("Exception occured while removing fieldGroups from recordType <" + recordTypeId 257 + "> on HBase", e); 258 } 259 recordType.setVersion(version); 260 } 261 return recordType; 262 } 263 264 public RecordType getRecordType(String recordTypeId, Long version) throws RecordTypeNotFoundException, 265 RepositoryException { 259 266 ArgumentValidator.notNull(recordTypeId, "recordTypeId"); 260 Get get = new Get(EncodingUtil.generateRecordTypeRowKey(recordTypeId)); 267 Get get = new Get(Bytes.toBytes(recordTypeId)); 268 if (version != null) { 269 get.setMaxVersions(); 270 } 261 271 Result result; 262 272 try { 273 if (!typeTable.exists(get)) { 274 throw new RecordTypeNotFoundException(recordTypeId, null); 275 } 263 276 result = typeTable.get(get); 264 277 } catch (IOException e) { … … 266 279 + "> from HBase table", e); 267 280 } 268 NavigableMap<byte[], byte[]> systemFamilyMap = result.getFamilyMap(SYSTEM_COLUMN_FAMILY);269 long version = Bytes.toLong(systemFamilyMap.get(CURRENT_VERSION_COLUMN_NAME));270 271 281 RecordType recordType = newRecordType(recordTypeId); 272 recordType.setVersion(version); 273 274 NavigableMap<byte[], byte[]> fieldDescriptorsFamilyMap = result.getFamilyMap(FIELDDESCRIPTOR_COLUMN_FAMILY); 275 Set<Entry<byte[], byte[]>> fieldDescriptorEntries = fieldDescriptorsFamilyMap.entrySet(); 276 for (Entry<byte[], byte[]> fieldDescriptorEntry : fieldDescriptorEntries) { 277 if (!EncodingUtil.isDeletedField(fieldDescriptorEntry.getValue())) { 278 recordType.addFieldDescriptor(getFieldDescriptor(recordTypeId, Bytes.toString(fieldDescriptorEntry 279 .getKey()), Bytes.toLong(EncodingUtil.stripPrefix(fieldDescriptorEntry.getValue())))); 280 } 282 Long currentVersion = Bytes.toLong(result.getValue(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME)); 283 if (version != null) { 284 if (currentVersion < version) { 285 throw new RecordTypeNotFoundException(recordTypeId, version); 286 } 287 recordType.setVersion(version); 288 } else { 289 recordType.setVersion(currentVersion); 290 } 291 Pair<String, Long> fieldGroup = extractFieldGroup(result, version, 292 RECORDTYPE_NONVERSIONABLEFIELDGROUP_COLUMN_NAME); 293 if (fieldGroup != null) { 294 recordType.setNonVersionableFieldGroupId(fieldGroup.getV1()); 295 recordType.setNonVersionableFieldGroupVersion(fieldGroup.getV2()); 296 } 297 fieldGroup = extractFieldGroup(result, version, RECORDTYPE_VERSIONABLEFIELDGROUP_COLUMN_NAME); 298 if (fieldGroup != null) { 299 recordType.setVersionableFieldGroupId(fieldGroup.getV1()); 300 recordType.setVersionableFieldGroupVersion(fieldGroup.getV2()); 301 } 302 fieldGroup = extractFieldGroup(result, version, RECORDTYPE_VERSIONABLEMUTABLEFIELDGROUP_COLUMN_NAME); 303 if (fieldGroup != null) { 304 recordType.setVersionableMutableFieldGroupId(fieldGroup.getV1()); 305 recordType.setVersionableMutableFieldGroupVersion(fieldGroup.getV2()); 281 306 } 282 307 return recordType; 283 308 } 284 309 285 public RecordType getRecordType(String recordTypeId, Long recordTypeVersion) throws RepositoryException { 286 if (recordTypeVersion == null) { 287 return getRecordType(recordTypeId); 288 } 289 ArgumentValidator.notNull(recordTypeId, "recordTypeId"); 290 Get get = new Get(EncodingUtil.generateRecordTypeRowKey(recordTypeId)); 291 get.setMaxVersions(); 310 private Pair<String, Long> extractFieldGroup(Result result, Long version, byte[] fieldGroupColumnName) { 311 byte[] fieldGroupBytes = null; 312 Pair<String, Long> fieldGroup = null; 313 if (version != null) { 314 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allVersionsMap = result.getMap(); 315 NavigableMap<byte[], NavigableMap<Long, byte[]>> versionableVersionsMap = allVersionsMap 316 .get(VERSIONABLE_COLUMN_FAMILY); 317 NavigableMap<Long, byte[]> fieldGroupVersions = versionableVersionsMap.get(fieldGroupColumnName); 318 if (fieldGroupVersions != null) { 319 Entry<Long, byte[]> ceilingEntry = fieldGroupVersions.ceilingEntry(version); 320 if (ceilingEntry != null) { 321 fieldGroupBytes = ceilingEntry.getValue(); 322 } 323 } 324 } else { 325 fieldGroupBytes = result.getValue(VERSIONABLE_COLUMN_FAMILY, fieldGroupColumnName); 326 } 327 if (fieldGroupBytes != null) { 328 fieldGroup = decodeFieldGroup(fieldGroupBytes); 329 } 330 return fieldGroup; 331 } 332 333 private byte[] encodeFieldGroup(String fieldGroupId, Long fieldGroupVersion) { 334 byte[] bytes = Bytes.toBytes(fieldGroupVersion); 335 bytes = EncodingUtil.prefixValue(Bytes.add(bytes, Bytes.toBytes(fieldGroupId)), EncodingUtil.EXISTS_FLAG); 336 return bytes; 337 } 338 339 private Pair<String, Long> decodeFieldGroup(byte[] fieldGroupBytes) { 340 if (EncodingUtil.isDeletedField(fieldGroupBytes)) { 341 return null; 342 } 343 byte[] encodedFieldGroupBytes = EncodingUtil.stripPrefix(fieldGroupBytes); 344 Long version = Bytes.toLong(encodedFieldGroupBytes, 0, Bytes.SIZEOF_LONG); 345 String fieldGroupId = Bytes.toString(encodedFieldGroupBytes, Bytes.SIZEOF_LONG, encodedFieldGroupBytes.length 346 - Bytes.SIZEOF_LONG); 347 return new Pair<String, Long>(fieldGroupId, version); 348 } 349 350 // Field Groups 351 352 public FieldGroup newFieldGroup(String id) { 353 ArgumentValidator.notNull(id, "id"); 354 return new FieldGroupImpl(id); 355 } 356 357 public FieldGroupEntry newFieldGroupEntry(String fieldDescriptorId, Long fieldDescriptorVersion, boolean mandatory, 358 String alias) { 359 ArgumentValidator.notNull(fieldDescriptorId, "fieldDescriptorId"); 360 ArgumentValidator.notNull(mandatory, "mandatory"); 361 ArgumentValidator.notNull(alias, "alias"); 362 return new FieldGroupEntryImpl(fieldDescriptorId, fieldDescriptorVersion, mandatory, alias); 363 } 364 365 public FieldGroup createFieldGroup(FieldGroup fieldGroup) throws FieldGroupExistsException, 366 FieldDescriptorNotFoundException, RepositoryException { 367 ArgumentValidator.notNull(fieldGroup, "fieldGroup"); 368 FieldGroup result; 369 String id = fieldGroup.getId(); 370 byte[] rowId = Bytes.toBytes(id); 371 Long version = Long.valueOf(1); 372 result = fieldGroup.clone(); 373 try { 374 if (typeTable.exists(new Get(rowId))) { 375 throw new FieldGroupExistsException(fieldGroup); 376 } 377 Put put = new Put(rowId); 378 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 379 Collection<FieldGroupEntry> fieldGroupEntries = fieldGroup.getFieldGroupEntries(); 380 for (FieldGroupEntry fieldGroupEntry : fieldGroupEntries) { 381 result.setFieldGroupEntry(putFieldGroupEntry(version, put, fieldGroupEntry)); 382 } 383 typeTable.put(put); 384 } catch (IOException e) { 385 throw new RepositoryException("Exception occured while creating fieldGroup <" + fieldGroup.getId() 386 + "> version: <" + version + "> on HBase", e); 387 } 388 result.setVersion(version); 389 return result; 390 } 391 392 public FieldGroup updateFieldGroup(FieldGroup fieldGroup) throws FieldGroupNotFoundException, 393 FieldDescriptorNotFoundException, RepositoryException { 394 ArgumentValidator.notNull(fieldGroup, "fieldGroup"); 395 String id = fieldGroup.getId(); 396 FieldGroup latestFieldGroup = getFieldGroup(id, null); 397 Long version = latestFieldGroup.getVersion() + 1; 398 byte[] rowId = Bytes.toBytes(id); 399 Put put = new Put(rowId); 400 boolean updateNeeded = false; 401 FieldGroup updatedFieldGroup = fieldGroup.clone(); 402 403 for (FieldGroupEntry fieldGroupEntry : fieldGroup.getFieldGroupEntries()) { 404 FieldGroupEntry latestFieldGroupEntry = latestFieldGroup.getFieldGroupEntry(fieldGroupEntry 405 .getFieldDescriptorId()); 406 if (!fieldGroupEntry.equals(latestFieldGroupEntry)) { 407 updatedFieldGroup.setFieldGroupEntry(putFieldGroupEntry(version, put, fieldGroupEntry)); 408 updateNeeded = true; 409 } 410 } 411 412 if (updateNeeded) { 413 updatedFieldGroup.setVersion(version); 414 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 415 try { 416 typeTable.put(put); 417 } catch (IOException e) { 418 throw new RepositoryException("Exception occured while updating fieldGroup <" + fieldGroup.getId() 419 + "> version: <" + version + "> on HBase", e); 420 } 421 } else { 422 updatedFieldGroup.setVersion(latestFieldGroup.getVersion()); 423 } 424 return updatedFieldGroup; 425 } 426 427 private FieldGroupEntry putFieldGroupEntry(Long version, Put put, FieldGroupEntry fieldGroupEntry) 428 throws FieldDescriptorNotFoundException, RepositoryException { 429 FieldGroupEntry newFieldGroupEntry = fieldGroupEntry.clone(); 430 // Retrieve fieldDescriptor to check it exists and get the latest 431 // version number if none was given. 432 Long fieldDescriptorVersion = getFieldDescriptor(fieldGroupEntry.getFieldDescriptorId(), 433 fieldGroupEntry.getFieldDescriptorVersion()).getVersion(); 434 newFieldGroupEntry.setFieldDescriptorVersion(fieldDescriptorVersion); 435 put.add(VERSIONABLE_COLUMN_FAMILY, Bytes.toBytes(fieldGroupEntry.getFieldDescriptorId()), version, 436 encodeFieldGroupEntry(newFieldGroupEntry)); 437 return newFieldGroupEntry; 438 } 439 440 public FieldGroup removeFieldDescriptors(String fieldGroupId, List<String> fieldDescriptorIds) throws FieldGroupNotFoundException, RepositoryException{ 441 FieldGroup fieldGroup = getFieldGroup(fieldGroupId, null); 442 Put put = new Put(Bytes.toBytes(fieldGroupId)); 443 Long version = fieldGroup.getVersion() + 1; 444 boolean changed = false; 445 for (String fieldDescriptorId : fieldDescriptorIds) { 446 if (fieldGroup.getFieldGroupEntry(fieldDescriptorId) == null) { 447 // Ignore 448 } else { 449 put.add(VERSIONABLE_COLUMN_FAMILY, Bytes.toBytes(fieldDescriptorId), version, new byte[]{EncodingUtil.DELETE_FLAG}); 450 fieldGroup.removeFieldGroupEntry(fieldDescriptorId); 451 changed = true; 452 } 453 } 454 if (changed) { 455 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 456 try { 457 typeTable.put(put); 458 } catch (IOException e) { 459 throw new RepositoryException("Exception occured while removing fieldDescriptor <"+fieldGroupId+"> from fieldGroup <" + fieldGroup.getId() 460 + "> on HBase", e); 461 } 462 fieldGroup.setVersion(version); 463 } 464 return fieldGroup; 465 } 466 467 public FieldGroup getFieldGroup(String id, Long version) throws FieldGroupNotFoundException, RepositoryException { 468 FieldGroup fieldGroup = new FieldGroupImpl(id); 469 byte[] rowId = Bytes.toBytes(id); 470 Get get = new Get(rowId); 471 if (version != null) { 472 get.setMaxVersions(); 473 } 292 474 Result result; 293 475 try { 476 if (!typeTable.exists(get)) { 477 throw new FieldGroupNotFoundException(id, null); 478 } 294 479 result = typeTable.get(get); 295 480 } catch (IOException e) { 296 throw new RepositoryException("Exception occured while retrieving recordType <" + recordTypeId 297 + "> from HBase table", e); 298 } 299 RecordType recordType = newRecordType(recordTypeId); 300 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allFamiliesMap = result.getMap(); 301 NavigableMap<byte[], NavigableMap<Long, byte[]>> fieldDescriptorsVersionedMap = allFamiliesMap 302 .get(FIELDDESCRIPTOR_COLUMN_FAMILY); 303 Set<Entry<byte[], NavigableMap<Long, byte[]>>> fieldDescriptorsEntrySet = fieldDescriptorsVersionedMap 304 .entrySet(); 305 for (Entry<byte[], NavigableMap<Long, byte[]>> fieldDescriptorEntry : fieldDescriptorsEntrySet) { 306 String fieldDescriptorId = Bytes.toString(fieldDescriptorEntry.getKey()); 307 Entry<Long, byte[]> ceilingEntry = fieldDescriptorEntry.getValue().ceilingEntry(recordTypeVersion); 308 if (ceilingEntry != null && !EncodingUtil.isDeletedField(ceilingEntry.getValue())) { 309 long fieldDescriptorVersion = Bytes.toLong(EncodingUtil.stripPrefix(ceilingEntry.getValue())); 310 recordType.addFieldDescriptor(getFieldDescriptor(recordTypeId, fieldDescriptorId, 311 fieldDescriptorVersion)); 312 } 313 } 314 recordType.setVersion(recordTypeVersion); 315 return recordType; 316 } 317 318 private FieldDescriptor getFieldDescriptor(String recordTypeId, String fieldDescriptorId, 319 Long fieldDescriptorVersion) throws RepositoryException { 320 Get get = new Get(EncodingUtil.generateFieldDescriptorRowKey(recordTypeId, fieldDescriptorId)); 321 get.setMaxVersions(); 481 throw new RepositoryException("Exception occured while retrieving fieldGroup <" + id + "> version: <" 482 + version + "> from HBase", e); 483 } 484 long latestVersion = Bytes.toLong(result.getValue(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME)); 485 if (version != null) { 486 if (version > latestVersion) { 487 throw new FieldGroupNotFoundException(id, version); 488 } 489 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allVersionsMap = result.getMap(); 490 NavigableMap<byte[], NavigableMap<Long, byte[]>> versionableVersionsMap = allVersionsMap 491 .get(VERSIONABLE_COLUMN_FAMILY); 492 for (Entry<byte[], NavigableMap<Long, byte[]>> entry : versionableVersionsMap.entrySet()) { 493 String fieldDescriptorId = Bytes.toString(entry.getKey()); 494 Entry<Long, byte[]> ceilingEntry = entry.getValue().ceilingEntry(version); 495 if (ceilingEntry != null) { 496 FieldGroupEntry decodedFieldGroupEntry = decodeFieldGroupEntry(ceilingEntry.getValue(), fieldDescriptorId); 497 if (decodedFieldGroupEntry != null) { 498 fieldGroup.setFieldGroupEntry(decodedFieldGroupEntry); 499 } 500 } 501 } 502 fieldGroup.setVersion(version); 503 } else { 504 NavigableMap<byte[], byte[]> versionableFamilyMap = result.getFamilyMap(VERSIONABLE_COLUMN_FAMILY); 505 for (Entry<byte[], byte[]> entry : versionableFamilyMap.entrySet()) { 506 String fieldDescriptorId = Bytes.toString(entry.getKey()); 507 FieldGroupEntry decodeFieldGroupEntry = decodeFieldGroupEntry(entry.getValue(), fieldDescriptorId); 508 if (decodeFieldGroupEntry != null) { 509 fieldGroup.setFieldGroupEntry(decodeFieldGroupEntry); 510 } 511 } 512 fieldGroup.setVersion(latestVersion); 513 } 514 515 return fieldGroup; 516 } 517 518 // TODO move to some encoder/decoder 519 /** 520 * Encoding the fields: FD-version, mandatory, alias 521 */ 522 private byte[] encodeFieldGroupEntry(FieldGroupEntry fieldGroupEntry) { 523 // TODO check if we can use nio instead 524 byte[] bytes = new byte[0]; 525 bytes = Bytes.add(bytes, Bytes.toBytes(fieldGroupEntry.getFieldDescriptorVersion())); 526 bytes = Bytes.add(bytes, Bytes.toBytes(fieldGroupEntry.isMandatory())); 527 bytes = Bytes.add(bytes, Bytes.toBytes(fieldGroupEntry.getAlias())); 528 return EncodingUtil.prefixValue(bytes, EncodingUtil.EXISTS_FLAG); 529 } 530 531 private FieldGroupEntry decodeFieldGroupEntry(byte[] bytes, String fieldDescriptorId) { 532 if (EncodingUtil.isDeletedField(bytes)) { 533 return null; 534 } 535 byte[] encodedBytes = EncodingUtil.stripPrefix(bytes); 536 int offset = 0; 537 long fieldDescriptorVersion = Bytes.toLong(encodedBytes, 0); 538 offset = offset + Bytes.SIZEOF_LONG; 539 byte[] booleanBytes = new byte[Bytes.SIZEOF_BOOLEAN]; 540 Bytes.putBytes(booleanBytes, 0, encodedBytes, offset, Bytes.SIZEOF_BOOLEAN); 541 boolean mandatory = Bytes.toBoolean(booleanBytes); 542 offset = offset + Bytes.SIZEOF_BOOLEAN; 543 String alias = Bytes.toString(encodedBytes, offset, encodedBytes.length - offset); 544 return new FieldGroupEntryImpl(fieldDescriptorId, fieldDescriptorVersion, mandatory, alias); 545 } 546 547 public FieldDescriptor newFieldDescriptor(String id, ValueType valueType, String globalName) { 548 ArgumentValidator.notNull(id, "id"); 549 ArgumentValidator.notNull(valueType, "valueType"); 550 ArgumentValidator.notNull(globalName, "globalName"); 551 return new FieldDescriptorImpl(id, valueType, globalName); 552 } 553 554 public FieldDescriptor createFieldDescriptor(FieldDescriptor fieldDescriptor) 555 throws FieldDescriptorExistsException, RepositoryException { 556 ArgumentValidator.notNull(fieldDescriptor, "fieldDescriptor"); 557 FieldDescriptor result; 558 byte[] rowId = Bytes.toBytes(fieldDescriptor.getId()); 559 Long version = Long.valueOf(1); 560 try { 561 if (typeTable.exists(new Get(rowId))) { 562 throw new FieldDescriptorExistsException(fieldDescriptor); 563 } 564 Put put = new Put(rowId); 565 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 566 put.add(NON_VERSIONABLE_COLUMN_FAMILY, FIELDDESCRIPTOR_VALUETYPE_COLUMN_NAME, fieldDescriptor 567 .getValueType().toBytes()); 568 put.add(VERSIONABLE_COLUMN_FAMILY, FIELDDESCRIPTOR_GLOBALNAME_COLUMN_NAME, version, Bytes 569 .toBytes(fieldDescriptor.getGlobalName())); 570 typeTable.put(put); 571 } catch (IOException e) { 572 throw new RepositoryException("Exception occured while creating fieldDescriptor <" 573 + fieldDescriptor.getId() + "> version: <" + version + "> on HBase", e); 574 } 575 result = fieldDescriptor.clone(); 576 result.setVersion(version); 577 return result; 578 } 579 580 public FieldDescriptor updateFieldDescriptor(FieldDescriptor fieldDescriptor) 581 throws FieldDescriptorNotFoundException, FieldDescriptorUpdateException, RepositoryException { 582 FieldDescriptor latestFieldDescriptor = getFieldDescriptor(fieldDescriptor.getId(), null); 583 if (!fieldDescriptor.getValueType().equals(latestFieldDescriptor.getValueType())) { 584 throw new FieldDescriptorUpdateException("Changing the valueType of a fieldDescriptor <" 585 + fieldDescriptor.getId() + "> is not allowed; old<" + latestFieldDescriptor.getValueType() 586 + "> new<" + fieldDescriptor.getValueType() + ">"); 587 } 588 Long version = latestFieldDescriptor.getVersion(); 589 if (!fieldDescriptor.getGlobalName().equals(latestFieldDescriptor.getGlobalName())) { 590 version = version + 1; 591 Put put = new Put(Bytes.toBytes(fieldDescriptor.getId())); 592 put.add(VERSIONABLE_COLUMN_FAMILY, FIELDDESCRIPTOR_GLOBALNAME_COLUMN_NAME, version, Bytes 593 .toBytes(fieldDescriptor.getGlobalName())); 594 put.add(NON_VERSIONABLE_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME, Bytes.toBytes(version)); 595 try { 596 typeTable.put(put); 597 } catch (IOException e) { 598 throw new RepositoryException("Exception occured while updating fieldDescriptor <" 599 + fieldDescriptor.getId() + "> on HBase", e); 600 } 601 } 602 FieldDescriptor newFieldDescriptor = fieldDescriptor.clone(); 603 newFieldDescriptor.setVersion(version); 604 return newFieldDescriptor; 605 } 606 607 public FieldDescriptor getFieldDescriptor(String id, Long version) throws FieldDescriptorNotFoundException, 608 RepositoryException { 609 ArgumentValidator.notNull(id, "id"); 322 610 Result result; 611 Get get = new Get(Bytes.toBytes(id)); 612 if (version != null) { 613 get.setMaxVersions(); 614 } 323 615 try { 616 if (!typeTable.exists(get)) { 617 throw new FieldDescriptorNotFoundException(id, null); 618 } 324 619 result = typeTable.get(get); 325 620 } catch (IOException e) { 326 throw new RepositoryException("Exception occured while retrieving fieldDescriptor <" + fieldDescriptorId 327 + "> for recordType <" + recordTypeId + "> from HBase table", e); 328 } 329 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allFamiliesMap = result.getMap(); 330 NavigableMap<byte[], NavigableMap<Long, byte[]>> systemVersionableVersionedMap = allFamiliesMap 331 .get(SYSTEM_VERSIONABLE_COLUMN_FAMILY); 332 ValueType valueType = ValueTypeImpl.fromBytes(systemVersionableVersionedMap.get(VALUE_TYPE_COLUMN_NAME) 333 .ceilingEntry(fieldDescriptorVersion).getValue(), this); 334 boolean mandatory = Bytes.toBoolean(systemVersionableVersionedMap.get(MANDATORY_COLUMN_NAME).ceilingEntry( 335 fieldDescriptorVersion).getValue()); 336 boolean versionable = Bytes.toBoolean(systemVersionableVersionedMap.get(VERSIONABLE_COLUMN_NAME).ceilingEntry( 337 fieldDescriptorVersion).getValue()); 338 339 return newFieldDescriptor(fieldDescriptorId, fieldDescriptorVersion, valueType, mandatory, versionable); 340 } 341 342 private long getLatestFieldDescriptorVersion(String recordTypeId, String fieldDescriptorId) 343 throws RepositoryException { 344 Get get = new Get(EncodingUtil.generateFieldDescriptorRowKey(recordTypeId, fieldDescriptorId)); 345 get.addColumn(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME); 346 Result result; 347 try { 348 result = typeTable.get(get); 349 } catch (IOException e) { 350 throw new RepositoryException("Exception occured while retrieving fielddescriptor <" + fieldDescriptorId 351 + "> of recordType <" + recordTypeId + ">", e); 352 } 353 if (result.isEmpty()) { 354 return 0; 355 } 356 return Bytes.toLong(result.getValue(SYSTEM_COLUMN_FAMILY, CURRENT_VERSION_COLUMN_NAME)); 357 } 621 throw new RepositoryException("Exception occured while retrieving fieldDescriptor <" + id + "> version: <" 622 + version + "> from HBase", e); 623 } 624 NavigableMap<byte[], byte[]> nonVersionableColumnFamily = result.getFamilyMap(NON_VERSIONABLE_COLUMN_FAMILY); 625 Long currentVersion = Bytes.toLong(nonVersionableColumnFamily.get(CURRENT_VERSION_COLUMN_NAME)); 626 Long retrievedVersion; 627 String globalName; 628 if (version != null) { 629 if (version > currentVersion) { 630 throw new FieldDescriptorNotFoundException(id, version); 631 } 632 NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> allVersionsMap = result.getMap(); 633 NavigableMap<byte[], NavigableMap<Long, byte[]>> versionableVersionsMap = allVersionsMap 634 .get(VERSIONABLE_COLUMN_FAMILY); 635 NavigableMap<Long, byte[]> globalNameVersionsMap = versionableVersionsMap 636 .get(FIELDDESCRIPTOR_GLOBALNAME_COLUMN_NAME); 637 globalName = Bytes.toString(globalNameVersionsMap.floorEntry(version).getValue()); 638 retrievedVersion = version; 639 } else { 640 NavigableMap<byte[], byte[]> versionableColumnFamily = result.getFamilyMap(VERSIONABLE_COLUMN_FAMILY); 641 globalName = Bytes.toString(versionableColumnFamily.get(FIELDDESCRIPTOR_GLOBALNAME_COLUMN_NAME)); 642 retrievedVersion = currentVersion; 643 } 644 ValueType valueType = ValueTypeImpl.fromBytes(nonVersionableColumnFamily 645 .get(FIELDDESCRIPTOR_VALUETYPE_COLUMN_NAME), this); 646 FieldDescriptor fieldDescriptor = new FieldDescriptorImpl(id, valueType, globalName); 647 fieldDescriptor.setVersion(retrievedVersion); 648 return fieldDescriptor; 649 } 650 651 // Value Types 358 652 359 653 // TODO move to a primitiveValueType registry … … 377 671 return new ValueTypeImpl(primitiveValueTypes.get(primitiveValueTypeName), multivalue, hierarchy); 378 672 } 673 379 674 } -
projects/lily/trunk/repository/impl/src/main/java/org/lilycms/repository/impl/RecordImpl.java
r3952 r3977 16 16 package org.lilycms.repository.impl; 17 17 18 import java.util.ArrayList; 18 19 import java.util.HashMap; 19 import java.util. HashSet;20 import java.util.List; 20 21 import java.util.Map; 21 import java.util.Set;22 22 23 23 import org.lilycms.repository.api.FieldNotFoundException; … … 27 27 28 28 public class RecordImpl implements Record { 29 private RecordId recordId; 30 private Map<String, Object> fields = new HashMap<String, Object>(); 31 private Set<String> deleteFields = new HashSet<String>(); 29 private RecordId id; 30 private Map<String, Object> nonVersionableFields = new HashMap<String, Object>(); 31 private Map<String, Object> versionableFields = new HashMap<String, Object>(); 32 private Map<String, Object> versionableMutableFields = new HashMap<String, Object>(); 32 33 private String recordTypeId; 33 private long recordTypeVersion; 34 private Map<String, String> variantProperties = new HashMap<String, String>(); 34 private Long recordTypeVersion; 35 private String nonVersionableRecordTypeId; 36 private Long nonVersionableRecordTypeVersion; 37 private String versionableRecordTypeId; 38 private Long versionableRecordTypeVersion; 39 private String versionableMutableRecordTypeId; 40 private Long versionableMutableRecordTypeVersion; 35 41 private Long version; 42 private List<String> nonVersionableFieldsToDelete = new ArrayList<String>(); 43 private List<String> versionableFieldsToDelete = new ArrayList<String>(); 44 private List<String> versionableMutableFieldsToDelete = new ArrayList<String>(); 36 45 37 46 /** … … 46 55 * @use {@link Repository#newRecord} instead 47 56 */ 48 public RecordImpl(RecordId recordId) {49 this. recordId = recordId;50 } 51 52 public void setId(RecordId recordId) {53 this. recordId = recordId;57 public RecordImpl(RecordId id) { 58 this.id = id; 59 } 60 61 public void setId(RecordId id) { 62 this.id = id; 54 63 } 55 64 56 65 public RecordId getId() { 57 return recordId;66 return id; 58 67 } 59 68 … … 66 75 } 67 76 68 public void setRecordType(String recordTypeId, long recordTypeVersion) {77 public void setRecordType(String recordTypeId, Long recordTypeVersion) { 69 78 this.recordTypeId = recordTypeId; 70 79 this.recordTypeVersion = recordTypeVersion; … … 75 84 } 76 85 77 public long getRecordTypeVersion() {86 public Long getRecordTypeVersion() { 78 87 return recordTypeVersion; 79 88 } 80 81 public void setField(String fieldId, Object value) { 82 fields.put(fieldId, value); 83 } 84 85 public Object getField(String fieldId) throws FieldNotFoundException { 86 Object field = fields.get(fieldId); 89 90 public void setNonVersionableRecordType(String id, Long version) { 91 this.nonVersionableRecordTypeId = id; 92 this.nonVersionableRecordTypeVersion = version; 93 } 94 95 public String getNonVersionableRecordTypeId() { 96 return nonVersionableRecordTypeId; 97 } 98 99 public Long getNonVersionableRecordTypeVersion() { 100 return nonVersionableRecordTypeVersion; 101 } 102 103 public void setVersionableRecordType(String id, Long version) { 104 this.versionableRecordTypeId = id; 105 this.versionableRecordTypeVersion = version; 106 } 107 108 public String getVersionableRecordTypeId() { 109 return versionableRecordTypeId; 110 } 111 112 public Long getVersionableRecordTypeVersion() { 113 return versionableRecordTypeVersion; 114 } 115 116 public void setVersionableMutableRecordType(String id, Long version) { 117 this.versionableMutableRecordTypeId = id; 118 this.versionableMutableRecordTypeVersion = version; 119 } 120 121 public String getVersionableMutableRecordTypeId() { 122 return versionableMutableRecordTypeId; 123 } 124 125 public Long getVersionableMutableRecordTypeVersion() { 126 return versionableMutableRecordTypeVersion; 127 } 128 129 public void setNonVersionableField(String fieldId, Object value) { 130 this.nonVersionableFields.put(fieldId, value); 131 } 132 133 public void setVersionableField(String fieldId, Object value) { 134 this.versionableFields.put(fieldId, value); 135 } 136 137 public void setVersionableMutableField(String fieldId, Object value) { 138 this.versionableMutableFields.put(fieldId, value); 139 } 140 141 public Object getNonVersionableField(String fieldId) throws FieldNotFoundException { 142 Object field = nonVersionableFields.get(fieldId); 87 143 if (field == null) { 88 144 throw new FieldNotFoundException(fieldId); … … 91 147 } 92 148 93 public Map<String, Object> getFields() { 94 return fields; 95 } 96 97 public void addVariantProperty(String dimension, String dimensionValue) { 98 variantProperties.put(dimension, dimensionValue); 99 } 100 101 public void addVariantProperties(Map<String, String> variantProperties) { 102 if (variantProperties != null) { 103 this.variantProperties.putAll(variantProperties); 149 public Object getVersionableField(String fieldId) throws FieldNotFoundException { 150 Object field = versionableFields.get(fieldId); 151 if (field == null) { 152 throw new FieldNotFoundException(fieldId); 104 153 } 105 } 106 107 public Map<String, String> getVariantProperties() { 108 return variantProperties; 109 } 110 111 public void deleteField(String fieldId) { 112 deleteFields.add(fieldId); 113 } 114 115 public Set<String> getDeleteFields() { 116 return deleteFields; 154 return field; 155 } 156 157 public Object getVersionableMutableField(String fieldId) throws FieldNotFoundException { 158 Object field = versionableMutableFields.get(fieldId); 159 if (field == null) { 160 throw new FieldNotFoundException(fieldId); 161 } 162 return field; 163 } 164 165 public Map<String, Object> getNonVersionableFields() { 166 return nonVersionableFields; 167 } 168 169 public Map<String, Object> getVersionableFields() { 170 return versionableFields; 171 } 172 173 public Map<String, Object> getVersionableMutableFields() { 174 return versionableMutableFields; 175 } 176 177 public List<String> getNonVersionableFieldsToDelete() { 178 return nonVersionableFieldsToDelete; 179 } 180 181 public List<String> getVersionableFieldsToDelete() { 182 return versionableFieldsToDelete; 183 } 184 185 public List<String> getVersionableMutableFieldsToDelete() { 186 return versionableMutableFieldsToDelete; 187 } 188 189 public void addNonVersionableFieldsToDelete(List<String> fieldIds) { 190 this.nonVersionableFieldsToDelete .addAll(fieldIds); 191 } 192 193 public void addVersionableFieldsToDelete(List<String> fieldIds) { 194 this.versionableFieldsToDelete.addAll(fieldIds); 195 } 196 197 public void addVersionableMutableFieldsToDelete(List<String> fieldIds) { 198 this.versionableMutableFieldsToDelete.addAll(fieldIds); 199 } 200 201 public void removeNonVersionableFieldsToDelete(List<String> fieldIds) { 202 this.nonVersionableFieldsToDelete .removeAll(fieldIds); 203 } 204 205 public void removeVersionableFieldsToDelete(List<String> fieldIds) { 206 this.versionableFieldsToDelete.removeAll(fieldIds); 207 } 208 209 public void removeVersionableMutableFieldsToDelete(List<String> fieldIds) { 210 this.versionableMutableFieldsToDelete.removeAll(fieldIds); 211 } 212 213 public Record clone() { 214 RecordImpl record = new RecordImpl(); 215 record.id = id; 216 record.version = version; 217 record.recordTypeId = recordTypeId; 218 record.recordTypeVersion = recordTypeVersion; 219 record.nonVersionableRecordTypeId = nonVersionableRecordTypeId; 220 record.nonVersionableRecordTypeVersion = nonVersionableRecordTypeVersion; 221 record.versionableRecordTypeId = versionableRecordTypeId; 222 record.versionableRecordTypeVersion = versionableRecordTypeVersion; 223 record.versionableMutableRecordTypeId = versionableMutableRecordTypeId; 224 record.versionableMutableRecordTypeVersion = versionableMutableRecordTypeVersion; 225 record.nonVersionableFields.putAll(nonVersionableFields); 226 record.versionableFields.putAll(versionableFields); 227 record.versionableMutableFields.putAll(versionableMutableFields); 228 record.nonVersionableFieldsToDelete.addAll(nonVersionableFieldsToDelete); 229 record.versionableFieldsToDelete.addAll(versionableFieldsToDelete); 230 record.versionableMutableFieldsToDelete.addAll(versionableMutableFieldsToDelete); 231 return record; 117 232 } 118 233 … … 121 236 final int prime = 31; 122 237 int result = 1; 123 result = prime * result + ((deleteFields == null) ? 0 : deleteFields.hashCode()); 124 result = prime * result + ((fields == null) ? 0 : fields.hashCode()); 125 result = prime * result + ((recordId == null) ? 0 : recordId.hashCode()); 238 result = prime * result + ((id == null) ? 0 : id.hashCode()); 239 result = prime * result + ((nonVersionableFields == null) ? 0 : nonVersionableFields.hashCode()); 240 result = prime * result 241 + ((nonVersionableFieldsToDelete == null) ? 0 : nonVersionableFieldsToDelete.hashCode()); 242 result = prime * result + ((nonVersionableRecordTypeId == null) ? 0 : nonVersionableRecordTypeId.hashCode()); 243 result = prime * result 244 + ((nonVersionableRecordTypeVersion == null) ? 0 : nonVersionableRecordTypeVersion.hashCode()); 126 245 result = prime * result + ((recordTypeId == null) ? 0 : recordTypeId.hashCode()); 127 result = prime * result + (int) (recordTypeVersion ^ (recordTypeVersion >>> 32)); 128 result = prime * result + ((variantProperties == null) ? 0 : variantProperties.hashCode()); 246 result = prime * result + ((recordTypeVersion == null) ? 0 : recordTypeVersion.hashCode()); 129 247 result = prime * result + ((version == null) ? 0 : version.hashCode()); 248 result = prime * result + ((versionableFields == null) ? 0 : versionableFields.hashCode()); 249 result = prime * result + ((versionableFieldsToDelete == null) ? 0 : versionableFieldsToDelete.hashCode()); 250 result = prime * result + ((versionableMutableFields == null) ? 0 : versionableMutableFields.hashCode()); 251 result = prime 252 * result 253 + ((versionableMutableFieldsToDelete == null) ? 0 : versionableMutableFieldsToDelete.hashCode()); 254 result = prime * result 255 + ((versionableMutableRecordTypeId == null) ? 0 : versionableMutableRecordTypeId.hashCode()); 256 result = prime 257 * result 258 + ((versionableMutableRecordTypeVersion == null) ? 0 : versionableMutableRecordTypeVersion 259 .hashCode()); 260 result = prime * result + ((versionableRecordTypeId == null) ? 0 : versionableRecordTypeId.hashCode()); 261 result = prime * result 262 + ((versionableRecordTypeVersion == null) ? 0 : versionableRecordTypeVersion.hashCode()); 130 263 return result; 131 264 } … … 140 273 return false; 141 274 RecordImpl other = (RecordImpl) obj; 142 if (deleteFields == null) { 143 if (other.deleteFields != null) 144 return false; 145 } else if (!deleteFields.equals(other.deleteFields)) 146 return false; 147 if (fields == null) { 148 if (other.fields != null) 149 return false; 150 } else if (!fields.equals(other.fields)) 151 return false; 152 if (recordId == null) { 153 if (other.recordId != null) 154 return false; 155 } else if (!recordId.equals(other.recordId)) 275 if (id == null) { 276 if (other.id != null) 277 return false; 278 } else if (!id.equals(other.id)) 279 return false; 280 if (nonVersionableFields == null) { 281 if (other.nonVersionableFields != null) 282 return false; 283 } else if (!nonVersionableFields.equals(other.nonVersionableFields)) 284 return false; 285 if (nonVersionableFieldsToDelete == null) { 286 if (other.nonVersionableFieldsToDelete != null) 287 return false; 288 } else if (!nonVersionableFieldsToDelete.equals(other.nonVersionableFieldsToDelete)) 289 return false; 290 if (nonVersionableRecordTypeId == null) { 291 if (other.nonVersionableRecordTypeId != null) 292 return false; 293 } else if (!nonVersionableRecordTypeId.equals(other.nonVersionableRecordTypeId)) 294 return false; 295 if (nonVersionableRecordTypeVersion == null) { 296 if (other.nonVersionableRecordTypeVersion != null) 297 return false; 298 } else if (!nonVersionableRecordTypeVersion.equals(other.nonVersionableRecordTypeVersion)) 156 299 return false; 157 300 if (recordTypeId == null) { … … 160 303 } else if (!recordTypeId.equals(other.recordTypeId)) 161 304 return false; 162 if (recordTypeVersion != other.recordTypeVersion) 163 return false; 164 if (variantProperties == null) { 165 if (other.variantProperties != null) 166 return false; 167 } else if (!variantProperties.equals(other.variantProperties)) 305 if (recordTypeVersion == null) { 306 if (other.recordTypeVersion != null) 307 return false; 308 } else if (!recordTypeVersion.equals(other.recordTypeVersion)) 168 309 return false; 169 310 if (version == null) { … … 172 313 } else if (!version.equals(other.version)) 173 314 return false; 315 if (versionableFields == null) { 316 if (other.versionableFields != null) 317 return false; 318 } else if (!versionableFields.equals(other.versionableFields)) 319 return false; 320 if (versionableFieldsToDelete == null) { 321 if (other.versionableFieldsToDelete != null) 322 return false; 323 } else if (!versionableFieldsToDelete.equals(other.versionableFieldsToDelete)) 324 return false; 325 if (versionableMutableFields == null) { 326 if (other.versionableMutableFields != null) 327 return false; 328 } else if (!versionableMutableFields.equals(other.versionableMutableFields)) 329 return false; 330 if (versionableMutableFieldsToDelete == null) { 331 if (other.versionableMutableFieldsToDelete != null) 332 return false; 333 } else if (!versionableMutableFieldsToDelete.equals(other.versionableMutableFieldsToDelete)) 334 return false; 335 if (versionableMutableRecordTypeId == null) { 336 if (other.versionableMutableRecordTypeId != null) 337 return false; 338 } else if (!versionableMutableRecordTypeId.equals(other.versionableMutableRecordTypeId)) 339 return false; 340 if (versionableMutableRecordTypeVersion == null) { 341 if (other.versionableMutableRecordTypeVersion != null) 342 return false; 343 } else if (!versionableMutableRecordTypeVersion.equals(other.versionableMutableRecordTypeVersion)) 344 return false; 345 if (versionableRecordTypeId == null) { 346 if (other.versionableRecordTypeId != null) 347 return false; 348 } else if (!versionableRecordTypeId.equals(other.versionableRecordTypeId)) 349 return false; 350 if (versionableRecordTypeVersion == null) { 351 if (other.versionableRecordTypeVersion != null) 352 return false; 353 } else if (!versionableRecordTypeVersion.equals(other.versionableRecordTypeVersion)) 354 return false; 174 355 return true; 175 356 } … … 177 358 @Override 178 359 public String toString() { 179 return "RecordImpl [recordId=" + recordId + ", version=" + version + ", recordTypeId=" + recordTypeId 180 + ", recordTypeVersion=" + recordTypeVersion + ", variantProperties=" + variantProperties 181 + ", fields=" + fields + ", deleteFields=" + deleteFields + "]"; 182 } 183 184 185 360 return "RecordImpl [id=" + id + ", version=" + version + ", recordTypeId=" + recordTypeId 361 + ", recordTypeVersion=" + recordTypeVersion + ", nonVersionableRecordTypeId=" 362 + nonVersionableRecordTypeId + ", nonVersionableRecordTypeVersion=" 363 + nonVersionableRecordTypeVersion + ", versionableMutableRecordTypeId=" 364 + versionableMutableRecordTypeId + ", versionableMutableRecordTypeVersion=" 365 + versionableMutableRecordTypeVersion + ", versionableRecordTypeId=" + versionableRecordTypeId 366 + ", versionableRecordTypeVersion=" + versionableRecordTypeVersion + ", nonVersionableFields=" 367 + nonVersionableFields + ", nonVersionableFieldsToDelete=" + nonVersionableFieldsToDelete 368 + ", versionableFields=" + versionableFields + ", versionableFieldsToDelete=" 369 + versionableFieldsToDelete + ", versionableMutableFields=" + versionableMutableFields 370 + ", versionableMutableFieldsToDelete=" + versionableMutableFieldsToDelete + "]"; 371 } 186 372 } -
projects/lily/trunk/repository/impl/src/main/java/org/lilycms/repository/impl/RecordTypeImpl.java
r3943 r3977 16 16 package org.lilycms.repository.impl; 17 17 18 import java.util.Collection;19 import java.util.HashMap;20 import java.util.Map;21 22 import org.lilycms.repository.api.FieldDescriptor;23 18 import org.lilycms.repository.api.RecordType; 19 import org.lilycms.repository.api.TypeManager; 24 20 25 21 public class RecordTypeImpl implements RecordType { 26 22 27 private final String recordTypeId; 28 private Map<String, FieldDescriptor> fieldDescriptors = new HashMap<String, FieldDescriptor>(); 23 private final String id; 29 24 private Long version; 25 private String nonVersionableFieldGroupId; 26 private String versionableFieldGroupId; 27 private String versionableMutableFieldGroupId; 28 private Long nonVersionableFieldGroupVersion; 29 private Long versionableFieldGroupVersion; 30 private Long versionableMutableFieldGroupVersion; 30 31 31 32 /** … … 33 34 * @use {@link TypeManager#newRecordType} instead 34 35 */ 35 public RecordTypeImpl(String recordTypeId) {36 this. recordTypeId = recordTypeId;36 public RecordTypeImpl(String id) { 37 this.id = id; 37 38 } 38 39 39 public void addFieldDescriptor(FieldDescriptor fieldDescriptor) {40 fieldDescriptors.put(fieldDescriptor.getId(), fieldDescriptor);41 }42 43 public void removeFieldDescriptor(String fieldDescriptorId) {44 fieldDescriptors.remove(fieldDescriptorId);45 }46 47 public FieldDescriptor getFieldDescriptor(String fieldDescriptorId) {48 return fieldDescriptors.get(fieldDescriptorId);49 }50 51 public Collection<FieldDescriptor> getFieldDescriptors() {52 return fieldDescriptors.values();53 }54 55 40 public String getId() { 56 return recordTypeId;41 return id; 57 42 } 58 43 … … 64 49 this.version = version; 65 50 } 51 52 public String getNonVersionableFieldGroupId() { 53 return nonVersionableFieldGroupId; 54 } 55 56 public Long getNonVersionableFieldGroupVersion() { 57 return nonVersionableFieldGroupVersion; 58 } 59 60 public String getVersionableFieldGroupId() { 61 return versionableFieldGroupId; 62 } 63 64 65 public Long getVersionableFieldGroupVersion() { 66 return versionableFieldGroupVersion; 67 } 68 69 public String getVersionableMutableFieldGroupId() { 70 return versionableMutableFieldGroupId; 71 } 72 73 public Long getVersionableMutableFieldGroupVersion() { 74 return versionableMutableFieldGroupVersion; 75 } 76 77 public void setNonVersionableFieldGroupId(String id) { 78 nonVersionableFieldGroupId = id; 79 } 80 81 public void setNonVersionableFieldGroupVersion(Long version) { 82 nonVersionableFieldGroupVersion = version; 83 } 84 85 public void setVersionableFieldGroupId(String id) { 86 versionableFieldGroupId = id; 87 } 88 89 public void setVersionableFieldGroupVersion(Long version) { 90 versionableFieldGroupVersion = version; 91 } 92 93 public void setVersionableMutableFieldGroupId(String id) { 94 versionableMutableFieldGroupId = id; 95 } 96 97 public void setVersionableMutableFieldGroupVersion(Long version) { 98 versionableMutableFieldGroupVersion = version; 99 } 100 101 public RecordType clone() { 102 RecordTypeImpl clone = new RecordTypeImpl(this.id); 103 clone.version = this.version; 104 clone.nonVersionableFieldGroupId = this.nonVersionableFieldGroupId; 105 clone.nonVersionableFieldGroupVersion = this.nonVersionableFieldGroupVersion; 106 clone.versionableFieldGroupId = this.versionableFieldGroupId; 107 clone.versionableFieldGroupVersion = this.versionableFieldGroupVersion; 108 clone.versionableMutableFieldGroupId = this.versionableMutableFieldGroupId; 109 clone.versionableMutableFieldGroupVersion = this.versionableMutableFieldGroupVersion; 110 return clone; 111 } 112 113 @Override 114 public int hashCode() { 115 final int prime = 31; 116 int result = 1; 117 result = prime * result + ((id == null) ? 0 : id.hashCode()); 118 result = prime * result + ((nonVersionableFieldGroupId == null) ? 0 : nonVersionableFieldGroupId.hashCode()); 119 result = prime * result 120 + ((nonVersionableFieldGroupVersion == null) ? 0 : nonVersionableFieldGroupVersion.hashCode()); 121 result = prime * result + ((version == null) ? 0 : version.hashCode()); 122 result = prime * result + ((versionableFieldGroupId == null) ? 0 : versionableFieldGroupId.hashCode()); 123 result = prime * result 124 + ((versionableFieldGroupVersion == null) ? 0 : versionableFieldGroupVersion.hashCode()); 125 result = prime * result 126 + ((versionableMutableFieldGroupId == null) ? 0 : versionableMutableFieldGroupId.hashCode()); 127 result = prime 128 * result 129 + ((versionableMutableFieldGroupVersion == null) ? 0 : versionableMutableFieldGroupVersion 130 .hashCode()); 131 return result; 132 } 133 134 @Override 135 public boolean equals(Object obj) { 136 if (this == obj) 137 return true; 138 if (obj == null) 139 return false; 140 if (getClass() != obj.getClass()) 141 return false; 142 RecordTypeImpl other = (RecordTypeImpl) obj; 143 if (id == null) { 144 if (other.id != null) 145 return false; 146 } else if (!id.equals(other.id)) 147 return false; 148 if (nonVersionableFieldGroupId == null) { 149 if (other.nonVersionableFieldGroupId != null) 150 return false; 151 } else if (!nonVersionableFieldGroupId.equals(other.nonVersionableFieldGroupId)) 152 return false; 153 if (nonVersionableFieldGroupVersion == null) { 154 if (other.nonVersionableFieldGroupVersion != null) 155 return false; 156 } else if (!nonVersionableFieldGroupVersion.equals(other.nonVersionableFieldGroupVersion)) 157 return false; 158 if (version == null) { 159 if (other.version != null) 160 return false; 161 } else if (!version.equals(other.version)) 162 return false; 163 if (versionableFieldGroupId == null) { 164 if (other.versionableFieldGroupId != null) 165 return false; 166 } else if (!versionableFieldGroupId.equals(other.versionableFieldGroupId)) 167 return false; 168 if (versionableFieldGroupVersion == null) { 169 if (other.versionableFieldGroupVersion != null) 170 return false; 171 } else if (!versionableFieldGroupVersion.equals(other.versionableFieldGroupVersion)) 172 return false; 173 if (versionableMutableFieldGroupId == null) { 174 if (other.versionableMutableFieldGroupId != null) 175 return false; 176 } else if (!versionableMutableFieldGroupId.equals(other.versionableMutableFieldGroupId)) 177 return false; 178 if (versionableMutableFieldGroupVersion == null) { 179 if (other.versionableMutableFieldGroupVersion != null) 180 return false; 181 } else if (!versionableMutableFieldGroupVersion.equals(other.versionableMutableFieldGroupVersion)) 182 return false; 183 return true; 184 } 185 186 @Override 187 public String toString() { 188 return "RecordTypeImpl [id=" + id + ", version=" + version + ", nonVersionableFieldGroupId=" 189 + nonVersionableFieldGroupId + ", nonVersionableFieldGroupVersion=" 190 + nonVersionableFieldGroupVersion + ", versionableFieldGroupId=" + versionableFieldGroupId 191 + ", versionableFieldGroupVersion=" + versionableFieldGroupVersion 192 + ", versionableMutableFieldGroupId=" + versionableMutableFieldGroupId 193 + ", versionableMutableFieldGroupVersion=" + versionableMutableFieldGroupVersion + "]"; 194 } 66 195 } -
projects/lily/trunk/repository/impl/src/test/java/org/lilycms/repository/impl/test/HBaseRepositoryTest.java
r3955 r3977 16 16 package org.lilycms.repository.impl.test; 17 17 18 import static org.easymock.EasyMock.anyLong; 19 import static org.easymock.EasyMock.expect; 20 import static org.easymock.EasyMock.isA; 21 import static org.easymock.classextension.EasyMock.createControl; 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.fail; 24 18 import static org.junit.Assert.*; 19 20 import java.util.Arrays; 25 21 import java.util.HashMap; 26 22 import java.util.Map; 27 23 28 24 import org.apache.hadoop.hbase.HBaseTestingUtility; 29 import org.easymock.classextension.IMocksControl;30 25 import org.junit.After; 31 26 import org.junit.AfterClass; … … 34 29 import org.junit.Test; 35 30 import org.lilycms.repository.api.FieldDescriptor; 31 import org.lilycms.repository.api.FieldGroup; 36 32 import org.lilycms.repository.api.FieldNotFoundException; 37 33 import org.lilycms.repository.api.IdGenerator; … … 42 38 import org.lilycms.repository.api.RecordNotFoundException; 43 39 import org.lilycms.repository.api.RecordType; 40 import org.lilycms.repository.api.RecordTypeNotFoundException; 44 41 import org.lilycms.repository.api.Repository; 45 42 import org.lilycms.repository.api.TypeManager; 46 import org.lilycms.repository.impl.FieldDescriptorImpl;47 43 import org.lilycms.repository.impl.HBaseRepository; 44 import org.lilycms.repository.impl.HBaseTypeManager; 48 45 import org.lilycms.repository.impl.IdGeneratorImpl; 49 import org.lilycms.repository.impl.RecordImpl;50 import org.lilycms.repository.impl.StringValueType;51 import org.lilycms.repository.impl.ValueTypeImpl;52 46 import org.lilycms.testfw.TestHelper; 53 47 … … 55 49 56 50 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 51 private static IdGenerator idGenerator = new IdGeneratorImpl(); 52 private static TypeManager typeManager; 53 private static Repository repository; 54 private static FieldDescriptor fieldDescriptor1; 55 private static FieldDescriptor fieldDescriptor1B; 56 private static FieldDescriptor fieldDescriptor2; 57 private static FieldDescriptor fieldDescriptor3; 58 private static FieldGroup fieldGroup1; 59 private static FieldGroup fieldGroup1B; 60 private static FieldGroup fieldGroup2; 61 private static FieldGroup fieldGroup3; 62 private static RecordType recordType1; 63 private static RecordType recordType1B; 64 private static RecordType recordType2; 57 65 58 66 @BeforeClass … … 60 68 TestHelper.setupLogging(); 61 69 TEST_UTIL.startMiniCluster(1); 70 typeManager = new HBaseTypeManager(idGenerator, TEST_UTIL.getConfiguration()); 71 repository = new HBaseRepository(typeManager, idGenerator, TEST_UTIL.getConfiguration()); 72 setupTypes(); 73 } 74 75 private static void setupTypes() throws Exception { 76 setupFieldDescriptors(); 77 setupFieldGroups(); 78 setupRecordTypes(); 79 } 80 81 private static void setupFieldDescriptors() throws Exception { 82 fieldDescriptor1 = typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("FD1", typeManager.getValueType("STRING", false, false), "GN1")); 83 fieldDescriptor1B = typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("FD1B", typeManager.getValueType("STRING", false, false), "GN1B")); 84 fieldDescriptor2 = typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("FD2", typeManager.getValueType("INTEGER", false, false), "GN2")); 85 fieldDescriptor3 = typeManager.createFieldDescriptor(typeManager.newFieldDescriptor("FD3", typeManager.getValueType("BOOLEAN", false, false), "GN3")); 86 } 87 88 private static void setupFieldGroups() throws Exception { 89 FieldGroup fieldGroup = typeManager.newFieldGroup("FG1"); 90 fieldGroup.setFieldGroupEntry(typeManager.newFieldGroupEntry(fieldDescriptor1.getId(), fieldDescriptor1.getVersion(), false, "alias1")); 91 fieldGroup1 = typeManager.createFieldGroup(fieldGroup); 92 fieldGroup = typeManager.newFieldGroup("FG1"); 93 fieldGroup.setFieldGroupEntry(typeManager.newFieldGroupEntry(fieldDescriptor1B.getId(), fieldDescriptor1B.getVersion(), false, "alias1B")); 94 fieldGroup1B = typeManager.updateFieldGroup(fieldGroup); 95 96 fieldGroup = typeManager.newFieldGroup("FG2"); 97 fieldGroup.setFieldGroupEntry(typeManager.newFieldGroupEntry(fieldDescriptor2.getId(), fieldDescriptor2.getVersion(), false, "alias2")); 98 fieldGroup2 = typeManager.createFieldGroup(fieldGroup); 99 fieldGroup = typeManager.newFieldGroup("FG3"); 100 fieldGroup.setFieldGroupEntry(typeManager.newFieldGroupEntry(fieldDescriptor3.getId(), fieldDescriptor3.getVersion(), false, "alias3")); 101 fieldGroup3 = typeManager.createFieldGroup(fieldGroup); 102 } 103 104 private static void setupRecordTypes() throws Exception { 105 recordType1 = typeManager.newRecordType("RT1"); 106 recordType1.setNonVersionableFieldGroupId(fieldGroup1.getId()); 107 recordType1.setNonVersionableFieldGroupVersion(fieldGroup1.getVersion()); 108 recordType1.setVersionableFieldGroupId(fieldGroup2.getId()); 109 recordType1.setVersionableFieldGroupVersion(fieldGroup2.getVersion()); 110 recordType1.setVersionableMutableFieldGroupId(fieldGroup3.getId()); 111 recordType1.setVersionableMutableFieldGroupVersion(fieldGroup3.getVersion()); 112 recordType1 = typeManager.createRecordType(recordType1); 113 114 recordType1B = recordType1.clone(); 115 recordType1B.setNonVersionableFieldGroupId(fieldGroup1B.getId()); 116 recordType1B.setNonVersionableFieldGroupVersion(fieldGroup1B.getVersion()); 117 recordType1B = typeManager.updateRecordType(recordType1B); 118 119 recordType2 = typeManager.newRecordType("RT2"); 120 recordType2.setNonVersionableFieldGroupId(fieldGroup2.getId()); 121 recordType2.setNonVersionableFieldGroupVersion(fieldGroup2.getVersion()); 122 recordType2.setVersionableFieldGroupId(fieldGroup3.getId()); 123 recordType2.setVersionableFieldGroupVersion(fieldGroup3.getVersion()); 124 recordType2.setVersionableMutableFieldGroupId(fieldGroup1.getId()); 125 recordType2.setVersionableMutableFieldGroupVersion(fieldGroup1.getVersion()); 126 recordType2 = typeManager.createRecordType(recordType2); 62 127 } 63 128 … … 67 132 } 68 133 69 private Repository repository;70 private IMocksControl control;71 private TypeManager typeManager;72 private RecordType recordType;73 private FieldDescriptor versionableFieldDescriptor;74 private FieldDescriptor nonVersionableFieldDescriptor;75 private IdGenerator idGenerator;76 77 134 @Before 78 135 public void setUp() throws Exception { 79 control = createControl();80 typeManager = control.createMock(TypeManager.class);81 expect(typeManager.getValueType("STRING", false, false)).andReturn(new ValueTypeImpl(new StringValueType(), false, false)).anyTimes();82 recordType = control.createMock(RecordType.class);83 expect(typeManager.getRecordType(isA(String.class), anyLong())).andReturn(recordType).anyTimes();84 expect(typeManager.getRecordType(isA(String.class))).andReturn(recordType).anyTimes();85 expect(recordType.getId()).andReturn("dummyRecordType").anyTimes();86 expect(recordType.getVersion()).andReturn(Long.valueOf(0)).anyTimes();87 88 // Using FieldDescriptorImpl since typeManager is a mock89 versionableFieldDescriptor = new FieldDescriptorImpl("aVersionableFieldDescriptor", Long.valueOf(1), new ValueTypeImpl(new StringValueType(), false, false), true, true);90 nonVersionableFieldDescriptor = new FieldDescriptorImpl("aNonVersionableFieldDescriptor", Long.valueOf(1), new ValueTypeImpl(new StringValueType(), false, false), true, false);91 92 idGenerator = new IdGeneratorImpl();93 repository = new HBaseRepository(typeManager, idGenerator, RecordImpl.class, TEST_UTIL.getConfiguration());94 136 } 95 137 96 138 @After 97 139 public void tearDown() throws Exception { 98 control.reset(); 99 } 100 101 @Test 102 public void testEmptyRecord() throws Exception { 103 control.replay(); 104 Record record = generateRecord(); 105 140 } 141 142 @Test 143 public void testRecordCreateWithoutRecordType() throws Exception { 144 Record record = repository.newRecord(idGenerator.newRecordId()); 145 try { 146 record = repository.create(record); 147 } catch (InvalidRecordException expected){ 148 } 149 } 150 151 @Test 152 public void testRecordUpdateWithoutRecordType() throws Exception { 153 Record record = createDefaultRecord(idGenerator.newRecordId()); 154 Record updateRecord = repository.newRecord(record.getId()); 155 try { 156 record = repository.update(updateRecord); 157 } catch (InvalidRecordException expected){ 158 } 159 } 160 161 @Test 162 public void testEmptyRecordCreate() throws Exception { 163 Record record = repository.newRecord(idGenerator.newRecordId()); 164 record.setRecordType(recordType1.getId(), null); 165 try { 166 record = repository.create(record); 167 } catch (InvalidRecordException expected){ 168 } 169 } 170 171 @Test 172 public void testCreate() throws Exception { 173 RecordId recordId = idGenerator.newRecordId(); 174 Record createdRecord = createDefaultRecord(recordId); 175 176 assertEquals(Long.valueOf(1), createdRecord.getVersion()); 177 assertEquals("value1", createdRecord.getNonVersionableField(fieldDescriptor1.getId())); 178 assertEquals(123, createdRecord.getVersionableField(fieldDescriptor2.getId())); 179 assertTrue((Boolean)createdRecord.getVersionableMutableField(fieldDescriptor3.getId())); 180 assertEquals(recordType1.getId(), createdRecord.getRecordTypeId()); 181 assertEquals(Long.valueOf(1), createdRecord.getRecordTypeVersion()); 182 assertEquals(recordType1.getId(), createdRecord.getNonVersionableRecordTypeId()); 183 assertEquals(Long.valueOf(1), createdRecord.getNonVersionableRecordTypeVersion()); 184 assertEquals(recordType1.getId(), createdRecord.getVersionableRecordTypeId()); 185 assertEquals(Long.valueOf(1), createdRecord.getVersionableRecordTypeVersion()); 186 assertEquals(recordType1.getId(), createdRecord.getVersionableMutableRecordTypeId()); 187 assertEquals(Long.valueOf(1), createdRecord.getVersionableMutableRecordTypeVersion()); 188 189 assertEquals(createdRecord, repository.read(recordId)); 190 } 191 192 private Record createDefaultRecord(RecordId recordId) throws Exception { 193 Record record = repository.newRecord(recordId); 194 record.setRecordType(recordType1.getId(), recordType1.getVersion()); 195 record.setNonVersionableField(fieldDescriptor1.getId(), "value1"); 196 record.setVersionableField(fieldDescriptor2.getId(), 123); 197 record.setVersionableMutableField(fieldDescriptor3.getId(), true); 198 return repository.create(record); 199 } 200 201 @Test 202 public void testCreateExistingRecordFails() throws Exception { 203 Record record = createDefaultRecord(idGenerator.newRecordId()); 204 106 205 try { 107 206 repository.create(record); 108 fail("A record should at least have some fields"); 109 } catch (InvalidRecordException expected) { 110 } 111 control.verify(); 112 } 113 114 @Test 115 public void testEmptyUpdateRecord() throws Exception { 116 expect(recordType.getFieldDescriptor("aField")).andReturn(versionableFieldDescriptor); 117 118 control.replay(); 119 Record record = generateRecord(new String[]{"aField" , "aValue", "false"}); 120 repository.create(record); 121 122 Record emptyRecord = repository.newRecord(record.getId()); 123 124 try { 125 repository.update(emptyRecord); 126 fail("A record should at least have some fields"); 127 } catch (Exception expected) { 128 } 129 control.verify(); 130 } 131 132 @Test 133 public void testNonVersionedRecord() throws Exception { 134 expect(recordType.getFieldDescriptor("aField")).andReturn(nonVersionableFieldDescriptor).times(2); 135 136 control.replay(); 137 Record record = generateRecord(new String[] { "aField", "aValue"}); 138 repository.create(record); 139 Record actualRecord = repository.read(record.getId()); 140 assertEquals(record, actualRecord); 141 control.verify(); 142 } 143 144 @Test 145 public void testMultipleFields() throws Exception { 146 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(nonVersionableFieldDescriptor).times(4); 147 148 control.replay(); 149 Record record = generateRecord(new String[] { "aField", "aValue"}, new String[] {"aField2", "aValue2"}); 150 repository.create(record); 151 Record actualRecord = repository.read(record.getId()); 152 assertEquals(record, actualRecord); 153 control.verify(); 154 } 155 156 @Test 157 public void testCreateExistingRecord() throws Exception { 158 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(nonVersionableFieldDescriptor); 159 160 control.replay(); 161 Record record = generateRecord(new String[] { "aField", "aValue"}); 162 repository.create(record); 207 fail(); 208 } catch (RecordExistsException expected) { 209 } 210 } 211 212 @Test 213 public void testCreateWithNonExistingRecordTypeFails() throws Exception { 214 Record record = repository.newRecord(idGenerator.newRecordId()); 215 record.setRecordType("nonExistingRecordType", null); 216 record.setNonVersionableField(fieldDescriptor1.getId(), "value1"); 163 217 try { 164 218 repository.create(record); 165 fail("Create of an existing record is not allowed"); 166 } catch (RecordExistsException expected) { 167 } 168 control.verify(); 169 } 170 171 @Test 172 public void testUpdateNonExistingRecord() throws Exception { 173 control.replay(); 174 Record record = repository.newRecord(idGenerator.newRecordId("nonExistingRecordId")); 175 176 try { 177 repository.update(record); 178 fail("Cannot update a non-existing document"); 219 fail(); 220 } catch (RecordTypeNotFoundException expected) { 221 } 222 } 223 224 @Test 225 public void testCreateUsesLatestRecordType() throws Exception { 226 Record record = repository.newRecord(idGenerator.newRecordId()); 227 record.setRecordType(recordType1.getId(), null); 228 record.setNonVersionableField(fieldDescriptor1.getId(), "value1"); 229 Record createdRecord = repository.create(record); 230 assertEquals(recordType1.getId(), createdRecord.getRecordTypeId()); 231 assertEquals(Long.valueOf(2), createdRecord.getRecordTypeVersion()); 232 assertEquals(recordType1.getId(), createdRecord.getNonVersionableRecordTypeId()); 233 assertEquals(Long.valueOf(2), createdRecord.getNonVersionableRecordTypeVersion()); 234 assertNull(createdRecord.getVersionableRecordTypeId()); 235 assertNull(createdRecord.getVersionableRecordTypeVersion()); 236 assertNull(createdRecord.getVersionableMutableRecordTypeId()); 237 assertNull(createdRecord.getVersionableMutableRecordTypeVersion()); 238 239 assertEquals(createdRecord, repository.read(record.getId())); 240 } 241 242 @Test 243 public void testCreateVariant() throws Exception { 244 Record record = createDefaultRecord(idGenerator.newRecordId()); 245 246 Map<String, String> variantProperties = new HashMap<String, String>(); 247 variantProperties.put("dimension1", "dimval1"); 248 Record variant = repository.newRecord(idGenerator.newRecordId(record.getId(), variantProperties )); 249 variant.setRecordType(recordType1.getId(), null); 250 variant.setNonVersionableField(fieldDescriptor1.getId(), "value2"); 251 variant.setVersionableField(fieldDescriptor2.getId(), 567); 252 variant.setVersionableMutableField(fieldDescriptor3.getId(), false); 253 254 Record createdVariant = repository.create(variant); 255 256 assertEquals(Long.valueOf(1), createdVariant.getVersion()); 257 assertEquals("value2", createdVariant.getNonVersionableField(fieldDescriptor1.getId())); 258 assertEquals(567, createdVariant.getVersionableField(fieldDescriptor2.getId())); 259 assertFalse((Boolean)createdVariant.getVersionableMutableField(fieldDescriptor3.getId())); 260 261 assertEquals(createdVariant, repository.read(variant.getId())); 262 } 263 264 @Test 265 public void testUpdate() throws Exception { 266 Record record = createDefaultRecord(idGenerator.newRecordId()); 267 Record updateRecord = record.clone(); 268 updateRecord.setNonVersionableField(fieldDescriptor1.getId(), "value2"); 269 updateRecord.setVersionableField(fieldDescriptor2.getId(), 789); 270 updateRecord.setVersionableMutableField(fieldDescriptor3.getId(), false); 271 272 Record updatedRecord = repository.update(updateRecord); 273 274 assertEquals(Long.valueOf(2), updatedRecord.getVersion()); 275 assertEquals("value2", updatedRecord.getNonVersionableField(fieldDescriptor1.getId())); 276 assertEquals(789, updatedRecord.getVersionableField(fieldDescriptor2.getId())); 277 assertEquals(false, updatedRecord.getVersionableMutableField(fieldDescriptor3.getId())); 278 279 assertEquals(updatedRecord, repository.read(record.getId())); 280 } 281 282 @Test 283 public void testUpdateOnlyOneField() throws Exception { 284 Record record = createDefaultRecord(idGenerator.newRecordId()); 285 Record updateRecord = repository.newRecord(record.getId()); 286 updateRecord.setRecordType(record.getRecordTypeId(), record.getRecordTypeVersion()); 287 updateRecord.setNonVersionableField(fieldDescriptor1.getId(), "value2"); 288 289 Record updatedRecord = repository.update(updateRecord); 290 291 assertEquals(Long.valueOf(1), updatedRecord.getVersion()); 292 assertEquals("value2", updatedRecord.getNonVersionableField(fieldDescriptor1.getId())); 293 try { 294 updatedRecord.getVersionableField(fieldDescriptor2.getId()); 295 fail(); 296 } catch (FieldNotFoundException expected) { 297 } 298 try { 299 updatedRecord.getVersionableMutableField(fieldDescriptor3.getId()); 300 fail(); 301 } catch (FieldNotFoundException expected) { 302 } 303 304 updatedRecord = repository.read(record.getId()); 305 assertEquals("value2", updatedRecord.getNonVersionableField(fieldDescriptor1.getId())); 306 assertEquals(123, updatedRecord.getVersionableField(fieldDescriptor2.getId())); 307 assertEquals(true, updatedRecord.getVersionableMutableField(fieldDescriptor3.getId())); 308 } 309 310 @Test 311 public void testEmptyUpdate() throws Exception { 312 Record record = createDefaultRecord(idGenerator.newRecordId()); 313 Record updateRecord = repository.newRecord(record.getId()); 314 updateRecord.setRecordType(record.getRecordTypeId(), record.getRecordTypeVersion()); 315 316 Record updatedRecord = repository.update(updateRecord); 317 318 assertEquals(Long.valueOf(1), updatedRecord.getVersion()); 319 try { 320 updatedRecord.getNonVersionableField(fieldDescriptor1.getId()); 321 fail(); 322 } catch (FieldNotFoundException expected) { 323 } 324 try { 325 updatedRecord.getVersionableField(fieldDescriptor2.getId()); 326 fail(); 327 } catch (FieldNotFoundException expected) { 328 } 329 try { 330 updatedRecord.getVersionableMutableField(fieldDescriptor3.getId()); 331 fail(); 332 } catch (FieldNotFoundException expected) { 333 } 334 335 assertEquals(record, repository.read(record.getId())); 336 } 337 338 @Test 339 public void testIdempotentUpdate() throws Exception { 340 Record record = createDefaultRecord(idGenerator.newRecordId()); 341 Record updateRecord = record.clone(); 342 343 Record updatedRecord = repository.update(updateRecord); 344 345 assertEquals(Long.valueOf(1), updatedRecord.getVersion()); 346 assertEquals("value1", updatedRecord.getNonVersionableField(fieldDescriptor1.getId())); 347 assertEquals(123, updatedRecord.getVersionableField(fieldDescriptor2.getId())); 348 assertEquals(true, updatedRecord.getVersionableMutableField(fieldDescriptor3.getId())); 349 350 assertEquals(record, repository.read(record.getId())); 351 } 352 353 @Test 354 public void testUpdateIgnoresVersion() throws Exception { 355 Record record = createDefaultRecord(idGenerator.newRecordId()); 356 Record updateRecord = record.clone(); 357 updateRecord.setVersion(Long.valueOf(99)); 358 updateRecord.setNonVersionableField(fieldDescriptor1.getId(), "value2"); 359 360 Record updatedRecord = repository.update(updateRecord); 361 362 assertEquals(Long.valueOf(1), updatedRecord.getVersion()); 363 364 assertEquals(updatedRecord, repository.read(record.getId())); 365 } 366 367 @Test 368 public void testUpdateNonVersionable() throws Exception { 369 Record record = createDefaultRecord(idGenerator.newRecordId()); 370 Record updateRecord = repository.newRecord(record.getId()); 371 updateRecord.setRecordType(record.getRecordTypeId(), null); 372 updateRecord.setNonVersionableField(fieldDescriptor1.getId(), "aNewValue"); 373 repository.update(updateRecord); 374 375 Record readRecord = repository.read(record.getId()); 376 assertEquals(Long.valueOf(1), readRecord.getVersion()); 377 assertEquals("aNewValue", readRecord.getNonVersionableField(fieldDescriptor1.getId())); 378 } 379 380 381 @Test 382 public void testReadOlderVersions() throws Exception { 383 Record record = createDefaultRecord(idGenerator.newRecordId()); 384 Record updateRecord = record.clone(); 385 updateRecord.setNonVersionableField(fieldDescriptor1.getId(), "value2"); 386 updateRecord.setVersionableField(fieldDescriptor2.getId(), 789); 387 updateRecord.setVersionableMutableField(fieldDescriptor3.getId(), false); 388 389 repository.update(updateRecord); 390 391 record.setNonVersionableField(fieldDescriptor1.getId(), "value2"); 392 assertEquals(record, repository.read(record.getId(), Long.valueOf(1))); 393 } 394 395 @Test 396 public void testReadNonExistingRecord() throws Exception { 397 try { 398 repository.read(idGenerator.newRecordId()); 399 fail(); 179 400 } catch (RecordNotFoundException expected) { 180 401 } 181 control.verify(); 182 } 183 184 @Test 185 public void testUpdateRecord() throws Exception { 186 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(nonVersionableFieldDescriptor).times(3); 187 188 control.replay(); 189 Record record = generateRecord(new String[] { "aField", "aValue"}); 190 repository.create(record); 191 192 record.setField("aField", "anotherValue"); 193 repository.update(record); 194 195 assertEquals(record, repository.read(record.getId())); 196 control.verify(); 197 } 198 199 @Test 200 public void testUpdateRecordWithExtraField() throws Exception { 201 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(nonVersionableFieldDescriptor).anyTimes(); 202 203 control.replay(); 204 Record record = generateRecord(new String[] { "aField", "aValue"}); 205 repository.create(record); 206 207 // TODO avoid updates of non-changed fields 208 record.setField("anotherField", "anotherValue"); 209 repository.update(record); 210 Record actualRecord = repository.read(record.getId()); 211 assertEquals(2, record.getFields().size()); 212 assertEquals(record, actualRecord); 213 control.verify(); 214 } 215 216 @Test 217 public void testReadNonExistingRecord() throws Exception { 218 control.replay(); 219 try { 220 repository.read(idGenerator.newRecordId("readNonExistingRecordId")); 221 fail("A RecordNotFoundException should be thrown"); 402 } 403 404 @Test 405 public void testReadTooRecentRecord() throws Exception { 406 Record record = createDefaultRecord(idGenerator.newRecordId()); 407 try { 408 repository.read(record.getId(), Long.valueOf(2)); 409 fail(); 222 410 } catch (RecordNotFoundException expected) { 223 411 } 224 control.verify();225 }226 227 @Test228 public void testReadAll() throws Exception {229 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(nonVersionableFieldDescriptor).anyTimes();230 231 control.replay();232 Record record = generateRecord(new String[] { "field1", "value1"}, new String[] { "field2",233 "value2"}, new String[] { "field3", "value3"});234 repository.create(record);235 Record actualRecord = repository.read(record.getId());236 assertEquals(record, actualRecord);237 assertEquals(record.getId(), actualRecord.getId());238 assertEquals(3, actualRecord.getFields().size());239 assertEquals("value1", actualRecord.getField("field1"));240 assertEquals("value2", actualRecord.getField("field2"));241 assertEquals("value3", actualRecord.getField("field3"));242 control.verify();243 }244 245 @Test246 public void testRecordDelete() throws Exception {247 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(nonVersionableFieldDescriptor).anyTimes();248 249 control.replay();250 Record record = generateRecord(new String[] { "field1", "value1"}, new String[] { "field2","value2"}, new String[] { "field3", "value3"});251 repository.create(record);252 RecordId recordId = record.getId();253 Record actualRecord = repository.read(recordId);254 assertEquals(record, actualRecord);255 repository.delete(recordId);256 try {257 repository.read(recordId);258 fail("A RecordNotFoundException should be thrown");259 } catch(RecordNotFoundException expected) {260 }261 control.verify();262 }263 264 @Test265 public void testCreateVersionableAndNonVersionable() throws Exception {266 expect(recordType.getFieldDescriptor("field1")).andReturn(nonVersionableFieldDescriptor).times(2);267 expect(recordType.getFieldDescriptor("field2")).andReturn(versionableFieldDescriptor).times(2);268 269 control.replay();270 Record record = generateRecord(new String[] { "field1", "value1",}, new String[] { "field2","value2"});271 repository.create(record);272 Record actualRecord = repository.read(record.getId());273 assertEquals(record, actualRecord);274 control.verify();275 }276 277 @Test278 public void testReadVersionableAndNonVersionableField() throws Exception {279 expect(recordType.getFieldDescriptor("field1")).andReturn(nonVersionableFieldDescriptor).times(3);280 expect(recordType.getFieldDescriptor("field2")).andReturn(versionableFieldDescriptor).times(3);281 282 control.replay();283 Record record = generateRecord(new String[] { "field1", "value1"}, new String[] { "field2",284 "value2"});285 repository.create(record);286 Record actualRecord = repository.read(record.getId(), "field1", "field2");287 assertEquals(record, actualRecord);288 control.verify();289 }290 291 @Test292 public void testVersionableField() throws Exception {293 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes();294 295 control.replay();296 Record record = generateRecord(new String[] { "versionableField1", "value1"});297 repository.create(record);298 record.setField("versionableField1", "value2");299 repository.update(record);300 301 Record actualRecord = repository.read(record.getId());302 assertEquals("value2", actualRecord.getField("versionableField1"));303 assertEquals(Long.valueOf(2), actualRecord.getVersion());304 305 actualRecord = repository.read(record.getId(), Long.valueOf(1));306 assertEquals("value1", actualRecord.getField("versionableField1"));307 assertEquals(Long.valueOf(1), actualRecord.getVersion());308 control.verify();309 }310 311 @Test312 public void testVersionableFields() throws Exception {313 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes();314 315 control.replay();316 Record record = generateRecord(317 new String[] { "versionableField1", "f1value1"},318 new String[] { "versionableField2", "f2value1"},319 new String[] { "versionableField3", "f3value1"});320 repository.create(record);321 Record update1 = generateRecord(322 new String[] { "versionableField1", "f1value2"},323 new String[] { "versionableField2", "f2value2"});324 RecordId recordId = record.getId();325 update1.setId(recordId);326 repository.update(update1);327 328 Record update2 = generateRecord(new String[] { "versionableField1", "f1value3"});329 update2.setId(recordId);330 repository.update(update2);331 332 Record expectedRecord = generateRecord(333 new String[] { "versionableField1", "f1value3"},334 new String[] { "versionableField2", "f2value2"},335 new String[] { "versionableField3", "f3value1"});336 expectedRecord.setId(recordId);337 expectedRecord.setVersion(Long.valueOf(3));338 Record actualRecord = repository.read(recordId);339 assertEquals(expectedRecord, actualRecord);340 341 actualRecord = repository.read(recordId, Long.valueOf(3));342 assertEquals(expectedRecord, actualRecord);343 344 expectedRecord = generateRecord(345 new String[] { "versionableField1", "f1value2"},346 new String[] { "versionableField2", "f2value2"},347 new String[] { "versionableField3", "f3value1"});348 expectedRecord.setId(recordId);349 expectedRecord.setVersion(Long.valueOf(2));350 actualRecord = repository.read(recordId, Long.valueOf(2));351 assertEquals(expectedRecord, actualRecord);352 353 expectedRecord = generateRecord(354 new String[] { "versionableField1", "f1value1"},355 new String[] { "versionableField2", "f2value1"},356 new String[] { "versionableField3", "f3value1"});357 expectedRecord.setId(recordId);358 expectedRecord.setVersion(Long.valueOf(1));359 actualRecord = repository.read(recordId, Long.valueOf(1));360 assertEquals(expectedRecord, actualRecord);361 control.verify();362 }363 364 @Test365 public void testReadNonExistingversion() throws Exception {366 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes();367 368 control.replay();369 Record record = generateRecord(new String[] { "versionableField1", "f1value1"});370 repository.create(record);371 record.setField("versionableField1", "f1value2");372 repository.update(record);373 try {374 repository.read(record.getId(), Long.valueOf(3));375 } catch(RecordNotFoundException expected) {376 assertEquals(record.getId(), expected.getRecord().getId());377 assertEquals(Long.valueOf(3), expected.getRecord().getVersion());378 }379 control.verify();380 412 } 381 413 382 414 @Test 383 415 public void testReadSpecificFields() throws Exception { 384 expect(recordType.getFieldDescriptor("field1")).andReturn(nonVersionableFieldDescriptor).anyTimes(); 385 expect(recordType.getFieldDescriptor("field2")).andReturn(nonVersionableFieldDescriptor).anyTimes(); 386 expect(recordType.getFieldDescriptor("field3")).andReturn(versionableFieldDescriptor).anyTimes(); 387 388 control.replay(); 389 Record record = generateRecord(new String[] { "field1", "value1"}, new String[] { "field2", 390 "value2"}, new String[] { "field3", "value3"}); 391 repository.create(record); 392 Record actualRecord = repository.read(record.getId(), "field1", "field3"); 393 assertEquals(record.getId(), actualRecord.getId()); 394 assertEquals("value1", actualRecord.getField("field1")); 395 try { 396 actualRecord.getField("field2"); 397 fail("An exception should be thrown because the record does not contain the requested field"); 398 } catch (FieldNotFoundException expected) { 399 } 400 assertEquals("value3", actualRecord.getField("field3")); 401 control.verify(); 402 } 403 404 @Test 405 public void testDeleteANonVersionableField() throws Exception { 406 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(nonVersionableFieldDescriptor).anyTimes(); 407 408 control.replay(); 409 Record record = generateRecord(new String[] {"aField", "f1"}); 410 repository.create(record); 416 Record record = createDefaultRecord(idGenerator.newRecordId()); 417 Record readRecord = repository.read(record.getId(), Arrays.asList(new String[]{fieldDescriptor1.getId()}), Arrays.asList(new String[]{fieldDescriptor2.getId()}), Arrays.asList(new String[]{fieldDescriptor3.getId()})); 418 assertEquals(repository.read(record.getId()), readRecord); 419 } 420 421 422 @Test 423 public void testUpdateWithNewRecordTypeVersion() throws Exception { 424 Record record = createDefaultRecord(idGenerator.newRecordId()); 425 Record updateRecord = repository.newRecord(record.getId()); 426 updateRecord.setRecordType(recordType1B.getId(), recordType1B.getVersion()); 427 updateRecord.setNonVersionableField(fieldDescriptor1.getId(), "value2"); 428 updateRecord.setVersionableField(fieldDescriptor2.getId(), 789); 429 updateRecord.setVersionableMutableField(fieldDescriptor3.getId(), false); 430 431 Record updatedRecord = repository.update(updateRecord); 432 assertEquals(recordType1B.getId(),updatedRecord.getRecordTypeId()); 433 assertEquals(recordType1B.getVersion(),updatedRecord.getRecordTypeVersion()); 434 assertEquals(recordType1B.getId(),updatedRecord.getNonVersionableRecordTypeId()); 435 assertEquals(recordType1B.getVersion(),updatedRecord.getNonVersionableRecordTypeVersion()); 436 assertEquals(recordType1B.getId(),updatedRecord.getVersionableRecordTypeId()); 437 assertEquals(recordType1B.getVersion(),updatedRecord.getVersionableRecordTypeVersion()); 438 assertEquals(recordType1B.getId(),updatedRecord.getVersionableMutableRecordTypeId()); 439 assertEquals(recordType1B.getVersion(),updatedRecord.getVersionableMutableRecordTypeVersion()); 440 441 Record recordV1 = repository.read(record.getId(), Long.valueOf(1)); 442 assertEquals(recordType1B.getId(),recordV1.getRecordTypeId()); 443 assertEquals(recordType1B.getVersion(),recordV1.getRecordTypeVersion()); 444 assertEquals(recordType1B.getId(),recordV1.getNonVersionableRecordTypeId()); 445 assertEquals(recordType1B.getVersion(),recordV1.getNonVersionableRecordTypeVersion()); 446 assertEquals(recordType1.getId(),recordV1.getVersionableRecordTypeId()); 447 assertEquals(recordType1.getVersion(),recordV1.getVersionableRecordTypeVersion()); 448 assertEquals(recordType1.getId(),recordV1.getVersionableMutableRecordTypeId()); 449 assertEquals(recordType1.getVersion(),recordV1.getVersionableMutableRecordTypeVersion()); 450 } 451 452 @Test 453 public void testUpdateWithNewRecordTypeVersionOnlyOneFieldUpdated() throws Exception { 454 Record record = createDefaultRecord(idGenerator.newRecordId()); 455 Record updateRecord = repository.newRecord(record.getId()); 456 updateRecord.setRecordType(recordType1B.getId(), recordType1B.getVersion()); 457 updateRecord.setVersionableField(fieldDescriptor2.getId(), 789); 458 459 Record updatedRecord = repository.update(updateRecord); 460 assertEquals(recordType1B.getId(),updatedRecord.getRecordTypeId()); 461 assertEquals(recordType1B.getVersion(),updatedRecord.getRecordTypeVersion()); 462 assertEquals(recordType1B.getId(),updatedRecord.getVersionableRecordTypeId()); 463 assertEquals(recordType1B.getVersion(),updatedRecord.getVersionableRecordTypeVersion()); 464 465 Record readRecord = repository.read(record.getId()); 466 assertEquals(recordType1B.getId(),updatedRecord.getRecordTypeId()); 467 assertEquals(recordType1B.getVersion(),updatedRecord.getRecordTypeVersion()); 468 assertEquals(recordType1.getId(),readRecord.getNonVersionableRecordTypeId()); 469 assertEquals(recordType1.getVersion(),readRecord.getNonVersionableRecordTypeVersion()); 470 assertEquals(recordType1B.getId(),updatedRecord.getVersionableRecordTypeId()); 471 assertEquals(recordType1B.getVersion(),updatedRecord.getVersionableRecordTypeVersion()); 472 assertEquals(recordType1.getId(),readRecord.getVersionableMutableRecordTypeId()); 473 assertEquals(recordType1.getVersion(),readRecord.getVersionableMutableRecordTypeVersion()); 474 } 475 476 @Test 477 public void testUpdateWithNewRecordType() throws Exception { 478 Record record = createDefaultRecord(idGenerator.newRecordId()); 479 Record updateRecord = repository.newRecord(record.getId()); 480 updateRecord.setRecordType(recordType2.getId(), recordType2.getVersion()); 481 updateRecord.setNonVersionableField(fieldDescriptor2.getId(), 789); 482 updateRecord.setVersionableField(fieldDescriptor3.getId(), false); 483 updateRecord.setVersionableMutableField(fieldDescriptor1.getId(), "value2"); 484 485 Record updatedRecord = repository.update(updateRecord); 486 assertEquals(recordType2.getId(),updatedRecord.getRecordTypeId()); 487 assertEquals(recordType2.getVersion(),updatedRecord.getRecordTypeVersion()); 488 assertEquals(recordType2.getId(),updatedRecord.getNonVersionableRecordTypeId()); 489 assertEquals(recordType2.getVersion(),updatedRecord.getNonVersionableRecordTypeVersion()); 490 assertEquals(recordType2.getId(),updatedRecord.getVersionableRecordTypeId()); 491 assertEquals(recordType2.getVersion(),updatedRecord.getVersionableRecordTypeVersion()); 492 assertEquals(recordType2.getId(),updatedRecord.getVersionableMutableRecordTypeId()); 493 assertEquals(recordType2.getVersion(),updatedRecord.getVersionableMutableRecordTypeVersion()); 494 495 assertEquals(1, updatedRecord.getNonVersionableFields().size()); 496 assertEquals(1, updatedRecord.getVersionableFields().size()); 497 assertEquals(1, updatedRecord.getVersionableMutableFields().size()); 498 499 Record readRecord = repository.read(record.getId()); 500 // Nothing got deleted 501 assertEquals(2, readRecord.getNonVersionableFields().size()); 502 assertEquals(2, readRecord.getVersionableFields().size()); 503 assertEquals(2, readRecord.getVersionableMutableFields().size()); 504 assertEquals("value1", readRecord.getNonVersionableField(fieldDescriptor1.getId())); 505 assertEquals(789, readRecord.getNonVersionableField(fieldDescriptor2.getId())); 506 assertEquals(123, readRecord.getVersionableField(fieldDescriptor2.getId())); 507 assertFalse((Boolean)readRecord.getVersionableField(fieldDescriptor3.getId())); 508 assertTrue((Boolean)readRecord.getVersionableMutableField(fieldDescriptor3.getId())); 509 assertEquals("value2", readRecord.getVersionableMutableField(fieldDescriptor1.getId())); 510 511 } 512 513 @Test 514 public void testDeleteField() throws Exception { 515 Record record = createDefaultRecord(idGenerator.newRecordId()); 411 516 Record deleteRecord = repository.newRecord(record.getId()); 412 deleteRecord.setRecordType("dummyRecordType", 1); 413 deleteRecord.deleteField("aField"); 517 deleteRecord.setRecordType(record.getRecordTypeId(), null); 518 deleteRecord.addNonVersionableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor1.getId()})); 519 deleteRecord.addVersionableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor2.getId()})); 520 deleteRecord.addVersionableMutableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor3.getId()})); 521 414 522 repository.update(deleteRecord); 415 Record actualRecord = repository.read(record.getId()); 416 try { 417 actualRecord.getField("aField"); 418 fail("Getting a deleted field from a record should throw a FieldNotFoundException"); 419 } catch(FieldNotFoundException expected) { 420 } 421 control.verify(); 422 } 423 424 @Test 425 public void testDeleteAVersionableField() throws Exception { 426 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes(); 427 428 control.replay(); 429 Record record = generateRecord(new String[] {"aField", "f1"}); 430 repository.create(record); 523 Record readRecord = repository.read(record.getId()); 524 assertTrue(readRecord.getNonVersionableFields().isEmpty()); 525 assertTrue(readRecord.getVersionableFields().isEmpty()); 526 assertTrue(readRecord.getVersionableMutableFields().isEmpty()); 527 } 528 529 @Test 530 public void testDeleteFieldsNoLongerInRecordType() throws Exception { 531 Record record = createDefaultRecord(idGenerator.newRecordId()); 532 Record updateRecord = repository.newRecord(record.getId()); 533 updateRecord.setRecordType(recordType2.getId(), recordType2.getVersion()); 534 updateRecord.setNonVersionableField(fieldDescriptor2.getId(), 789); 535 updateRecord.setVersionableField(fieldDescriptor3.getId(), false); 536 updateRecord.setVersionableMutableField(fieldDescriptor1.getId(), "value2"); 537 538 repository.update(updateRecord); 539 431 540 Record deleteRecord = repository.newRecord(record.getId()); 432 deleteRecord.setRecordType( "dummyRecordType", 1);433 deleteRecord. deleteField("aField");541 deleteRecord.setRecordType(recordType2.getId(), recordType2.getVersion()); 542 deleteRecord.addNonVersionableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor1.getId()})); 434 543 repository.update(deleteRecord); 435 Record actualRecord = repository.read(record.getId()); 436 try { 437 actualRecord.getField("aField"); 438 fail("Getting a deleted field from a record should throw a FieldNotFoundException"); 439 } catch(FieldNotFoundException expected) { 440 } 441 442 //TODO should we throw already at the moment of the read operation? i.e. validate that the requested fields are not null 443 actualRecord = repository.read(record.getId(), "aField"); 444 try { 445 actualRecord.getField("aField"); 446 fail("Getting a deleted field from a record should throw a FieldNotFoundException"); 447 } catch(FieldNotFoundException expected) { 448 } 449 control.verify(); 450 } 451 452 @Test 453 public void testDeleteAVersionableFieldWithOlderVersions() throws Exception { 454 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes(); 455 456 control.replay(); 457 Record record = generateRecord(new String[] {"aField", "f1"}); 458 repository.create(record); 459 record.setField("aField", "f2"); 460 repository.update(record); 461 544 545 Record readRecord = repository.read(record.getId()); 546 assertEquals(Long.valueOf(2), readRecord.getVersion()); 547 assertEquals(1, readRecord.getNonVersionableFields().size()); 548 try { 549 readRecord.getNonVersionableField(fieldDescriptor1.getId()); 550 fail(); 551 } catch (FieldNotFoundException expected) { 552 } 553 assertEquals("value2", readRecord.getVersionableMutableField(fieldDescriptor1.getId())); 554 assertEquals(789, readRecord.getNonVersionableField(fieldDescriptor2.getId())); 555 556 deleteRecord.addVersionableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor2.getId()})); 557 deleteRecord.addVersionableMutableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor3.getId()})); 558 repository.update(deleteRecord); 559 560 readRecord = repository.read(record.getId()); 561 assertEquals(Long.valueOf(3), readRecord.getVersion()); 562 assertEquals(1, readRecord.getNonVersionableFields().size()); 563 assertEquals(1, readRecord.getVersionableFields().size()); 564 assertEquals(1, readRecord.getVersionableMutableFields().size()); 565 assertEquals(789, readRecord.getNonVersionableField(fieldDescriptor2.getId())); 566 assertEquals(false, readRecord.getVersionableField(fieldDescriptor3.getId())); 567 assertEquals("value2", readRecord.getVersionableMutableField(fieldDescriptor1.getId())); 568 } 569 570 @Test 571 public void testUpdateAfterDelete() throws Exception { 572 Record record = createDefaultRecord(idGenerator.newRecordId()); 462 573 Record deleteRecord = repository.newRecord(record.getId()); 463 deleteRecord.setRecordType( "dummyRecordType", 1);464 deleteRecord. deleteField("aField");574 deleteRecord.setRecordType(record.getRecordTypeId(), record.getRecordTypeVersion()); 575 deleteRecord.addVersionableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor2.getId()})); 465 576 repository.update(deleteRecord); 466 467 Record actualRecord = repository.read(record.getId()); 468 try { 469 actualRecord.getField("aField"); 470 fail("Getting a deleted field from a record should throw a FieldNotFoundException"); 471 } catch(FieldNotFoundException expected) { 472 } 473 control.verify(); 474 } 475 476 @Test 477 public void testCreateVariantRecord() throws Exception { 478 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes(); 479 480 control.replay(); 481 Record record = generateRecord(new String[] {"aField", "f1"}); 482 repository.create(record); 483 484 Map<String, String> variantProperties = new HashMap<String, String>(); 485 variantProperties.put("dimension1", "dimensionValue1"); 486 Record variantRecord = generateRecord(new String[] {"aVariantField", "vf1"}); 487 RecordId variantRecordId = idGenerator.newRecordId(record.getId(), variantProperties); 488 variantRecord.setId(variantRecordId); 489 repository.create(variantRecord); 490 491 Record actualVariantRecord = repository.read(variantRecordId); 492 493 assertEquals(variantRecord, actualVariantRecord); 494 495 control.verify(); 496 } 497 498 @Test 499 public void testCreateVariantRecordWithNonExistingRecord() throws Exception { 500 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes(); 501 502 control.replay(); 503 Map<String, String> variantProperties = new HashMap<String, String>(); 504 variantProperties.put("dimension1", "dimensionValue1"); 505 Record variantRecord = generateRecord(new String[] {"aVariantField", "vf1"}); 506 variantRecord.setId(idGenerator.newRecordId(idGenerator.newRecordId("nonExistingMasterRecordId"), variantProperties )); 507 try { 508 repository.create(variantRecord); 577 578 Record updateRecord = repository.newRecord(record.getId()); 579 updateRecord.setRecordType(record.getRecordTypeId(), record.getRecordTypeVersion()); 580 updateRecord.setVersionableField(fieldDescriptor2.getId(), 789); 581 repository.update(updateRecord); 582 583 Record readRecord = repository.read(record.getId()); 584 assertEquals(Long.valueOf(3), readRecord.getVersion()); 585 assertEquals(789, readRecord.getVersionableField(fieldDescriptor2.getId())); 586 587 readRecord = repository.read(record.getId(), Long.valueOf(2)); 588 try { 589 readRecord.getVersionableField(fieldDescriptor2.getId()); 590 fail(); 591 } catch (FieldNotFoundException expected) { 592 } 593 594 readRecord = repository.read(record.getId(), Long.valueOf(1)); 595 assertEquals(123, readRecord.getVersionableField(fieldDescriptor2.getId())); 596 } 597 598 @Test 599 public void testDeleteNonVersionableFieldAndUpdateVersionableField() throws Exception { 600 Record record = createDefaultRecord(idGenerator.newRecordId()); 601 Record updateRecord = repository.newRecord(record.getId()); 602 updateRecord.setRecordType(record.getRecordTypeId(), record.getRecordTypeVersion()); 603 updateRecord.setVersionableField(fieldDescriptor2.getId(), 999); 604 updateRecord.addNonVersionableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor1.getId()})); 605 repository.update(updateRecord); 606 607 Record readRecord = repository.read(record.getId()); 608 assertEquals(999, readRecord.getVersionableField(fieldDescriptor2.getId())); 609 try { 610 readRecord.getNonVersionableField(fieldDescriptor1.getId()); 611 fail(); 612 } catch (FieldNotFoundException expected) { 613 } 614 615 readRecord = repository.read(record.getId(), Long.valueOf(1)); 616 try { 617 readRecord.getNonVersionableField(fieldDescriptor1.getId()); 618 fail(); 619 } catch (FieldNotFoundException expected) { 620 } 621 622 } 623 624 @Test 625 public void testUpdateAndDeleteSameField() throws Exception { 626 Record record = createDefaultRecord(idGenerator.newRecordId()); 627 Record updateRecord = repository.newRecord(record.getId()); 628 updateRecord.setRecordType(record.getRecordTypeId(), record.getRecordTypeVersion()); 629 updateRecord.setVersionableField(fieldDescriptor2.getId(), 789); 630 updateRecord.addVersionableFieldsToDelete(Arrays.asList(new String[]{fieldDescriptor2.getId()})); 631 repository.update(updateRecord); 632 633 try { 634 repository.read(record.getId()).getVersionableField(fieldDescriptor2.getId()); 635 fail(); 636 } catch (FieldNotFoundException expected) { 637 } 638 } 639 640 public void testDeleteRecord() throws Exception { 641 Record record = createDefaultRecord(idGenerator.newRecordId()); 642 repository.delete(record.getId()); 643 try { 644 repository.read(record.getId()); 509 645 fail(); 510 646 } catch (RecordNotFoundException expected) { 511 assertEquals(variantRecord, expected.getRecord()); 512 } 513 control.verify(); 514 } 515 516 @Test 517 public void testReadNonExistingVariantRecord() throws Exception { 518 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes(); 519 520 control.replay(); 521 Record record = generateRecord(new String[] {"aField", "f1"}); 522 repository.create(record); 523 524 Record variantRecord = generateRecord(new String[] {"aVariantField", "vf1"}); 525 Map<String, String> variantProperties = new HashMap<String, String>(); 526 variantProperties.put("dimension1", "dimensionValue1"); 527 RecordId variantRecordId = idGenerator.newRecordId(record.getId(), variantProperties ); 528 variantRecord.setId(variantRecordId); 529 530 try { 531 repository.read(variantRecordId); 532 fail("Reading a non-existing variant should throw an exception"); 533 } catch (RecordNotFoundException expected) { 534 assertEquals(variantRecordId, expected.getRecord().getId()); 535 } 536 repository.create(variantRecord); 537 538 Map<String, String> variantProperties2 = new HashMap<String, String>(); 539 variantProperties2.put("dimension2", "dimensionValue1"); 540 RecordId variantRecordId2 = idGenerator.newRecordId(record.getId(), variantProperties2); 541 try { 542 repository.read(variantRecordId2); 543 fail("Reading a non-existing variant should throw an exception"); 544 } catch (RecordNotFoundException expected) { 545 assertEquals(variantRecordId2, expected.getRecord().getId()); 546 } 547 control.verify(); 548 } 549 550 @Test 551 public void testReadNonExistingVariantRecordVersion() throws Exception { 552 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes(); 553 554 control.replay(); 555 Record record = generateRecord(new String[] {"aField", "f1"}); 556 repository.create(record); 557 558 Record variantRecord = generateRecord(new String[] {"aVariantField", "vf1"}); 559 Map<String, String> variantProperties = new HashMap<String, String>(); 560 variantProperties.put("dimension1", "dimensionValue1"); 561 RecordId variantRecordId = idGenerator.newRecordId(record.getId(), variantProperties ); 562 variantRecord.setId(variantRecordId); 563 repository.create(variantRecord); 564 565 try { 566 repository.read(variantRecordId, Long.valueOf(2)); 567 fail("Reading a non-existing variant should throw an exception"); 568 } catch (RecordNotFoundException expected) { 569 assertEquals(variantRecordId, expected.getRecord().getId()); 570 assertEquals(Long.valueOf(2), expected.getRecord().getVersion()); 571 } 572 573 control.verify(); 574 } 575 576 @Test 577 public void testVariantRecordVersions() throws Exception { 578 expect(recordType.getFieldDescriptor(isA(String.class))).andReturn(versionableFieldDescriptor).anyTimes(); 579 580 control.replay(); 581 Record record = generateRecord(new String[] {"field1", "f1"}); 582 repository.create(record); 583 RecordId recordId = record.getId(); 584 Map<String, String> variantProperties = new HashMap<String, String>(); 585 variantProperties.put("dimension1", "dimensionValue1"); 586 RecordId variantRecordId = idGenerator.newRecordId(recordId, variantProperties); 587 588 Record variantRecord = generateRecord(new String[] {"field1", "vf1"}); 589 variantRecord.setId(variantRecordId); 590 repository.create(variantRecord); 591 592 variantRecord = generateRecord(new String[] {"field1", "vf1B"}, new String[] {"field2", "vf2"}); 593 variantRecord.setId(variantRecordId); 594 repository.update(variantRecord); 595 596 variantRecord = generateRecord(new String[] {"field2", "vf2B"}, new String[] {"field3", "vf3"}); 597 variantRecord.setId(variantRecordId); 598 repository.update(variantRecord); 599 600 variantRecord = generateRecord(); 601 variantRecord.setId(variantRecordId); 602 variantRecord.deleteField("field1"); 603 repository.update(variantRecord); 604 605 variantRecord = generateRecord(new String[] {"field1", "vf1B"}); 606 variantRecord.setId(variantRecordId); 607 repository.update(variantRecord); 608 609 Record actualMasterRecord = repository.read(recordId); 610 assertEquals("f1", actualMasterRecord.getField("field1")); 611 Record actualVariantRecord = repository.read(variantRecordId, Long.valueOf(1)); 612 assertEquals("vf1", actualVariantRecord.getField("field1")); 613 614 actualVariantRecord = repository.read(variantRecordId, Long.valueOf(2)); 615 assertEquals("vf1B", actualVariantRecord.getField("field1")); 616 assertEquals("vf2", actualVariantRecord.getField("field2")); 617 618 actualVariantRecord = repository.read(variantRecordId, Long.valueOf(3)); 619 assertEquals("vf1B", actualVariantRecord.getField("field1")); 620 assertEquals("vf2B", actualVariantRecord.getField("field2")); 621 assertEquals("vf3", actualVariantRecord.getField("field3")); 622 623 actualVariantRecord = repository.read(variantRecordId, Long.valueOf(4)); 624 try { 625 actualVariantRecord.getField("field1"); 626 fail(); 627 } catch (FieldNotFoundException expected) { 628 } 629 630 actualVariantRecord = repository.read(variantRecordId, Long.valueOf(5)); 631 assertEquals("vf1B", actualVariantRecord.getField("field1")); 632 633 try { 634 actualVariantRecord = repository.read(variantRecordId, Long.valueOf(6)); 635 fail(); 636 } catch(RecordNotFoundException expected) { 637 } 638 639 control.verify(); 640 641 } 642 643 private Record generateRecord(String[]... fieldsAndValues) throws Exception { 644 Record record = repository.newRecord(); 645 646 record.setRecordType(recordType.getId(), recordType.getVersion()); 647 for (String[] fieldInfo : fieldsAndValues) { 648 record.setField(fieldInfo[0], fieldInfo[1]); 649 } 650 return record; 647 } 651 648 } 652 649 } -
projects/lily/trunk/repository/impl/src/test/java/org/lilycms/repository/impl/test/ValueTypeTest.java
r3959 r3977 29 29 import org.junit.Test; 30 30 import org.lilycms.repository.api.FieldDescriptor; 31 import org.lilycms.repository.api.Field NotFoundException;31 import org.lilycms.repository.api.FieldGroup; 32 32 import org.lilycms.repository.api.HierarchyPath; 33 import org.lilycms.repository.api.InvalidRecordException;34 33 import org.lilycms.repository.api.PrimitiveValueType; 35 34 import org.lilycms.repository.api.Record; 36 import org.lilycms.repository.api.RecordExistsException;37 import org.lilycms.repository.api.RecordNotFoundException;38 35 import org.lilycms.repository.api.RecordType; 39 import org.lilycms.repository.api.RepositoryException;40 import org.lilycms.repository.impl.FieldDescriptorImpl;41 36 import org.lilycms.repository.impl.HBaseRepository; 42 37 import org.lilycms.repository.impl.HBaseTypeManager; 43 38 import org.lilycms.repository.impl.IdGeneratorImpl; 44 import org.lilycms.repository.impl.RecordImpl;45 import org.lilycms.repository.impl.RecordTypeImpl;46 39 import org.lilycms.testfw.TestHelper; 47 40 … … 69 62 public void setUp() throws Exception { 70 63 idGenerator = new IdGeneratorImpl(); 71 typeManager = new HBaseTypeManager(idGenerator, RecordTypeImpl.class, FieldDescriptorImpl.class, TEST_UTIL 72 .getConfiguration()); 73 repository = new HBaseRepository(typeManager, idGenerator, RecordImpl.class, TEST_UTIL 74 .getConfiguration()); 64 typeManager = new HBaseTypeManager(idGenerator, TEST_UTIL.getConfiguration()); 65 repository = new HBaseRepository(typeManager, idGenerator, TEST_UTIL.getConfiguration()); 75 66 } 76 67 … … 115 106 } 116 107 117 private void runValueTypeTests(String recordTypeId, String primitiv aValueType, Object value1, Object value2, Object value3) throws Exception {118 testType(recordTypeId, primitiv aValueType, false, false, value1);119 testType(recordTypeId, primitiv aValueType, true, false, Arrays.asList(new Object[] { value1,108 private void runValueTypeTests(String recordTypeId, String primitiveValueType, Object value1, Object value2, Object value3) throws Exception { 109 testType(recordTypeId, primitiveValueType, false, false, value1); 110 testType(recordTypeId, primitiveValueType, true, false, Arrays.asList(new Object[] { value1, 120 111 value2 })); 121 testType(recordTypeId, primitiv aValueType, false, true, new HierarchyPath(new Object[] { value1,112 testType(recordTypeId, primitiveValueType, false, true, new HierarchyPath(new Object[] { value1, 122 113 value2 })); 123 testType(recordTypeId, primitiv aValueType, true, true, Arrays.asList(new HierarchyPath[] {114 testType(recordTypeId, primitiveValueType, true, true, Arrays.asList(new HierarchyPath[] { 124 115 new HierarchyPath(new Object[] { value1, value2 }), 125 116 new HierarchyPath(new Object[] { value1, value3 }) })); 126 117 } 127 118 128 private void testType(String recordId, String valueTypeString, boolean multivalue, boolean hierarchical, 129 Object fieldValue) throws RepositoryException, RecordExistsException, RecordNotFoundException, 130 InvalidRecordException, FieldNotFoundException { 131 RecordType recordType = typeManager.newRecordType(recordId); 132 FieldDescriptor fieldDescriptor = typeManager.newFieldDescriptor("aFieldId", typeManager.getValueType( 133 valueTypeString, multivalue, hierarchical), true, true); 134 recordType.addFieldDescriptor(fieldDescriptor); 119 private void testType(String recordTypeId, String valueTypeString, boolean multivalue, boolean hierarchical, 120 Object fieldValue) throws Exception { 121 String fieldDescriptorId = valueTypeString+"FieldId"+multivalue+hierarchical; 122 FieldDescriptor fieldDescriptor = typeManager.createFieldDescriptor(typeManager.newFieldDescriptor(fieldDescriptorId, typeManager.getValueType( 123 valueTypeString, multivalue, hierarchical), "aGlobalName")); 124 String fieldGroupId = valueTypeString+"FieldGroupId"+multivalue+hierarchical; 125 FieldGroup fieldGroup = typeManager.newFieldGroup(fieldGroupId); 126 fieldGroup.setFieldGroupEntry(typeManager.newFieldGroupEntry(fieldDescriptor.getId(), fieldDescriptor.getVersion(), true, "anAlias")); 127 fieldGroup = typeManager.createFieldGroup(fieldGroup); 128 RecordType recordType = typeManager.newRecordType(recordTypeId+"RecordTypeId"+multivalue+hierarchical); 129 recordType.setNonVersionableFieldGroupId(fieldGroup.getId()); 130 recordType.setNonVersionableFieldGroupVersion(fieldGroup.getVersion()); 135 131 typeManager.createRecordType(recordType); 136 132 137 Record record = repository.newRecord( );133 Record record = repository.newRecord(idGenerator.newRecordId()); 138 134 record.setRecordType(recordType.getId(), recordType.getVersion()); 139 record.set Field("aFieldId", fieldValue);135 record.setNonVersionableField(fieldDescriptorId, fieldValue); 140 136 repository.create(record); 141 137 142 138 Record actualRecord = repository.read(record.getId()); 143 assertEquals(fieldValue, actualRecord.get Field("aFieldId"));139 assertEquals(fieldValue, actualRecord.getNonVersionableField(fieldDescriptorId)); 144 140 } 145 141
Note: See TracChangeset
for help on using the changeset viewer.