blob: 82d16d9a845f4e988ad16959b65fde880406ffac [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sling.jcr.contentparser.impl;
import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.util.ISO8601;
import org.apache.sling.jcr.contentparser.ParseException;
import org.apache.sling.jcr.contentparser.ParserOptions;
import java.lang.reflect.Array;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.json.JsonObject;
/**
* Helper parsing logic based on parser options.
*/
class ParserHelper {
static final String JCR_PRIMARYTYPE = "jcr:primaryType";
static final String ECMA_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z";
static final Locale DATE_FORMAT_LOCALE = Locale.US;
private final ParserOptions options;
private final DateTimeFormatter calendarFormat;
public ParserHelper(ParserOptions options) {
this.options = options;
if (options.isDetectCalendarValues()) {
this.calendarFormat = DateTimeFormatter.ofPattern(ECMA_DATE_FORMAT, DATE_FORMAT_LOCALE);
}
else {
this.calendarFormat = null;
}
}
public void ensureDefaultPrimaryType(Map<String, Object> map) {
String defaultPrimaryType = options.getDefaultPrimaryType();
if (defaultPrimaryType != null) {
if (!map.containsKey(JCR_PRIMARYTYPE)) {
map.put(JCR_PRIMARYTYPE, defaultPrimaryType);
}
}
}
public Calendar tryParseCalendar(String value) {
if (options.isDetectCalendarValues() && !StringUtils.isBlank(value)) {
// 1st try: parse with ISO-8601 format first
Calendar calendar = ISO8601.parse(value);
if (calendar != null) {
return calendar;
}
// 2nd try: parse with ECMA date format which is used by Sling GET servlet
calendar = Calendar.getInstance();
try {
final OffsetDateTime offsetDateTime = OffsetDateTime.parse(value, calendarFormat);
final Instant instant = offsetDateTime.toInstant();
calendar.setTime(Date.from(instant));
calendar.setTimeZone(TimeZone.getTimeZone(offsetDateTime.getOffset()));
return calendar;
} catch (DateTimeParseException ex) {
// ignore
}
}
return null;
}
public boolean ignoreProperty(String propertyName) {
return ignoreNames(options.getIgnorePropertyNames(), propertyName);
}
public boolean ignoreResource(String resourceName) {
return ignoreNames(options.getIgnoreResourceNames(), resourceName);
}
private boolean ignoreNames(Set<String> names, String name) {
return names != null && names.contains(name);
}
public String cleanupPropertyName(String propertyName) {
Set<String> prefixes = options.getRemovePropertyNamePrefixes();
if (prefixes != null) {
for (String prefix : prefixes) {
if (StringUtils.startsWith(propertyName, prefix)) {
return StringUtils.substringAfter(propertyName, prefix);
}
}
}
return propertyName;
}
public Object convertSingleTypeArray(Object[] values) {
if (values.length == 0) {
return values;
}
Class<?> itemType = null;
for (Object value : values) {
if (value == null) {
throw new ParseException("Multivalue array must not contain null values.");
}
if (value instanceof Map || value instanceof JsonObject) {
throw new ParseException("Multivalue array must not contain maps/objects.");
}
if (itemType == null) {
itemType = value.getClass();
}
else if (itemType != value.getClass()) {
throw new ParseException("Multivalue array must not contain values with different types "
+ "(" + itemType.getName() + ", " + value.getClass().getName() + ").");
}
}
Object convertedArray = Array.newInstance(itemType, values.length);
for (int i=0; i<values.length; i++) {
Array.set(convertedArray, i, values[i]);
}
return convertedArray;
}
public String concatenatePath(String parentPath, String name) {
if (StringUtils.endsWith(parentPath, "/")) {
return parentPath + name;
}
else {
return parentPath + "/" + name;
}
}
}