001: /**********************************************************************
002: Copyright (c) 2005 Andy Jefferson and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015:
016: Contributors:
017: ...
018: **********************************************************************/package org.jpox.store.mapping;
019:
020: import java.sql.Timestamp;
021: import java.util.Date;
022: import java.util.GregorianCalendar;
023: import java.util.TimeZone;
024:
025: import org.jpox.ClassLoaderResolver;
026: import org.jpox.ClassNameConstants;
027: import org.jpox.ObjectManager;
028: import org.jpox.exceptions.JPOXUserException;
029: import org.jpox.metadata.AbstractMemberMetaData;
030: import org.jpox.store.DatastoreAdapter;
031: import org.jpox.store.DatastoreContainerObject;
032: import org.jpox.store.expression.QueryExpression;
033: import org.jpox.store.expression.ScalarExpression;
034: import org.jpox.store.expression.LogicSetExpression;
035: import org.jpox.store.expression.SqlTemporalExpression;
036: import org.jpox.store.expression.SqlTimestampLiteral;
037:
038: /**
039: * Maps the class fields of a GregorianCalendar to datastore fields.
040: * JPOX traditionally supported this as mapping to 2 datastore fields (timestamp millisecs and timezone).
041: * It also supports as mapping to a single datastore field (timestamp).
042: *
043: * @version $Revision: 1.24 $
044: */
045: public class GregorianCalendarMapping extends SingleFieldMultiMapping {
046: boolean singleColumn = false;
047:
048: /**
049: * Initialize this JavaTypeMapping with the given DatastoreAdapter for the given FieldMetaData.
050: * @param dba The Datastore Adapter that this Mapping should use.
051: * @param fmd FieldMetaData for the field to be mapped (if any)
052: * @param container The datastore container storing this mapping (if any)
053: * @param clr the ClassLoaderResolver
054: */
055: public void initialize(DatastoreAdapter dba,
056: AbstractMemberMetaData fmd,
057: DatastoreContainerObject container, ClassLoaderResolver clr) {
058: super .initialize(dba, fmd, container, clr);
059: if (fmd.hasExtension("calendar-one-column")
060: && fmd.getValueForExtension("calendar-one-column")
061: .equals("true")) {
062: // If this mapping is created via a query we assume multiple columns currently
063: singleColumn = true;
064: }
065:
066: if (singleColumn) {
067: // (Timestamp) implementation
068: addDatastoreField(ClassNameConstants.JAVA_SQL_TIMESTAMP);
069: } else {
070: // (Timestamp millisecs, Timezone) implementation
071: addDatastoreField(ClassNameConstants.LONG); // Timestamp millisecs
072: addDatastoreField(ClassNameConstants.JAVA_LANG_STRING); // Timezone
073: }
074: }
075:
076: /*
077: * (non-Javadoc)
078: * @see org.jpox.store.mapping.JavaTypeMapping#getJavaType()
079: */
080: public Class getJavaType() {
081: return GregorianCalendar.class;
082: }
083:
084: /**
085: * Accessor for the name of the java-type actually used when mapping the particular datastore field.
086: * This java-type must have an entry in the datastore mappings.
087: * @param index requested datastore field index.
088: * @return the name of java-type for the requested datastore field.
089: */
090: public String getJavaTypeForDatastoreMapping(int index) {
091: if (singleColumn) {
092: // (Timestamp) implementation
093: return ClassNameConstants.JAVA_SQL_TIMESTAMP;
094: } else {
095: // (Timestamp millisecs, Timezone) implementation
096: if (index == 0) {
097: return ClassNameConstants.LONG;
098: } else if (index == 1) {
099: return ClassNameConstants.JAVA_LANG_STRING;
100: }
101: }
102: return null;
103: }
104:
105: /*
106: * (non-Javadoc)
107: * @see org.jpox.store.mapping.JavaTypeMapping#getSampleValue()
108: */
109: public Object getSampleValue(ClassLoaderResolver clr) {
110: return new GregorianCalendar();
111: }
112:
113: /*
114: * (non-Javadoc)
115: * @see org.jpox.store.mapping.JavaTypeMapping#setObject(org.jpox.ObjectManager, java.lang.Object,
116: * int[], java.lang.Object)
117: */
118: public void setObject(ObjectManager om, Object preparedStatement,
119: int[] exprIndex, Object value) {
120: GregorianCalendar cal = (GregorianCalendar) value;
121: if (singleColumn) {
122: // (Timestamp) implementation
123: Timestamp ts = null;
124: if (cal != null) {
125: ts = new Timestamp(cal.getTimeInMillis());
126: }
127: // Server timezone will be applied in the RDBMSMapping at persistence
128: getDataStoreMapping(0).setObject(preparedStatement,
129: exprIndex[0], ts);
130: } else {
131: // (Timestamp millisecs, Timezone) implementation
132: if (cal == null) {
133: getDataStoreMapping(0).setObject(preparedStatement,
134: exprIndex[0], null);
135: getDataStoreMapping(1).setObject(preparedStatement,
136: exprIndex[1], null);
137: } else {
138: getDataStoreMapping(0).setLong(preparedStatement,
139: exprIndex[0], cal.getTime().getTime());
140: getDataStoreMapping(1).setString(preparedStatement,
141: exprIndex[1], cal.getTimeZone().getID());
142: }
143: }
144: }
145:
146: /*
147: * (non-Javadoc)
148: * @see org.jpox.store.mapping.JavaTypeMapping#getObject(org.jpox.ObjectManager, java.lang.Object, int[])
149: */
150: public Object getObject(ObjectManager om, Object resultSet,
151: int[] exprIndex) {
152: try {
153: // Check for null entries
154: if (getDataStoreMapping(0).getObject(resultSet,
155: exprIndex[0]) == null) {
156: return null;
157: }
158: } catch (Exception e) {
159: // Do nothing
160: }
161:
162: if (singleColumn) {
163:
164: Timestamp ts = (Timestamp) getDataStoreMapping(0)
165: .getObject(resultSet, exprIndex[0]);
166: GregorianCalendar cal = new GregorianCalendar();
167: cal.setTimeInMillis(ts.getTime());
168:
169: String timezoneID = om.getOMFContext()
170: .getPersistenceConfiguration()
171: .getServerTimeZoneID();
172: if (timezoneID != null) {
173: // Apply server timezone ID since we dont know what it was upon persistence
174: cal.setTimeZone(TimeZone.getTimeZone(timezoneID));
175: }
176: return cal;
177: } else {
178: // (Timestamp millisecs, Timezone) implementation
179: long millisecs = getDataStoreMapping(0).getLong(resultSet,
180: exprIndex[0]);
181:
182: GregorianCalendar cal = new GregorianCalendar();
183: cal.setTime(new Date(millisecs));
184: String timezoneId = getDataStoreMapping(1).getString(
185: resultSet, exprIndex[1]);
186: if (timezoneId != null) {
187: cal.setTimeZone(TimeZone.getTimeZone(timezoneId));
188: }
189: return cal;
190: }
191: }
192:
193: // ---------------------------------- JDOQL Query Methods --------------------------------------
194:
195: /*
196: * (non-Javadoc)
197: * @see org.jpox.store.mapping.JavaTypeMapping#newLiteral(org.jpox.store.query.QueryStatement,
198: * java.lang.Object)
199: */
200: public ScalarExpression newLiteral(QueryExpression qs, Object value) {
201: if (singleColumn) {
202: return new SqlTimestampLiteral(qs, this , (Timestamp) value);
203: } else {
204: // [CORE-2802]
205: throw new JPOXUserException(
206: "JPOX doesnt support querying of Calendar fields when stored as 2 columns");
207: }
208: }
209:
210: /*
211: * (non-Javadoc)
212: * @see org.jpox.store.mapping.JavaTypeMapping#newScalarExpression(org.jpox.store.query.QueryStatement,
213: * org.jpox.store.expression.TableExpression)
214: */
215: public ScalarExpression newScalarExpression(QueryExpression qs,
216: LogicSetExpression te) {
217: if (singleColumn) {
218: return new SqlTemporalExpression(qs, this , te);
219: } else {
220: // [CORE-2802]
221: throw new JPOXUserException(
222: "JPOX doesnt support querying of Calendar fields when stored as 2 columns");
223: }
224: }
225: }
|