/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed 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 com.fujitsu.dc.core.rs.odata; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ws.rs.core.MultivaluedMap; import org.odata4j.expression.BoolCommonExpression; import org.odata4j.expression.EntitySimpleProperty; import org.odata4j.expression.OrderByExpression; import org.odata4j.producer.InlineCount; import org.odata4j.producer.QueryInfo; import org.odata4j.producer.resources.OptionsQueryParser; import com.fujitsu.dc.core.DcCoreConfig; import com.fujitsu.dc.core.DcCoreException; import com.fujitsu.dc.core.model.ctl.Common; import com.fujitsu.dc.core.odata.DcOptionsQueryParser; import com.sun.jersey.api.uri.UriComponent; /** * クエリをパースして値を返却するクラス. */ public class QueryParser { private QueryParser() { } /** * skipクエリをパースして値を返却する. * @param query クエリ文字列("$skip=VALUE") * @return クエリで指定された値 */ public static Integer parseSkipQuery(String query) { Integer skip = null; try { skip = OptionsQueryParser.parseTop(query); } catch (Exception e) { throw DcCoreException.OData.QUERY_PARSE_ERROR_WITH_PARAM.params("$skip").reason(e); } if (skip != null && (0 > skip || skip > DcCoreConfig.getSkipQueryMaxSize())) { // Integerでそのまま値を返却すると、カンマが付くため、文字列でエラーメッセージを返却する throw DcCoreException.OData.QUERY_INVALID_ERROR.params("$skip", skip.toString()); } return skip; } /** * topクエリをパースして値を返却する. * @param query クエリ文字列("$top=VALUE") * @return クエリで指定された値 */ public static Integer parseTopQuery(String query) { Integer top = null; try { top = OptionsQueryParser.parseTop(query); } catch (Exception e) { throw DcCoreException.OData.QUERY_PARSE_ERROR_WITH_PARAM.params("$top").reason(e); } if (top != null && (0 > top || top > DcCoreConfig.getTopQueryMaxSize())) { // Integerでそのまま値を返却すると、カンマが付くため、文字列でエラーメッセージを返却する throw DcCoreException.OData.QUERY_INVALID_ERROR.params("$top", top.toString()); } return top; } /** * orderbyクエリをパースして値を返却する. * @param query クエリ文字列("$orderby=VALUE") * @return クエリで指定された値 */ public static List<OrderByExpression> parseOderByQuery(String query) { List<OrderByExpression> orderBy = null; try { if (query != null && query.equals("")) { throw DcCoreException.OData.ORDERBY_PARSE_ERROR; } orderBy = DcOptionsQueryParser.parseOrderBy(query); } catch (Exception e) { throw DcCoreException.OData.ORDERBY_PARSE_ERROR; } return orderBy; } /** * skiptokenクエリをパースして値を返却する. * @param query クエリ文字列("$skiptoken=VALUE") * @return クエリで指定された値 */ public static String parseSkipTokenQuery(String query) { String skipToken = null; try { skipToken = OptionsQueryParser.parseSkipToken(query); } catch (Exception e) { throw DcCoreException.OData.FILTER_PARSE_ERROR; } return skipToken; } /** * inlinecountクエリをパースして値を返却する. * @param query クエリ文字列("$inlinecount=VALUE") * @return クエリで指定された値 */ public static InlineCount parseInlinecountQuery(String query) { InlineCount inlineCount = null; if (query == null) { // デフォルト値の設定(__countなし) inlineCount = InlineCount.NONE; } else { // パースをして有効値以外が返却された場合はパースエラーとする inlineCount = OptionsQueryParser.parseInlineCount(query); if (inlineCount == null) { throw DcCoreException.OData.INLINECOUNT_PARSE_ERROR.params(query); } } return inlineCount; } /** * expandクエリをパースして値を返却する. * @param query クエリ文字列("$expand=VALUE") * @return クエリで指定された値 */ public static List<EntitySimpleProperty> parseExpandQuery(String query) { List<EntitySimpleProperty> expand = null; try { expand = DcOptionsQueryParser.parseExpand(query); } catch (Exception e) { throw DcCoreException.OData.EXPAND_PARSE_ERROR; } // $expandに指定されたプロパティ数の上限チェック if (expand != null && expand.size() > DcCoreConfig.getExpandPropertyMaxSizeForList()) { throw DcCoreException.OData.EXPAND_COUNT_LIMITATION_EXCEEDED; } return expand; } /** * selectクエリをパースして値を返却する. * @param query クエリ文字列("$select=VALUE") * @return クエリで指定された値 */ public static List<EntitySimpleProperty> parseSelectQuery(String query) { List<EntitySimpleProperty> select = null; if ("".equals(query)) { throw DcCoreException.OData.SELECT_PARSE_ERROR; } if (!"*".equals(query)) { try { select = DcOptionsQueryParser.parseSelect(query); } catch (Exception e) { throw DcCoreException.OData.SELECT_PARSE_ERROR.reason(e); } } return select; } /** * filterクエリをパースして値を返却する. * @param query クエリ文字列("$filter=VALUE") * @return クエリで指定された値 */ public static BoolCommonExpression parseFilterQuery(String query) { BoolCommonExpression filter = null; try { filter = DcOptionsQueryParser.parseFilter(query); } catch (Exception e) { throw DcCoreException.OData.FILTER_PARSE_ERROR.reason(e); } return filter; } /** * qクエリをパースする. * @param fullTextSearchKeyword クエリ文字列("q=VALUE") */ public static void parseFullTextSearchQuery(String fullTextSearchKeyword) { // 全文検索クエリqのバリデート if (fullTextSearchKeyword != null && (fullTextSearchKeyword.getBytes().length < 1 || fullTextSearchKeyword.getBytes().length > Common.MAX_Q_VALUE_LENGTH)) { throw DcCoreException.OData.QUERY_INVALID_ERROR.params("q", fullTextSearchKeyword); } } /** * QueryInfoを生成. * @param requestQuery requestQuery * @return requestQuery */ public static QueryInfo createQueryInfo(String requestQuery) { MultivaluedMap<String, String> queryParams = UriComponent.decodeQuery(requestQuery, true); Integer top = QueryParser.parseTopQuery(queryParams.getFirst("$top")); Integer skip = QueryParser.parseSkipQuery(queryParams.getFirst("$skip")); BoolCommonExpression filter = QueryParser.parseFilterQuery(queryParams.getFirst("$filter")); List<EntitySimpleProperty> select = QueryParser.parseSelectQuery(queryParams.getFirst("$select")); List<EntitySimpleProperty> expand = QueryParser.parseExpandQuery(queryParams.getFirst("$expand")); InlineCount inlineCount = QueryParser.parseInlinecountQuery(queryParams.getFirst("$inlinecount")); String skipToken = QueryParser.parseSkipTokenQuery(queryParams.getFirst("$skiptoken")); List<OrderByExpression> orderBy = QueryParser.parseOderByQuery(queryParams.getFirst("$orderby")); parseFullTextSearchQuery(queryParams.getFirst("q")); // $expand指定時は$topの最大値が変わるためチェックする if (expand != null && top != null && top > DcCoreConfig.getTopQueryMaxSizeWithExpand()) { // Integerでそのまま値を返却すると、カンマが付くため、文字列でエラーメッセージを返却する throw DcCoreException.OData.QUERY_INVALID_ERROR.params("$top", top.toString()); } Map<String, String> customOptions = new HashMap<String, String>(); customOptions.put("q", queryParams.getFirst("q")); QueryInfo queryInfo = new QueryInfo( inlineCount, top, skip, filter, orderBy, skipToken, customOptions, expand, select); return queryInfo; } }