Skip to content

Commit a1131e6

Browse files
author
sjaakd
committed
mapstruct#689 Joda LocalTime to XmlGregorianCalendar built in and vice versa
1 parent aec5922 commit a1131e6

9 files changed

Lines changed: 442 additions & 0 deletions

File tree

processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public BuiltInMappingMethods(TypeFactory typeFactory) {
6363
builtInMethods.add( new XmlGregorianCalendarToJodaLocalDateTime( typeFactory ) );
6464
builtInMethods.add( new JodaLocalDateToXmlGregorianCalendar( typeFactory ) );
6565
builtInMethods.add( new XmlGregorianCalendarToJodaLocalDate( typeFactory ) );
66+
builtInMethods.add( new JodaLocalTimeToXmlGregorianCalendar( typeFactory ) );
67+
builtInMethods.add( new XmlGregorianCalendarToJodaLocalTime( typeFactory ) );
6668
}
6769
}
6870

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.internal.model.source.builtin;
20+
21+
import static org.mapstruct.ap.internal.util.Collections.asSet;
22+
23+
import java.util.Set;
24+
25+
import javax.xml.datatype.DatatypeConfigurationException;
26+
import javax.xml.datatype.DatatypeConstants;
27+
import javax.xml.datatype.DatatypeFactory;
28+
import javax.xml.datatype.XMLGregorianCalendar;
29+
30+
import org.mapstruct.ap.internal.model.common.Parameter;
31+
import org.mapstruct.ap.internal.model.common.Type;
32+
import org.mapstruct.ap.internal.model.common.TypeFactory;
33+
import org.mapstruct.ap.internal.util.JodaTimeConstants;
34+
35+
/**
36+
* @author Sjaak Derksen
37+
*/
38+
public class JodaLocalTimeToXmlGregorianCalendar extends BuiltInMethod {
39+
40+
private final Parameter parameter;
41+
private final Type returnType;
42+
private final Set<Type> importTypes;
43+
44+
public JodaLocalTimeToXmlGregorianCalendar(TypeFactory typeFactory) {
45+
this.parameter = new Parameter(
46+
"dt",
47+
typeFactory.getType( JodaTimeConstants.LOCAL_TIME_FQN )
48+
);
49+
this.returnType = typeFactory.getType( XMLGregorianCalendar.class );
50+
51+
this.importTypes = asSet(
52+
returnType,
53+
parameter.getType(),
54+
typeFactory.getType( DatatypeConstants.class ),
55+
typeFactory.getType( DatatypeFactory.class ),
56+
typeFactory.getType( DatatypeConfigurationException.class )
57+
);
58+
}
59+
60+
@Override
61+
public Set<Type> getImportTypes() {
62+
return importTypes;
63+
}
64+
65+
@Override
66+
public Parameter getParameter() {
67+
return parameter;
68+
}
69+
70+
@Override
71+
public Type getReturnType() {
72+
return returnType;
73+
}
74+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.internal.model.source.builtin;
20+
21+
import static org.mapstruct.ap.internal.util.Collections.asSet;
22+
23+
import java.util.Set;
24+
import javax.xml.datatype.DatatypeConstants;
25+
import javax.xml.datatype.XMLGregorianCalendar;
26+
27+
import org.mapstruct.ap.internal.model.common.Parameter;
28+
import org.mapstruct.ap.internal.model.common.Type;
29+
import org.mapstruct.ap.internal.model.common.TypeFactory;
30+
import org.mapstruct.ap.internal.util.JodaTimeConstants;
31+
32+
/**
33+
* @author Sjaak Derksen
34+
*/
35+
public class XmlGregorianCalendarToJodaLocalTime extends BuiltInMethod {
36+
37+
private final Parameter parameter;
38+
private final Type returnType;
39+
private final Set<Type> importTypes;
40+
41+
public XmlGregorianCalendarToJodaLocalTime(TypeFactory typeFactory) {
42+
this.parameter = new Parameter( "xcal", typeFactory.getType( XMLGregorianCalendar.class ) );
43+
this.returnType = typeFactory.getType( JodaTimeConstants.LOCAL_TIME_FQN );
44+
this.importTypes = asSet(
45+
typeFactory.getType( DatatypeConstants.class ),
46+
returnType,
47+
parameter.getType() );
48+
}
49+
50+
@Override
51+
public Parameter getParameter() {
52+
return parameter;
53+
}
54+
55+
@Override
56+
public Type getReturnType() {
57+
return returnType;
58+
}
59+
60+
@Override
61+
public Set<Type> getImportTypes() {
62+
return importTypes;
63+
}
64+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<#--
2+
3+
Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
4+
and/or other contributors as indicated by the @authors tag. See the
5+
copyright.txt file in the distribution for a full listing of all
6+
contributors.
7+
8+
Licensed under the Apache License, Version 2.0 (the "License");
9+
you may not use this file except in compliance with the License.
10+
You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing, software
15+
distributed under the License is distributed on an "AS IS" BASIS,
16+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
See the License for the specific language governing permissions and
18+
limitations under the License.
19+
20+
-->
21+
private XMLGregorianCalendar ${name}( LocalTime dt ) {
22+
if ( dt == null ) {
23+
return null;
24+
}
25+
26+
try {
27+
return DatatypeFactory.newInstance().newXMLGregorianCalendarTime(
28+
dt.getHourOfDay(),
29+
dt.getMinuteOfHour(),
30+
dt.getSecondOfMinute(),
31+
dt.getMillisOfSecond(),
32+
DatatypeConstants.FIELD_UNDEFINED );
33+
}
34+
catch ( DatatypeConfigurationException ex ) {
35+
throw new RuntimeException( ex );
36+
}
37+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<#--
2+
3+
Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
4+
and/or other contributors as indicated by the @authors tag. See the
5+
copyright.txt file in the distribution for a full listing of all
6+
contributors.
7+
8+
Licensed under the Apache License, Version 2.0 (the "License");
9+
you may not use this file except in compliance with the License.
10+
You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing, software
15+
distributed under the License is distributed on an "AS IS" BASIS,
16+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
See the License for the specific language governing permissions and
18+
limitations under the License.
19+
20+
-->
21+
private static LocalTime ${name}( XMLGregorianCalendar xcal ) {
22+
if ( xcal == null ) {
23+
return null;
24+
}
25+
26+
if ( xcal.getHour() != DatatypeConstants.FIELD_UNDEFINED
27+
&& xcal.getMinute() != DatatypeConstants.FIELD_UNDEFINED ) {
28+
if ( xcal.getSecond() != DatatypeConstants.FIELD_UNDEFINED
29+
&& xcal.getMillisecond() != DatatypeConstants.FIELD_UNDEFINED ) {
30+
return new LocalTime( xcal.getHour(),
31+
xcal.getMinute(),
32+
xcal.getSecond(),
33+
xcal.getMillisecond()
34+
);
35+
}
36+
else if ( xcal.getSecond() != DatatypeConstants.FIELD_UNDEFINED ) {
37+
return new LocalTime(
38+
xcal.getHour(),
39+
xcal.getMinute(),
40+
xcal.getSecond()
41+
);
42+
}
43+
else {
44+
return new LocalTime( xcal.getHour(),
45+
xcal.getMinute()
46+
);
47+
}
48+
}
49+
return null;
50+
}

processor/src/test/java/org/mapstruct/ap/test/builtin/bean/jodatime/JodaTimeTest.java

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,22 @@
2727
import org.joda.time.DateTimeZone;
2828
import org.joda.time.LocalDate;
2929
import org.joda.time.LocalDateTime;
30+
import org.joda.time.LocalTime;
3031
import org.junit.Test;
3132
import org.junit.runner.RunWith;
3233
import org.mapstruct.ap.test.builtin.bean.jodatime.bean.DateTimeBean;
3334
import org.mapstruct.ap.test.builtin.bean.jodatime.bean.LocalDateBean;
3435
import org.mapstruct.ap.test.builtin.bean.jodatime.bean.LocalDateTimeBean;
36+
import org.mapstruct.ap.test.builtin.bean.jodatime.bean.LocalTimeBean;
3537
import org.mapstruct.ap.test.builtin.bean.jodatime.bean.XmlGregorianCalendarBean;
3638
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.DateTimeToXmlGregorianCalendar;
3739
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.LocalDateTimeToXmlGregorianCalendar;
3840
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.LocalDateToXmlGregorianCalendar;
41+
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.LocalTimeToXmlGregorianCalendar;
3942
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.XmlGregorianCalendarToDateTime;
4043
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.XmlGregorianCalendarToLocalDate;
4144
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.XmlGregorianCalendarToLocalDateTime;
45+
import org.mapstruct.ap.test.builtin.bean.jodatime.mapper.XmlGregorianCalendarToLocalTime;
4246
import org.mapstruct.ap.testutil.IssueKey;
4347
import org.mapstruct.ap.testutil.WithClasses;
4448
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
@@ -49,6 +53,7 @@
4953
*/
5054
@WithClasses({
5155
DateTimeBean.class,
56+
LocalTimeBean.class,
5257
LocalDateBean.class,
5358
LocalDateTimeBean.class,
5459
XmlGregorianCalendarBean.class
@@ -447,4 +452,99 @@ public void shouldNotMapXmlGregorianCalendarWithoutDaysToLocalDate() throws Exce
447452
assertThat( res.getLocalDate() ).isNull();
448453

449454
}
455+
456+
457+
458+
459+
460+
461+
462+
@Test
463+
@WithClasses(LocalTimeToXmlGregorianCalendar.class)
464+
public void shouldMapIncompleteLocalTimeToXmlGregorianCalendar() {
465+
466+
LocalTimeBean in = new LocalTimeBean();
467+
LocalTime dt = new LocalTime( 1, 1, 0, 100 );
468+
in.setLocalTime( dt );
469+
XmlGregorianCalendarBean res = LocalTimeToXmlGregorianCalendar.INSTANCE.toXmlGregorianCalendarBean( in );
470+
471+
assertThat( res.getxMLGregorianCalendar().getYear() ).isEqualTo( DatatypeConstants.FIELD_UNDEFINED );
472+
assertThat( res.getxMLGregorianCalendar().getMonth() ).isEqualTo( DatatypeConstants.FIELD_UNDEFINED );
473+
assertThat( res.getxMLGregorianCalendar().getDay() ).isEqualTo( DatatypeConstants.FIELD_UNDEFINED );
474+
assertThat( res.getxMLGregorianCalendar().getHour() ).isEqualTo( 1 );
475+
assertThat( res.getxMLGregorianCalendar().getMinute() ).isEqualTo( 1 );
476+
assertThat( res.getxMLGregorianCalendar().getSecond() ).isEqualTo( 0 );
477+
assertThat( res.getxMLGregorianCalendar().getMillisecond() ).isEqualTo( 100 );
478+
assertThat( res.getxMLGregorianCalendar().getTimezone() ).isEqualTo( DatatypeConstants.FIELD_UNDEFINED );
479+
}
480+
481+
@Test
482+
@WithClasses(XmlGregorianCalendarToLocalTime.class)
483+
public void shouldMapXmlGregorianCalendarToLocalTime() throws Exception {
484+
485+
XmlGregorianCalendarBean in = new XmlGregorianCalendarBean();
486+
XMLGregorianCalendar xcal =
487+
DatatypeFactory.newInstance().newXMLGregorianCalendarTime( 1, 1, 1, 100, 60 );
488+
in.setxMLGregorianCalendar( xcal );
489+
490+
LocalTimeBean res = XmlGregorianCalendarToLocalTime.INSTANCE.toLocalTimeBean( in );
491+
assertThat( res.getLocalTime().getHourOfDay() ).isEqualTo( 1 );
492+
assertThat( res.getLocalTime().getMinuteOfHour() ).isEqualTo( 1 );
493+
assertThat( res.getLocalTime().getSecondOfMinute() ).isEqualTo( 1 );
494+
assertThat( res.getLocalTime().getMillisOfSecond() ).isEqualTo( 100 );
495+
}
496+
497+
@Test
498+
@WithClasses(XmlGregorianCalendarToLocalTime.class)
499+
public void shouldMapXmlGregorianCalendarWithoutMillisToLocalTime() throws Exception {
500+
501+
XmlGregorianCalendarBean in = new XmlGregorianCalendarBean();
502+
XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar();
503+
xcal.setHour( 23 );
504+
xcal.setMinute( 34 );
505+
xcal.setSecond( 45 );
506+
in.setxMLGregorianCalendar( xcal );
507+
508+
LocalTimeBean res = XmlGregorianCalendarToLocalTime.INSTANCE.toLocalTimeBean( in );
509+
assertThat( res.getLocalTime().getHourOfDay() ).isEqualTo( 23 );
510+
assertThat( res.getLocalTime().getMinuteOfHour() ).isEqualTo( 34 );
511+
assertThat( res.getLocalTime().getSecondOfMinute() ).isEqualTo( 45 );
512+
assertThat( res.getLocalTime().getMillisOfSecond() ).isEqualTo( 0 );
513+
}
514+
515+
@Test
516+
@WithClasses(XmlGregorianCalendarToLocalTime.class)
517+
public void shouldMapXmlGregorianCalendarWithoutSecondsToLocalTime() throws Exception {
518+
519+
XmlGregorianCalendarBean in = new XmlGregorianCalendarBean();
520+
XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar();
521+
xcal.setHour( 23 );
522+
xcal.setMinute( 34 );
523+
xcal.setTimezone( 60 );
524+
in.setxMLGregorianCalendar( xcal );
525+
526+
LocalTimeBean res = XmlGregorianCalendarToLocalTime.INSTANCE.toLocalTimeBean( in );
527+
assertThat( res.getLocalTime().getHourOfDay() ).isEqualTo( 23 );
528+
assertThat( res.getLocalTime().getMinuteOfHour() ).isEqualTo( 34 );
529+
assertThat( res.getLocalTime().getSecondOfMinute() ).isEqualTo( 0 );
530+
assertThat( res.getLocalTime().getMillisOfSecond() ).isEqualTo( 0 );
531+
}
532+
533+
@Test
534+
@WithClasses(XmlGregorianCalendarToLocalTime.class)
535+
public void shouldNotMapXmlGregorianCalendarWithoutMinutesToLocalTime() throws Exception {
536+
537+
XmlGregorianCalendarBean in = new XmlGregorianCalendarBean();
538+
XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar();
539+
xcal.setYear( 1999 );
540+
xcal.setMonth( 5 );
541+
xcal.setDay( 25 );
542+
xcal.setHour( 23 );
543+
in.setxMLGregorianCalendar( xcal );
544+
545+
LocalTimeBean res = XmlGregorianCalendarToLocalTime.INSTANCE.toLocalTimeBean( in );
546+
assertThat( res.getLocalTime() ).isNull();
547+
548+
}
549+
450550
}

0 commit comments

Comments
 (0)