1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: FieldInfo.java,v 1.1 2008/02/07 17:12:27 mark Exp $
7 */
8
9package com.sleepycat.persist.impl;
10
11import java.io.Serializable;
12import java.lang.reflect.Field;
13import java.lang.reflect.Modifier;
14import java.util.ArrayList;
15import java.util.List;
16import java.util.Map;
17
18import com.sleepycat.persist.raw.RawField;
19
20/**
21 * A field definition used by ComplexFormat and CompositeKeyFormat.
22 *
23 * <p>Note that the equals(), compareTo() and hashCode() methods only use the
24 * name field in this class.  Comparing two FieldInfo objects is only done when
25 * both are declared in the same class, so comparing the field name is
26 * sufficient.</p>
27 *
28 * @author Mark Hayes
29 */
30class FieldInfo implements RawField, Serializable, Comparable<FieldInfo> {
31
32    private static final long serialVersionUID = 2062721100372306296L;
33
34    /**
35     * Returns a list of all non-transient non-static fields that are declared
36     * in the given class.
37     */
38    static List<FieldInfo> getInstanceFields(Class cls) {
39        Field[] declaredFields = cls.getDeclaredFields();
40        List<FieldInfo> fields =
41            new ArrayList<FieldInfo>(declaredFields.length);
42        for (Field field : declaredFields) {
43            int mods = field.getModifiers();
44            if (!Modifier.isTransient(mods) && !Modifier.isStatic(mods)) {
45                fields.add(new FieldInfo(field));
46            }
47        }
48        return fields;
49    }
50
51    static FieldInfo getField(List<FieldInfo> fields, String fieldName) {
52        int i = getFieldIndex(fields, fieldName);
53        if (i >= 0) {
54            return fields.get(i);
55        } else {
56            return null;
57        }
58    }
59
60    static int getFieldIndex(List<FieldInfo> fields, String fieldName) {
61        for (int i = 0; i < fields.size(); i += 1) {
62            FieldInfo field = fields.get(i);
63            if (fieldName.equals(field.getName())) {
64                return i;
65            }
66        }
67        return -1;
68    }
69
70    private String name;
71    private String className;
72    private Format format;
73    private transient Class cls;
74
75    private FieldInfo(Field field) {
76        name = field.getName();
77        cls = field.getType();
78        className = cls.getName();
79    }
80
81    void collectRelatedFormats(Catalog catalog,
82                               Map<String,Format> newFormats) {
83        format = catalog.createFormat(cls, newFormats);
84    }
85
86    void migrateFromBeta(Map<String,Format> formatMap) {
87        if (format == null) {
88            format = formatMap.get(className);
89            if (format == null) {
90                throw new IllegalStateException(className);
91            }
92        }
93    }
94
95    void initialize(Catalog catalog, int initVersion) {
96    }
97
98    Class getFieldClass() {
99        if (cls == null) {
100            try {
101                cls = SimpleCatalog.classForName(className);
102            } catch (ClassNotFoundException e) {
103                throw new IllegalStateException(e);
104            }
105        }
106        return cls;
107    }
108
109    String getClassName() {
110        return className;
111    }
112
113    public String getName() {
114        return name;
115    }
116
117    public Format getType() {
118        return format;
119    }
120
121    public int compareTo(FieldInfo o) {
122        return name.compareTo(o.name);
123    }
124
125    @Override
126    public boolean equals(Object other) {
127        if (other instanceof FieldInfo) {
128            FieldInfo o = (FieldInfo) other;
129            return name.equals(o.name);
130        } else {
131            return false;
132        }
133    }
134
135    @Override
136    public int hashCode() {
137        return name.hashCode();
138    }
139
140    @Override
141    public String toString() {
142        return "[Field name: " + name + " class: " + className + ']';
143    }
144}
145