|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| InlineMetaService.java | 37.5% | 69.6% | 100% | 66.7% |
|
||||||||||||||
| 1 | /* | |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
| 3 | * contributor license agreements. See the NOTICE file distributed with | |
| 4 | * this work for additional information regarding copyright ownership. | |
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 6 | * (the "License"); you may not use this file except in compliance with | |
| 7 | * the License. You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | * | |
| 17 | * $Id: InlineMetaService.java 571950 2007-09-02 10:53:17Z vgritsenko $ | |
| 18 | */ | |
| 19 | ||
| 20 | package org.apache.xindice.core.meta.inline; | |
| 21 | ||
| 22 | import org.apache.commons.logging.Log; | |
| 23 | import org.apache.commons.logging.LogFactory; | |
| 24 | import org.apache.xindice.core.FaultCodes; | |
| 25 | import org.apache.xindice.core.data.Value; | |
| 26 | ||
| 27 | /** | |
| 28 | * If the documents in a collection have headers, the Collection | |
| 29 | * object holds an instance of this class. All services the collection | |
| 30 | * needs for working with inline metadata are provided by this class. | |
| 31 | * | |
| 32 | * @version $Revision: 571950 $, $Date: 2007-09-02 03:53:17 -0700 (Sun, 02 Sep 2007) $ | |
| 33 | */ | |
| 34 | public class InlineMetaService { | |
| 35 | ||
| 36 | private static final Log log = LogFactory.getLog(InlineMetaService.class); | |
| 37 | ||
| 38 | /** | |
| 39 | * The known readers. All readers for header versions up to | |
| 40 | * and including the current version must be present in this array. | |
| 41 | */ | |
| 42 | public static final InlineMetaReader[] readerByVersion = {new NullReader(), new ResourceTypeReader()}; | |
| 43 | ||
| 44 | /** | |
| 45 | * The writer corresponding to the current header version. | |
| 46 | */ | |
| 47 | public static final InlineMetaWriter currentWriter = new ResourceTypeWriter(); | |
| 48 | ||
| 49 | /** | |
| 50 | * The InlineMetaMap class associated with the current header | |
| 51 | * version. When the Collection fills in an InlineMetaMap object | |
| 52 | * prior to a store, it is working with this class. | |
| 53 | */ | |
| 54 | public static final Class currentMapClass = ResourceTypeReader.ResourceTypeMap.class; | |
| 55 | ||
| 56 | /** | |
| 57 | * Get an <code>InlineMetaMap</code> instance corresponding to the | |
| 58 | * current header version. Used by <code>Collection</code> to inform | |
| 59 | * the InlineMeta code of the metadata values for the entry being stored. | |
| 60 | * | |
| 61 | * @return InlineMetaMap instance | |
| 62 | */ | |
| 63 | 1983 | public InlineMetaMap getEmptyMap() { |
| 64 | 1983 | try { |
| 65 | 1983 | return (InlineMetaMap) currentMapClass.newInstance(); |
| 66 | } catch (Exception e) { | |
| 67 | 0 | String msg = "unable to create instance of current inline metadata map class '" + currentMapClass.getName() + "'"; |
| 68 | /* | |
| 69 | * This can only happen as a result of a programming error, | |
| 70 | * so log it and throw a runtime. Shouldn't happen in production. | |
| 71 | */ | |
| 72 | 0 | if (log.isFatalEnabled()) { |
| 73 | 0 | log.fatal(msg, e); |
| 74 | } | |
| 75 | 0 | throw new IllegalStateException(msg); |
| 76 | } | |
| 77 | } | |
| 78 | ||
| 79 | /** | |
| 80 | * Create a Value object containing the appropriate header and | |
| 81 | * data. This utility method takes the metadata and the data | |
| 82 | * for the entry to be stored in the database and creates a | |
| 83 | * <code>Value</code> object containing both, ready to store. | |
| 84 | * | |
| 85 | * @param map containing metadata | |
| 86 | * @param data containing entry to be stored in database | |
| 87 | * @param offset in the data to the beginning of the entry | |
| 88 | * @param length of the entry | |
| 89 | * @return Value object containing the header + entry, ready to store | |
| 90 | * @throws InlineMetaException if the metadata is incomplete | |
| 91 | */ | |
| 92 | 1983 | public Value createValue(InlineMetaMap map, byte[] data, int offset, int length) throws InlineMetaException { |
| 93 | ||
| 94 | 1983 | byte[] metadata = currentWriter.getMetadata(map); |
| 95 | ||
| 96 | 1983 | return InlineHeaderBuilder.createValue(currentWriter.getVersion(), metadata, data, offset, length); |
| 97 | } | |
| 98 | ||
| 99 | /** | |
| 100 | * Returns true if a reader is available for the specified | |
| 101 | * version. | |
| 102 | * | |
| 103 | * @param version of the header | |
| 104 | * @return true if a reader is available for the given version | |
| 105 | */ | |
| 106 | 34452 | public boolean haveReaderForVersion(int version) { |
| 107 | 34452 | return version < readerByVersion.length; |
| 108 | } | |
| 109 | ||
| 110 | /** | |
| 111 | * Given a <code>Value</code> object from the database, | |
| 112 | * disassemble it into its component metadata and entry data | |
| 113 | * components. | |
| 114 | * | |
| 115 | * @param rawValue containing raw header + entry data from the backing store | |
| 116 | * @return DatabaseEntry containing metadata in an <code>InlineMetaMap</code> | |
| 117 | * and entry data in a <code>Value</code>. | |
| 118 | * @throws InlineMetaException if missing the reader for the header, or if | |
| 119 | * the header is corrupted. | |
| 120 | */ | |
| 121 | 34452 | public DatabaseEntry readDatabaseEntry(Value rawValue) throws InlineMetaException { |
| 122 | 34452 | if (log.isDebugEnabled()) { |
| 123 | 0 | log.debug("readDatabaseEntry: rawData: length=" + rawValue.getLength() + |
| 124 | " byte 0: " + rawValue.byteAt(0) + " byte 1: " + rawValue.byteAt(1)); | |
| 125 | } | |
| 126 | ||
| 127 | /* | |
| 128 | * Read the header. | |
| 129 | */ | |
| 130 | ||
| 131 | 34452 | int headerLen = rawValue.byteAt(0); |
| 132 | 34452 | int version = rawValue.byteAt(1); |
| 133 | 34452 | if (!haveReaderForVersion(version)) { |
| 134 | 0 | throw new InlineMetaException(FaultCodes.GEN_CRITICAL_ERROR, |
| 135 | "No inline metadata reader available for version " + version); | |
| 136 | } | |
| 137 | ||
| 138 | 34452 | final InlineMetaReader reader = readerByVersion[version]; |
| 139 | 34452 | InlineMetaMap map = reader.read(rawValue.valueAt(2, headerLen - 2)); |
| 140 | 34452 | if (log.isDebugEnabled()) { |
| 141 | 0 | log.debug("readDatabaseEntry: map: type=" + map.get("type")); |
| 142 | } | |
| 143 | ||
| 144 | /* | |
| 145 | * Exract the data into a Value object. | |
| 146 | */ | |
| 147 | ||
| 148 | 34452 | Value value = rawValue.valueAt(headerLen, rawValue.getLength() - headerLen); |
| 149 | // FIXME: May be Record should be used instead? new Record(null, value, map); | |
| 150 | 34452 | return new DatabaseEntry(map, value); |
| 151 | } | |
| 152 | ||
| 153 | /** | |
| 154 | * Utility class for returning an InlineMetaMap and Value | |
| 155 | * from <code>readDatabaseEntry(Value)</code>. | |
| 156 | */ | |
| 157 | public static class DatabaseEntry { | |
| 158 | public final InlineMetaMap map; | |
| 159 | public final Value value; | |
| 160 | ||
| 161 | 34452 | public DatabaseEntry(InlineMetaMap map, Value value) { |
| 162 | 34452 | this.map = map; |
| 163 | 34452 | this.value = value; |
| 164 | } | |
| 165 | } | |
| 166 | } |
|
||||||||||