001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.solr.schema;
017:
018: import org.apache.lucene.document.Field;
019: import org.apache.lucene.document.Fieldable;
020: import org.apache.lucene.search.SortField;
021: import org.apache.solr.request.XMLWriter;
022: import org.apache.solr.request.TextResponseWriter;
023:
024: import java.util.Map;
025: import java.io.IOException;
026:
027: /**
028: * Encapsulates all information about a Field in a Solr Schema
029: *
030: * @author yonik
031: * @version $Id: SchemaField.java 533571 2007-04-29 23:03:03Z ryan $
032: */
033: public final class SchemaField extends FieldProperties {
034: final String name;
035: final FieldType type;
036: final int properties;
037: final String defaultValue;
038: boolean required = false; // this can't be final since it may be changed dynamically
039:
040: /** Create a new SchemaField with the given name and type,
041: * using all the default properties from the type.
042: */
043: public SchemaField(String name, FieldType type) {
044: this (name, type, type.properties, null);
045: }
046:
047: /** Create a new SchemaField from an existing one by using all
048: * of the properties of the prototype except the field name.
049: */
050: public SchemaField(SchemaField prototype, String name) {
051: this (name, prototype.type, prototype.properties,
052: prototype.defaultValue);
053: }
054:
055: /** Create a new SchemaField with the given name and type,
056: * and with the specified properties. Properties are *not*
057: * inherited from the type in this case, so users of this
058: * constructor should derive the properties from type.getProperties()
059: * using all the default properties from the type.
060: */
061: public SchemaField(String name, FieldType type, int properties,
062: String defaultValue) {
063: this .name = name;
064: this .type = type;
065: this .properties = properties;
066: this .defaultValue = defaultValue;
067:
068: // initalize with the required property flag
069: required = (properties & REQUIRED) != 0;
070: }
071:
072: public String getName() {
073: return name;
074: }
075:
076: public FieldType getType() {
077: return type;
078: }
079:
080: int getProperties() {
081: return properties;
082: }
083:
084: public boolean indexed() {
085: return (properties & INDEXED) != 0;
086: }
087:
088: public boolean stored() {
089: return (properties & STORED) != 0;
090: }
091:
092: public boolean storeTermVector() {
093: return (properties & STORE_TERMVECTORS) != 0;
094: }
095:
096: public boolean storeTermPositions() {
097: return (properties & STORE_TERMPOSITIONS) != 0;
098: }
099:
100: public boolean storeTermOffsets() {
101: return (properties & STORE_TERMOFFSETS) != 0;
102: }
103:
104: public boolean omitNorms() {
105: return (properties & OMIT_NORMS) != 0;
106: }
107:
108: public boolean multiValued() {
109: return (properties & MULTIVALUED) != 0;
110: }
111:
112: public boolean sortMissingFirst() {
113: return (properties & SORT_MISSING_FIRST) != 0;
114: }
115:
116: public boolean sortMissingLast() {
117: return (properties & SORT_MISSING_LAST) != 0;
118: }
119:
120: public boolean isCompressed() {
121: return (properties & COMPRESSED) != 0;
122: }
123:
124: public boolean isRequired() {
125: return required;
126: }
127:
128: // things that should be determined by field type, not set as options
129: boolean isTokenized() {
130: return (properties & TOKENIZED) != 0;
131: }
132:
133: boolean isBinary() {
134: return (properties & BINARY) != 0;
135: }
136:
137: public Field createField(String val, float boost) {
138: return type.createField(this , val, boost);
139: }
140:
141: @Override
142: public String toString() {
143: return name
144: + "{type="
145: + type.getTypeName()
146: + ((defaultValue == null) ? ""
147: : (",default=" + defaultValue))
148: + ",properties=" + propertiesToString(properties)
149: + (required ? ", required=true" : "") + "}";
150: }
151:
152: public void write(XMLWriter writer, String name, Fieldable val)
153: throws IOException {
154: // name is passed in because it may be null if name should not be used.
155: type.write(writer, name, val);
156: }
157:
158: public void write(TextResponseWriter writer, String name,
159: Fieldable val) throws IOException {
160: // name is passed in because it may be null if name should not be used.
161: type.write(writer, name, val);
162: }
163:
164: public SortField getSortField(boolean top) {
165: return type.getSortField(this , top);
166: }
167:
168: static SchemaField create(String name, FieldType ft,
169: Map<String, String> props) {
170: int trueProps = parseProperties(props, true);
171: int falseProps = parseProperties(props, false);
172:
173: int p = ft.properties;
174:
175: //
176: // If any properties were explicitly turned off, then turn off other properties
177: // that depend on that.
178: //
179: if (on(falseProps, STORED)) {
180: int pp = STORED | BINARY | COMPRESSED;
181: if (on(pp, trueProps)) {
182: throw new RuntimeException("SchemaField: " + name
183: + " conflicting stored field options:" + props);
184: }
185: p &= ~pp;
186: }
187:
188: if (on(falseProps, INDEXED)) {
189: int pp = (INDEXED | OMIT_NORMS | STORE_TERMVECTORS
190: | STORE_TERMPOSITIONS | STORE_TERMOFFSETS
191: | SORT_MISSING_FIRST | SORT_MISSING_LAST);
192: if (on(pp, trueProps)) {
193: throw new RuntimeException("SchemaField: " + name
194: + " conflicting indexed field options:" + props);
195: }
196: p &= ~pp;
197:
198: }
199:
200: if (on(falseProps, STORE_TERMVECTORS)) {
201: int pp = (STORE_TERMVECTORS | STORE_TERMPOSITIONS | STORE_TERMOFFSETS);
202: if (on(pp, trueProps)) {
203: throw new RuntimeException("SchemaField: " + name
204: + " conflicting termvector field options:"
205: + props);
206: }
207: p &= ~pp;
208: }
209:
210: // override sort flags
211: if (on(trueProps, SORT_MISSING_FIRST)) {
212: p &= ~SORT_MISSING_LAST;
213: }
214:
215: if (on(trueProps, SORT_MISSING_LAST)) {
216: p &= ~SORT_MISSING_FIRST;
217: }
218:
219: p &= ~falseProps;
220: p |= trueProps;
221:
222: String defaultValue = null;
223: if (props.containsKey("default")) {
224: defaultValue = (String) props.get("default");
225: }
226: return new SchemaField(name, ft, p, defaultValue);
227: }
228:
229: public String getDefaultValue() {
230: return defaultValue;
231: }
232: }
|