001/** 002 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 003 * This file is part of the LDP4j Project: 004 * http://www.ldp4j.org/ 005 * 006 * Center for Open Middleware 007 * http://www.centeropenmiddleware.com/ 008 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 009 * Copyright (C) 2014-2016 Center for Open Middleware. 010 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 011 * Licensed under the Apache License, Version 2.0 (the "License"); 012 * you may not use this file except in compliance with the License. 013 * You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, software 018 * distributed under the License is distributed on an "AS IS" BASIS, 019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 020 * See the License for the specific language governing permissions and 021 * limitations under the License. 022 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 023 * Artifact : org.ldp4j.framework:ldp4j-application-api:0.2.1 024 * Bundle : ldp4j-application-api-0.2.1.jar 025 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 026 */ 027package org.ldp4j.application.data; 028 029import static com.google.common.base.Preconditions.checkNotNull; 030 031import java.io.Serializable; 032import java.net.URI; 033import java.util.Calendar; 034import java.util.Date; 035import java.util.GregorianCalendar; 036import java.util.Locale; 037import java.util.Map.Entry; 038import java.util.TimeZone; 039import java.util.concurrent.TimeUnit; 040 041import javax.xml.datatype.XMLGregorianCalendar; 042 043import org.joda.time.DateTime; 044import org.joda.time.Duration; 045import org.joda.time.Period; 046import org.joda.time.chrono.ISOChronology; 047import org.joda.time.format.ISOPeriodFormat; 048 049import com.google.common.collect.ImmutableMap; 050 051public final class Literals { 052 053 public abstract static class DateTimeLiteralBuilder { 054 055 private DateTimeLiteralBuilder() { 056 } 057 058 public final DateTimeLiteral dateTime() { 059 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.DATE_TIME); 060 } 061 062 public final DateTimeLiteral date() { 063 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.DATE); 064 } 065 066 public final DateTimeLiteral time() { 067 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.TIME); 068 } 069 070 public final DateTimeLiteral year() { 071 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.GYEAR); 072 } 073 074 public final DateTimeLiteral month() { 075 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.GMONTH); 076 } 077 078 public final DateTimeLiteral day() { 079 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.GDAY); 080 } 081 082 public final DateTimeLiteral yearAndMonth() { 083 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.GYEARMONTH); 084 } 085 086 public final DateTimeLiteral monthAndDay() { 087 return new ImmutableDateTimeLiteral(getDateTime(),Datatypes.GMONTHDAY); 088 } 089 090 protected abstract DateTime getDateTime(); 091 092 } 093 094 public static final class DateTimeDateTimeLiteralBuilder extends DateTimeLiteralBuilder { 095 096 private final DateTime dateTime; 097 098 private DateTimeDateTimeLiteralBuilder(DateTime dateTime) { 099 super(); 100 this.dateTime = dateTime; 101 } 102 103 @Override 104 protected DateTime getDateTime() { 105 return dateTime; 106 } 107 108 } 109 110 public static final class XMLGregorianCalendarDateTimeLiteralBuilder extends DateTimeLiteralBuilder { 111 112 private final XMLGregorianCalendar calendar; 113 114 private TimeZone timezone; 115 private Locale locale; 116 private XMLGregorianCalendar defaults; 117 118 private XMLGregorianCalendarDateTimeLiteralBuilder(XMLGregorianCalendar calendar) { 119 super(); 120 this.calendar = calendar; 121 } 122 123 public XMLGregorianCalendarDateTimeLiteralBuilder withTimeZone(TimeZone timezone) { 124 this.timezone = timezone; 125 return this; 126 } 127 128 public XMLGregorianCalendarDateTimeLiteralBuilder withLocale(Locale locale) { 129 this.locale = locale; 130 return this; 131 } 132 133 public XMLGregorianCalendarDateTimeLiteralBuilder withDefaults(XMLGregorianCalendar defaults) { 134 this.defaults = defaults; 135 return this; 136 } 137 138 @Override 139 protected DateTime getDateTime() { 140 return normalizeChronology(new DateTime(this.calendar.toGregorianCalendar(this.timezone, this.locale, this.defaults))); 141 } 142 143 } 144 145 private interface DateTimeLiteralBuilderFactory { 146 147 DateTimeLiteralBuilder createBuilder(Object value, URI datatype); 148 149 } 150 151 private interface DateTimeLiteralBuilderAdapter { 152 153 DateTimeLiteral adapt(DateTimeLiteralBuilder builder); 154 155 } 156 157 private static final ImmutableMap<Class<?>,DateTimeLiteralBuilderFactory> FACTORIES= 158 ImmutableMap. 159 <Class<?>,DateTimeLiteralBuilderFactory>builder(). 160 put( 161 Date.class, 162 new DateTimeLiteralBuilderFactory() { 163 @Override 164 public DateTimeLiteralBuilder createBuilder(Object value, URI datatype) { 165 return of((Date)value); 166 } 167 } 168 ). 169 put( 170 GregorianCalendar.class, 171 new DateTimeLiteralBuilderFactory() { 172 @Override 173 public DateTimeLiteralBuilder createBuilder(Object value, URI datatype) { 174 return of((GregorianCalendar)value); 175 } 176 } 177 ). 178 put( 179 Calendar.class, 180 new DateTimeLiteralBuilderFactory() { 181 @Override 182 public DateTimeLiteralBuilder createBuilder(Object value, URI datatype) { 183 return of((Calendar)value); 184 } 185 } 186 ). 187 put( 188 DateTime.class, 189 new DateTimeLiteralBuilderFactory() { 190 @Override 191 public DateTimeLiteralBuilder createBuilder(Object value, URI datatype) { 192 return of((DateTime)value); 193 } 194 } 195 ). 196 put( 197 XMLGregorianCalendar.class, 198 new DateTimeLiteralBuilderFactory() { 199 @Override 200 public DateTimeLiteralBuilder createBuilder(Object value, URI datatype) { 201 return of((XMLGregorianCalendar)value); 202 } 203 } 204 ). 205 put( 206 String.class, 207 new DateTimeLiteralBuilderFactory() { 208 @Override 209 public DateTimeLiteralBuilder createBuilder(Object value, URI datatype) { 210 try { 211 return of(new DateTime(value)); 212 } catch (Exception e) { 213 throw new DatatypeCohercionException(value,datatype,e); 214 } 215 } 216 } 217 ). 218 build(); 219 220 private static final ImmutableMap<URI,DateTimeLiteralBuilderAdapter> ADAPTERS= 221 ImmutableMap. 222 <URI,DateTimeLiteralBuilderAdapter>builder(). 223 put( 224 Datatypes.DATE_TIME, 225 new DateTimeLiteralBuilderAdapter() { 226 @Override 227 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 228 return builder.dateTime(); 229 } 230 } 231 ). 232 put( 233 Datatypes.DATE, 234 new DateTimeLiteralBuilderAdapter() { 235 @Override 236 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 237 return builder.date(); 238 } 239 } 240 ). 241 put( 242 Datatypes.TIME, 243 new DateTimeLiteralBuilderAdapter() { 244 @Override 245 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 246 return builder.time(); 247 } 248 } 249 ). 250 put( 251 Datatypes.GYEAR, 252 new DateTimeLiteralBuilderAdapter() { 253 @Override 254 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 255 return builder.year(); 256 } 257 } 258 ). 259 put( 260 Datatypes.GMONTH, 261 new DateTimeLiteralBuilderAdapter() { 262 @Override 263 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 264 return builder.month(); 265 } 266 } 267 ). 268 put( 269 Datatypes.GDAY, 270 new DateTimeLiteralBuilderAdapter() { 271 @Override 272 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 273 return builder.day(); 274 } 275 } 276 ). 277 put( 278 Datatypes.GYEARMONTH, 279 new DateTimeLiteralBuilderAdapter() { 280 @Override 281 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 282 return builder.yearAndMonth(); 283 } 284 } 285 ). 286 put( 287 Datatypes.GMONTHDAY, 288 new DateTimeLiteralBuilderAdapter() { 289 @Override 290 public DateTimeLiteral adapt(DateTimeLiteralBuilder builder) { 291 return builder.monthAndDay(); 292 } 293 } 294 ). 295 build(); 296 297 private static final String DATATYPE_CANNOT_BE_NULL = "Datatype cannot be null"; 298 private static final String LANGUAGE_CANNOT_BE_NULL = "Language cannot be null"; 299 private static final String STRING_CANNOT_BE_NULL = "String cannot be null"; 300 private static final String TIME_UNIT_CANNOT_BE_NULL = "Time unit cannot be null"; 301 private static final String DATE_TIME_CANNOT_BE_NULL = "Date-time cannot be null"; 302 private static final String LITERAL_VALUE_CANNOT_BE_NULL = "Literal value cannot be null"; 303 private static final String CALENDAR_CANNOT_BE_NULL = "Calendar cannot be null"; 304 private static final String TIME_CANNOT_BE_NULL = "Time cannot be null"; 305 private static final String DATE_CANNOT_BE_NULL = "Date cannot be null"; 306 private static final String DURATION_CANNOT_BE_NULL = "Duration cannot be null"; 307 308 309 private static final Class<?>[] DATE_TIME_CLASSES={ 310 java.sql.Date.class, 311 Date.class, 312 java.sql.Time.class, 313 DateTime.class, 314 GregorianCalendar.class, 315 Calendar.class, 316 XMLGregorianCalendar.class 317 }; 318 319 private static final Class<?>[] DURATION_CLASSES={ 320 Duration.class, 321 javax.xml.datatype.Duration.class 322 }; 323 324 private Literals() { 325 } 326 327 private static boolean isDateTime(Object obj) { 328 return isInstanceOf(obj,Literals.DATE_TIME_CLASSES); 329 } 330 331 private static boolean isDuration(Object obj) { 332 return isInstanceOf(obj,Literals.DURATION_CLASSES); 333 } 334 335 private static boolean isInstanceOf(Object obj, Class<?>[] classes) { 336 for(Class<?> clazz:classes) { 337 if(clazz.isInstance(obj)) { 338 return true; 339 } 340 } 341 return false; 342 } 343 344 private static DateTime normalizeChronology(DateTime dateTime) { 345 return dateTime.withChronology(ISOChronology.getInstance()); 346 } 347 348 private static <T> DurationLiteral coherceDuration(T value) { 349 DurationLiteral duration=null; 350 if(value instanceof Duration) { 351 duration=of((Duration)value); 352 } else if(value instanceof javax.xml.datatype.Duration) { 353 duration=of((javax.xml.datatype.Duration)value); 354 } else if(value instanceof String) { 355 try { 356 Period period = ISOPeriodFormat.standard().parsePeriod((String)value); 357 duration=of(period.toStandardDuration()); 358 } catch (Exception e) { 359 throw new DatatypeCohercionException(value,Datatypes.DURATION,e); 360 } 361 } else { 362 throw new DatatypeCohercionException(value,Datatypes.DURATION); 363 } 364 return duration; 365 } 366 367 private static DateTimeLiteral coherceDateTime(Object value, URI datatype) throws AssertionError { 368 DateTimeLiteral dateTime=null; 369 if(value instanceof java.sql.Date) { 370 dateTime=of((java.sql.Date)value); 371 } else if(value instanceof java.sql.Time) { 372 dateTime=of((java.sql.Time)value); 373 } else { 374 dateTime=coherceVariableDateTime(value,datatype); 375 } 376 return dateTime; 377 } 378 379 private static DateTimeLiteral coherceVariableDateTime(Object value, URI datatype) { 380 return Literals.ADAPTERS.get(datatype).adapt(getBuilder(value,datatype)); 381 } 382 383 private static DateTimeLiteralBuilder getBuilder(Object value, URI datatype) { 384 for(Entry<Class<?>,DateTimeLiteralBuilderFactory> entry:Literals.FACTORIES.entrySet()) { 385 if(entry.getKey().isInstance(value)) { 386 return entry.getValue().createBuilder(value, datatype); 387 } 388 } 389 throw new DatatypeCohercionException(value,datatype); 390 } 391 392 public static Literal<String> of(String value) { 393 checkNotNull(value,STRING_CANNOT_BE_NULL); 394 return new ImmutableLiteral<String>(value); 395 } 396 397 public static DurationLiteral of(javax.xml.datatype.Duration duration) { 398 checkNotNull(duration,DURATION_CANNOT_BE_NULL); 399 Period period = ISOPeriodFormat.standard().parsePeriod(duration.toString()); 400 return new ImmutableDurationLiteral(period.toStandardDuration(),Datatypes.DURATION); 401 } 402 403 public static DurationLiteral of(Duration duration) { 404 checkNotNull(duration,DURATION_CANNOT_BE_NULL); 405 return new ImmutableDurationLiteral(duration,Datatypes.DURATION); 406 } 407 408 public static DateTimeDateTimeLiteralBuilder of(Date date) { 409 checkNotNull(date,DATE_CANNOT_BE_NULL); 410 return new DateTimeDateTimeLiteralBuilder(new DateTime(date)); 411 } 412 413 public static DateTimeLiteral of(java.sql.Date date) { 414 checkNotNull(date,DATE_CANNOT_BE_NULL); 415 return new ImmutableDateTimeLiteral(new DateTime(date), Datatypes.DATE); 416 } 417 418 public static DateTimeLiteral of(java.sql.Time time) { 419 checkNotNull(time,TIME_CANNOT_BE_NULL); 420 return new ImmutableDateTimeLiteral(new DateTime(time.getTime()), Datatypes.TIME); 421 } 422 423 public static DateTimeDateTimeLiteralBuilder of(Calendar calendar) { 424 checkNotNull(calendar,CALENDAR_CANNOT_BE_NULL); 425 return new DateTimeDateTimeLiteralBuilder(normalizeChronology(new DateTime(calendar))); 426 } 427 428 public static DateTimeDateTimeLiteralBuilder of(GregorianCalendar calendar) { 429 checkNotNull(calendar,CALENDAR_CANNOT_BE_NULL); 430 return new DateTimeDateTimeLiteralBuilder(normalizeChronology(new DateTime(calendar))); 431 } 432 433 public static XMLGregorianCalendarDateTimeLiteralBuilder of(XMLGregorianCalendar calendar) { 434 checkNotNull(calendar,CALENDAR_CANNOT_BE_NULL); 435 return new XMLGregorianCalendarDateTimeLiteralBuilder(calendar); 436 } 437 438 public static DateTimeDateTimeLiteralBuilder of(DateTime dateTime) { 439 checkNotNull(dateTime,DATE_TIME_CANNOT_BE_NULL); 440 return new DateTimeDateTimeLiteralBuilder(dateTime); 441 } 442 443 public static DurationLiteral duration(long time, TimeUnit unit) { 444 checkNotNull(time,TIME_CANNOT_BE_NULL); 445 checkNotNull(unit,TIME_UNIT_CANNOT_BE_NULL); 446 return of(new Duration(TimeUnit.MILLISECONDS.convert(time, unit))); 447 } 448 449 public static Literal<? extends Serializable> newLiteral(Object value) { 450 checkNotNull(value,LITERAL_VALUE_CANNOT_BE_NULL); 451 Literal<? extends Serializable> result=null; 452 if(isDuration(value)) { 453 result=coherceDuration(value); 454 } else if(isDateTime(value)) { 455 result=coherceDateTime(value,Datatypes.DATE_TIME); 456 } else if(value instanceof Serializable) { 457 result=new ImmutableLiteral<Serializable>((Serializable)value); 458 } else { 459 result=new ImmutableTypedLiteral<String>(value.toString(),Datatypes.STRING); 460 } 461 return result; 462 } 463 464 public static TypedLiteral<? extends Serializable> newTypedLiteral(Object value, URI datatype) { 465 checkNotNull(value,LITERAL_VALUE_CANNOT_BE_NULL); 466 checkNotNull(datatype,DATATYPE_CANNOT_BE_NULL); 467 TypedLiteral<? extends Serializable> result=null; 468 if(Datatypes.isDuration(datatype)) { 469 result=coherceDuration(value); 470 } else if(Datatypes.isTemporal(datatype)) { 471 result=coherceDateTime(value, datatype); 472 } else if(value instanceof Serializable){ 473 result=new ImmutableTypedLiteral<Serializable>((Serializable)value,datatype); 474 } else { 475 result=new ImmutableTypedLiteral<String>(value.toString(),Datatypes.STRING); 476 } 477 return result; 478 } 479 480 public static LanguageLiteral newLanguageLiteral(String value, String language) { 481 checkNotNull(value,STRING_CANNOT_BE_NULL); 482 checkNotNull(language,LANGUAGE_CANNOT_BE_NULL); 483 return new ImmutableLanguageLiteral(value,language); 484 } 485 486}