/* * Copyright 2011 Outerthought bvba * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.lilyproject.repository.impl; import java.util.List; import java.util.Map; import org.lilyproject.bytes.impl.DataInputImpl; import org.lilyproject.repository.api.FieldNotFoundException; import org.lilyproject.repository.api.IdRecord; import org.lilyproject.repository.api.IdentityRecordStack; import org.lilyproject.repository.api.Metadata; import org.lilyproject.repository.api.QName; import org.lilyproject.repository.api.Record; import org.lilyproject.repository.api.RecordException; import org.lilyproject.repository.api.RecordId; import org.lilyproject.repository.api.RepositoryException; import org.lilyproject.repository.api.ResponseStatus; import org.lilyproject.repository.api.SchemaId; import org.lilyproject.repository.api.Scope; import org.lilyproject.repository.impl.valuetype.RecordValueType; public class RecordRvtImpl implements IdRecord, Cloneable { private IdRecord delegate; private byte[] bytes; private RecordValueType recordValueType; public RecordRvtImpl(byte[] bytes, RecordValueType recordValueType) { this.bytes = bytes; this.recordValueType = recordValueType; } /** * * @param clearBytes should be false for read operations, true for write operations. * The idea is that as long as the record is not modified, the * existing bytes can be reused. */ private synchronized void decode(boolean clearBytes) { if (delegate == null) { try { delegate = (IdRecord)recordValueType.read(new DataInputImpl(bytes)); } catch (RepositoryException e) { throw new RuntimeException("Failed to decode record "); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } if (clearBytes) { bytes = null; } } public byte[] getBytes() { return bytes; } @Override public void addFieldsToDelete(List<QName> fieldNames) { decode(true); delegate.addFieldsToDelete(fieldNames); } @Override public void delete(QName fieldName, boolean addToFieldsToDelete) { decode(true); delegate.delete(fieldName, addToFieldsToDelete); } @Override public void delete(String fieldName, boolean addToFieldsToDelete) throws RecordException { decode(true); delegate.delete(fieldName, addToFieldsToDelete); } @Override public <T> T getField(QName fieldName) throws FieldNotFoundException { decode(false); return delegate.getField(fieldName); } @Override public <T> T getField(String fieldName) throws FieldNotFoundException, RecordException { decode(false); return delegate.getField(fieldName); } @Override public Map<QName, Object> getFields() { decode(false); return delegate.getFields(); } @Override public List<QName> getFieldsToDelete() { decode(false); return delegate.getFieldsToDelete(); } @Override public RecordId getId() { decode(false); return delegate.getId(); } @Override public QName getRecordTypeName() { decode(false); return delegate.getRecordTypeName(); } @Override public QName getRecordTypeName(Scope scope) { decode(false); return delegate.getRecordTypeName(scope); } @Override public Long getRecordTypeVersion() { decode(false); return delegate.getRecordTypeVersion(); } @Override public Long getRecordTypeVersion(Scope scope) { decode(false); return delegate.getRecordTypeVersion(scope); } @Override public ResponseStatus getResponseStatus() { decode(false); return delegate.getResponseStatus(); } @Override public Long getVersion() { decode(false); return delegate.getVersion(); } @Override public boolean hasField(QName fieldName) { decode(false); return delegate.hasField(fieldName); } @Override public boolean hasField(String fieldName) throws RecordException { decode(false); return delegate.hasField(fieldName); } @Override public void removeFieldsToDelete(List<QName> fieldNames) { decode(true); delegate.removeFieldsToDelete(fieldNames); } @Override public void setDefaultNamespace(String namespace) { decode(true); delegate.setDefaultNamespace(namespace); } @Override public void setField(QName fieldName, Object value) { decode(true); delegate.setField(fieldName, value); } @Override public void setField(String fieldName, Object value) throws RecordException { decode(true); delegate.setField(fieldName, value); } @Override public void setId(RecordId recordId) { decode(true); delegate.setId(recordId); } @Override public void setRecordType(QName name, Long version) { decode(true); delegate.setRecordType(name, version); } @Override public void setRecordType(QName name) { decode(true); delegate.setRecordType(name); } @Override public void setRecordType(Scope scope, QName name, Long version) { decode(true); delegate.setRecordType(scope, name, version); } @Override public void setRecordType(String recordTypeName) throws RecordException { decode(true); delegate.setRecordType(recordTypeName); } @Override public void setRecordType(String recordTypeName, Long version) throws RecordException { decode(true); delegate.setRecordType(recordTypeName, version); } @Override public void setRecordType(Scope scope, String recordTypeName, Long version) throws RecordException { decode(true); delegate.setRecordType(scope, recordTypeName, version); } @Override public void setResponseStatus(ResponseStatus status) { decode(true); delegate.setResponseStatus(status); } @Override public void setVersion(Long version) { decode(true); delegate.setVersion(version); } @Override public IdRecord clone() { return new RecordRvtImpl(bytes, recordValueType); } @Override public IdRecord cloneRecord() throws RecordException { return clone(); } @Override public IdRecord cloneRecord(IdentityRecordStack parentRecords) throws RecordException { return clone(); } @Override public boolean softEquals(Object obj) { decode(false); return delegate.softEquals(obj); } @Override public boolean equals(Object obj) { decode(false); return delegate.equals(obj); } @Override public int hashCode() { decode(false); return delegate.hashCode(); } @Override public Record getRecord() { decode(true); return delegate; } @Override public Map<SchemaId, QName> getFieldIdToNameMapping() { decode(false); return delegate.getFieldIdToNameMapping(); } @Override public SchemaId getRecordTypeId() { decode(false); return delegate.getRecordTypeId(); } @Override public SchemaId getRecordTypeId(Scope scope) { decode(false); return delegate.getRecordTypeId(scope); } @Override public <T> T getField(SchemaId fieldId) throws FieldNotFoundException { decode(false); return delegate.getField(fieldId); } @Override public boolean hasField(SchemaId fieldId) { decode(false); return delegate.hasField(fieldId); } @Override public Map<SchemaId, Object> getFieldsById() { decode(false); return delegate.getFieldsById(); } @Override public Map<String, String> getAttributes() { decode(false); return delegate.getAttributes(); } @Override public boolean hasAttributes() { decode(false); return delegate.hasAttributes(); } @Override public void setAttributes(Map<String, String> attributes) { decode(true); delegate.setAttributes(attributes); } @Override public Metadata getMetadata(QName fieldName) { decode(false); return delegate.getMetadata(fieldName); } @Override public void setMetadata(QName fieldName, Metadata metadata) { decode(true); delegate.setMetadata(fieldName, metadata); } @Override public Map<QName, Metadata> getMetadataMap() { decode(true); return delegate.getMetadataMap(); } }