|
|||||||||||||||||||
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 | } |
|