001    package nl.tudelft.tbm.eeni.owl2java.model.xsd;
002    
003    import com.hp.hpl.jena.datatypes.DatatypeFormatException;
004    import com.hp.hpl.jena.datatypes.RDFDatatype;
005    import com.hp.hpl.jena.datatypes.TypeMapper;
006    import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
007    import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
008    import com.hp.hpl.jena.datatypes.xsd.XSDDuration;
009    import com.hp.hpl.jena.ontology.OntModel;
010    import com.hp.hpl.jena.rdf.model.Literal;
011    import com.hp.hpl.jena.rdf.model.Statement;
012    import com.hp.hpl.jena.util.iterator.Map1;
013    import org.apache.commons.logging.Log;
014    import org.apache.commons.logging.LogFactory;
015    
016    import java.math.BigDecimal;
017    import java.math.BigInteger;
018    import java.text.SimpleDateFormat;
019    import java.util.Calendar;
020    
021    public class XsdUtils {
022    
023        private static Log log = LogFactory.getLog(XsdUtils.class);
024    
025        // ///////////////////////////////////////////////////
026        // Helper function to convert from Calendar to various xsd date/time strings
027        // ///////////////////////////////////////////////////
028    
029        // CCYY-MM-DD (w/ optional time zone)
030        // timezone is "[+|-]hh:mm" or "Z" for UTC
031        private static final SimpleDateFormat XSD_date = new SimpleDateFormat("yyyy-MM-ddZ");
032    
033        // CCYY-MM-DDThh:mm:ss (w/ optional time zone)
034        private static final SimpleDateFormat XSD_dateTime = new SimpleDateFormat(
035                "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
036    
037        // hh:mm:ss (w/ optional time zone)
038        private static final SimpleDateFormat XSD_time = new SimpleDateFormat("HH:mm:ss.SSSZ");
039    
040        // ---DD (w/ optional time zone)
041        private static final SimpleDateFormat XSD_gDay = new SimpleDateFormat("---ddZ");
042    
043        // --MM-- (w/ optional time zone)
044        private static final SimpleDateFormat XSD_gMonth = new SimpleDateFormat("--MM--Z");
045    
046        // --MM-DD (w/ optional time zone)
047        private static final SimpleDateFormat XSD_gMonthDay = new SimpleDateFormat("--MM-ddZ");
048    
049        // CCYY (w/ optional time zone)
050        private static final SimpleDateFormat XSD_gYear = new SimpleDateFormat("yyyyZ");
051    
052        // CCYY-MM (w/ optional time zone)
053        private static final SimpleDateFormat XSD_gYearMonth = new SimpleDateFormat("yyyy-MMZ");
054    
055        /**
056         * Convenience function to generate lexical values from a Calendar object based on a specified
057         * RDF datatype.
058         */
059        public static String CalendarToXSD(Calendar c, RDFDatatype dt) {
060            String time = null;
061            if (dt.equals(XSDDatatype.XSDdate)) {
062                time = XSD_date.format(c.getTime());
063            } else if (dt.equals(XSDDatatype.XSDdateTime)) {
064                time = XSD_dateTime.format(c.getTime());
065            } else if (dt.equals(XSDDatatype.XSDgDay)) {
066                time = XSD_gDay.format(c.getTime());
067            } else if (dt.equals(XSDDatatype.XSDgMonth)) {
068                time = XSD_gMonth.format(c.getTime());
069            } else if (dt.equals(XSDDatatype.XSDgMonthDay)) {
070                time = XSD_gMonthDay.format(c.getTime());
071            } else if (dt.equals(XSDDatatype.XSDgYear)) {
072                time = XSD_gYear.format(c.getTime());
073            } else if (dt.equals(XSDDatatype.XSDgYearMonth)) {
074                time = XSD_gYearMonth.format(c.getTime());
075            } else if (dt.equals(XSDDatatype.XSDtime)) {
076                time = XSD_time.format(c.getTime());
077            } else {
078                return c.toString();
079            }
080            StringBuffer sb = new StringBuffer(time);
081            sb.insert(sb.length() - 2, ':');
082            return sb.toString();
083        }
084    
085        public static String DateTimeToXSD(XSDDateTime datetime, RDFDatatype dt) {
086            Calendar cal = datetime.asCalendar();
087            return CalendarToXSD(cal, dt);
088        }
089    
090        public static String DurationToXSD(XSDDuration duration, RDFDatatype dt) {
091            return duration.toString();
092        }
093    
094        public static Literal createTypedLiteral(OntModel ontModel, Object obj, String dataType) {
095            RDFDatatype rdfdt = TypeMapper.getInstance().getTypeByName(dataType);
096            if (obj instanceof Calendar) {
097                String lex = CalendarToXSD((Calendar) obj, rdfdt);
098                if (rdfdt.isValidValue(lex)) {
099                    return ontModel.createTypedLiteral(lex, dataType);
100                } else {
101                    throw new DatatypeFormatException(lex, rdfdt, "Value does not match datatype.");
102                }
103            } else if (obj instanceof XSDDateTime) {
104                String lex = DateTimeToXSD((XSDDateTime) obj, rdfdt);
105                if (rdfdt.isValidValue(lex)) {
106                    return ontModel.createTypedLiteral(lex, dataType);
107                } else {
108                    throw new DatatypeFormatException(lex, rdfdt, "Value does not match datatype.");
109                }
110            } else if (obj instanceof XSDDuration) {
111                String lex = DurationToXSD((XSDDuration) obj, rdfdt);
112                if (rdfdt.isValidValue(lex)) {
113                    return ontModel.createTypedLiteral(lex, dataType);
114                } else {
115                    throw new DatatypeFormatException(lex, rdfdt, "Value does not match datatype.");
116                }
117            } else if (rdfdt.isValid(obj.toString())) {
118                // Don't want to store the object directly because the model should not contain
119                // mutable objects.
120                return ontModel.createTypedLiteral(obj.toString(), dataType);
121            } else {
122                throw new DatatypeFormatException(obj.toString(), rdfdt,
123                        "Value does not match datatype.");
124            }
125        }
126    
127        public static BigDecimal getBigDecimal(Literal l) {
128            Object o = l.getValue();
129            if (o instanceof BigDecimal) {
130                return (BigDecimal) o;
131            } else if (o instanceof Number) {
132                Number n = (Number) o;
133                try {
134                    // Throws NumberFormatException
135                    return new BigDecimal(n.toString());
136                } catch (NumberFormatException e) {
137                    log.error("Error in getBigDecimal for literal " + l.toString());
138                    return null;
139                }
140            } else {
141                return null;
142            }
143        }
144    
145        public static BigInteger getBigInteger(Literal l) {
146            Object o = l.getValue();
147            if (o instanceof BigInteger) {
148                return (BigInteger) o;
149            } else if (o instanceof Number) {
150                Number n = (Number) o;
151                try {
152                    // Throws NumberFormatException
153                    return new BigInteger(n.toString());
154                } catch (NumberFormatException e) {
155                    log.error("Error in getBigInteger for literal " + l.toString());
156                    return null;
157                }
158            } else {
159    
160                return null;
161            }
162        }
163    
164        public static Boolean getBoolean(Literal l) {
165            return new Boolean(l.getBoolean());
166        }
167    
168        public static Byte getByte(Literal l) {
169            return new Byte(l.getByte());
170        }
171    
172        public static Calendar getCalendar(Literal l) {
173            try {
174                Object o = l.getValue();
175                if (o instanceof Calendar) {
176                    return (Calendar) o;
177                } else if (o instanceof XSDDateTime) {
178                    // Will be fixed with next release of Jena.
179                    Calendar c = ((XSDDateTime) o).asCalendar();
180                    // c.set(Calendar.MONTH, c.get(Calendar.MONTH)-1);
181                    return c;
182                }
183            } catch (DatatypeFormatException e) {
184                log.error("Error in getCalendar for literal " + l.toString());
185            }
186            return null;
187        }
188    
189        public static Character getCharacter(Literal l) {
190            return new Character(l.getChar());
191        }
192    
193        public static Double getDouble(Literal l) {
194            return new Double(l.getDouble());
195        }
196    
197        public static Float getFloat(Literal l) {
198            return new Float(l.getFloat());
199        }
200    
201        public static Integer getInteger(Literal l) {
202            return new Integer(l.getInt());
203        }
204    
205        public static Long getLong(Literal l) {
206            return new Long(l.getLong());
207        }
208    
209        public static Short getShort(Literal l) {
210            return new Short(l.getShort());
211        }
212    
213        public static String getString(Literal l) {
214            return l.getString();
215        }
216    
217        public static XSDDateTime getXSDDateTime(Literal l) {
218            Object o = l.getValue();
219            if (o instanceof XSDDateTime) {
220                XSDDateTime dt = (XSDDateTime) o;
221                return dt;
222            }
223            return null;
224        }
225    
226        public static XSDDuration getXSDDuration(Literal l) {
227            Object o = l.getValue();
228            if (o instanceof XSDDuration) {
229                XSDDuration d = (XSDDuration) o;
230                return d;
231            }
232            return null;
233        }
234    
235        public static final Map1<Statement, BigDecimal> objectAsBigDecimalMapper = new Map1<Statement, BigDecimal>() {
236            @Override
237            public BigDecimal map1(Statement x) {
238                try {
239                    Literal l = x.getLiteral();
240                    return getBigDecimal(l);
241                } catch (Exception e) {
242                    log.warn("Could not convert statement " + x + "to BigDecimal");
243                    return null;
244                }
245            }
246        };
247    
248        public static final Map1<Statement, BigInteger> objectAsBigIntegerMapper = new Map1<Statement, BigInteger>() {
249            @Override
250            public BigInteger map1(Statement x) {
251                try {
252                    Literal l = x.getLiteral();
253                    return getBigInteger(l);
254                } catch (Exception e) {
255                    log.warn("Could not convert statement " + x + "to BigInteger");
256                    return null;
257                }
258            }
259        };
260    
261        public static final Map1<Statement, Boolean> objectAsBooleanMapper = new Map1<Statement, Boolean>() {
262            @Override
263            public Boolean map1(Statement x) {
264                try {
265                    Literal l = x.getLiteral();
266                    return getBoolean(l);
267                } catch (Exception e) {
268                    log.warn("Could not convert statement " + x + "to Boolean");
269                    return null;
270                }
271            }
272        };
273    
274        public static final Map1<Statement, Byte> objectAsByteMapper = new Map1<Statement, Byte>() {
275            @Override
276            public Byte map1(Statement x) {
277                try {
278                    Literal l = x.getLiteral();
279                    return getByte(l);
280                } catch (Exception e) {
281                    log.warn("Could not convert statement " + x + "to Byte");
282                    return null;
283                }
284            }
285        };
286    
287        public static final Map1<Statement, Character> objectAsCharacterMapper = new Map1<Statement, Character>() {
288            @Override
289            public Character map1(Statement x) {
290                try {
291                    Literal l = x.getLiteral();
292                    return getCharacter(l);
293                } catch (Exception e) {
294                    log.warn("Could not convert statement " + x + "to Character");
295                    return null;
296                }
297            }
298        };
299    
300        public static final Map1<Statement, Double> objectAsDoubleMapper = new Map1<Statement, Double>() {
301            @Override
302            public Double map1(Statement x) {
303                try {
304                    Literal l = x.getLiteral();
305                    return getDouble(l);
306                } catch (Exception e) {
307                    log.warn("Could not convert statement " + x + "to Double");
308                    return null;
309                }
310            }
311        };
312    
313        public static final Map1<Statement, Float> objectAsFloatMapper = new Map1<Statement, Float>() {
314            @Override
315            public Float map1(Statement x) {
316                try {
317                    Literal l = x.getLiteral();
318                    return getFloat(l);
319                } catch (Exception e) {
320                    log.warn("Could not convert statement " + x + "to Float");
321                    return null;
322                }
323            }
324        };
325    
326        public static final Map1<Statement, Integer> objectAsIntegerMapper = new Map1<Statement, Integer>() {
327            @Override
328            public Integer map1(Statement x) {
329                try {
330                    Literal l = x.getLiteral();
331                    return getInteger(l);
332                } catch (Exception e) {
333                    log.warn("Could not convert statement " + x + "to Integer");
334                    return null;
335                }
336            }
337        };
338    
339        public static final Map1<Statement, Long> objectAsLongMapper = new Map1<Statement, Long>() {
340            @Override
341            public Long map1(Statement x) {
342                try {
343                    Literal l = x.getLiteral();
344                    return getLong(l);
345                } catch (Exception e) {
346                    log.warn("Could not convert statement " + x + "to Long");
347                    return null;
348                }
349            }
350        };
351    
352        public static final Map1<Statement, Short> objectAsShortMapper = new Map1<Statement, Short>() {
353            @Override
354            public Short map1(Statement x) {
355                try {
356                    Literal l = x.getLiteral();
357                    return getShort(l);
358                } catch (Exception e) {
359                    log.warn("Could not convert statement " + x + "to Short");
360                    return null;
361                }
362            }
363        };
364    
365        public static final Map1<Statement, String> objectAsStringMapper = new Map1<Statement, String>() {
366            @Override
367            public String map1(Statement x) {
368                if (x instanceof Statement)
369                    return x.getString();
370                return null;
371            }
372        };
373    
374        public static final Map1<Statement, Calendar> objectAsCalendarMapper = new Map1<Statement, Calendar>() {
375            @Override
376            public Calendar map1(Statement x) {
377                try {
378                    Literal l = x.getLiteral();
379                    return getCalendar(l);
380                } catch (Exception e) {
381                    log.warn("Could not convert statement " + x + "to Calendar");
382                    return null;
383                }
384            }
385        };
386    
387        public static final Map1<Statement, XSDDuration> objectAsXSDDurationMapper = new Map1<Statement, XSDDuration>() {
388            @Override
389            public XSDDuration map1(Statement x) {
390                try {
391                    Literal l = x.getLiteral();
392                    return getXSDDuration(l);
393                } catch (Exception e) {
394                    log.warn("Could not convert statement " + x + "to XsdDuration");
395                    return null;
396                }
397            }
398        };
399    
400        public static final Map1<Statement, XSDDateTime> objectAsXSDDateTimeMapper = new Map1<Statement, XSDDateTime>() {
401            @Override
402            public XSDDateTime map1(Statement x) {
403                try {
404                    Literal l = x.getLiteral();
405                    return getXSDDateTime(l);
406                } catch (Exception e) {
407                    log.warn("Could not convert statement " + x + "to XsdDateTime");
408                    return null;
409                }
410            }
411        };
412    
413    }