/**
* 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.model.impl.es.odata;
import java.util.Map;
import org.odata4j.edm.EdmEntityType;
import org.odata4j.edm.EdmProperty;
import org.odata4j.edm.EdmProperty.CollectionKind;
import org.odata4j.edm.EdmSimpleType;
import org.odata4j.expression.CommonExpression;
import org.odata4j.expression.EntitySimpleProperty;
import org.odata4j.expression.OrderByExpression;
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.model.impl.es.doc.OEntityDocHandler;
/**
* UserDataのelasticsearchクエリハンドラー.
*/
public class UserDataQueryHandler extends EsQueryHandler implements ODataQueryHandler {
/**
* Property/ComplexTypePropertyとAliasのマッピングデータ.
*/
private Map<String, PropertyAlias> propertyAliasMap;
/**
* コンストラクタ.
* @param entityType エンティティタイプ
* @param map プロパティ名とAliasのMap
*/
public UserDataQueryHandler(EdmEntityType entityType, Map<String, PropertyAlias> map) {
super(entityType);
this.propertyAliasMap = map;
}
@Override
public void visit(OrderByExpression expr) {
log.debug("visit(OrderByExpression expr)");
if (!(expr.getExpression() instanceof EntitySimpleProperty)) {
throw DcCoreException.OData.FILTER_PARSE_ERROR;
}
// ソート対象のプロパティスキーマを取得する
String name = ((EntitySimpleProperty) expr.getExpression()).getPropertyName();
EdmProperty edmProperty = this.entityType.findProperty(name);
// プロパティが存在しない場合はソート条件に追加しない
if (edmProperty == null) {
return;
}
// 配列に対するソート指定時はエラーとする
if (CollectionKind.List.equals(edmProperty.getCollectionKind())) {
throw DcCoreException.OData.CANNOT_SPECIFY_THE_LIST_TYPE_TO_ORDERBY;
}
if (!isUntouched(name, edmProperty)) {
super.visit(expr);
} else {
// 文字列の場合
String key = getSearchKey(expr.getExpression(), true);
String orderOption = getOrderOption(expr.getDirection());
Map<String, Object> orderByValue = null;
if (DcCoreConfig.getOrderbySortOrder()) {
orderByValue = UserDataQueryHandlerHelper.getOrderByValueForMissingFirst(orderOption, key);
} else {
orderByValue = UserDataQueryHandlerHelper.getOrderByValue(orderOption, key);
}
this.orderBy.put(UserDataQueryHandlerHelper.getOrderByKey(key), orderByValue);
}
}
@Override
protected String getSearchKey(CommonExpression expr, Boolean isUntouched) {
// 検索キーとして設定を行う
String name = ((EntitySimpleProperty) expr).getPropertyName();
EdmProperty edmProperty = this.entityType.findProperty(name);
// published, updated
if (Common.P_PUBLISHED.getName().equals(name)) {
return OEntityDocHandler.KEY_PUBLISHED;
} else if (Common.P_UPDATED.getName().equals(name)) {
return OEntityDocHandler.KEY_UPDATED;
}
// s.フィールドフィールドを検索する
String fieldPrefix = OEntityDocHandler.KEY_STATIC_FIELDS;
// キー名をAliasに変換する
String key = "Name='" + name + "',_EntityType.Name='" + this.entityType.getName() + "'";
String keyName = getAlias(key, this.entityType.getName());
if (keyName == null) {
keyName = name;
}
// 型によってサフィックス(検索対象フィールド)変更する
String suffix = getSuffix(edmProperty);
if (isUntouched) {
return fieldPrefix + "." + keyName + "." + suffix;
} else {
return fieldPrefix + "." + keyName;
}
}
/**
* untouchedフィールドを使用すべき項目かどうかを判定する.
* @param name プロパティ名
* @param edmProperty プロパティのスキーマ情報
* @return untouchedフィールドを使用すべき場合はtrue、そうでない場合はfalse
*/
private boolean isUntouched(String name, EdmProperty edmProperty) {
if (Common.P_ID.getName().equals(name)
|| Common.P_PUBLISHED.getName().equals(name)
|| Common.P_UPDATED.getName().equals(name)
|| EdmSimpleType.SINGLE.equals(edmProperty.getType())
|| EdmSimpleType.DOUBLE.equals(edmProperty.getType())
|| EdmSimpleType.INT32.equals(edmProperty.getType())) {
return false;
}
return true;
}
private String getSuffix(EdmProperty edmProperty) {
String suffix = "untouched";
if (edmProperty != null) {
if (EdmSimpleType.SINGLE.equals(edmProperty.getType())
|| EdmSimpleType.DOUBLE.equals(edmProperty.getType())) {
suffix = "double";
} else if (EdmSimpleType.INT32.equals(edmProperty.getType())) {
suffix = "long";
}
}
return suffix;
}
@Override
protected String getFieldName(String prop) {
String key = "Name='" + prop + "',_EntityType.Name='" + this.entityType.getName() + "'";
String keyName = getAlias(key, this.entityType.getName());
return OEntityDocHandler.KEY_STATIC_FIELDS + "." + keyName;
}
/**
* プロパティのAlias名をマッピングデータから取得する.
* @param key マッピングデータの検索キー
* @param propertyName プロパティ名
* @return Alias名
*/
private String getAlias(String key, String propertyName) {
if (propertyName.startsWith("_")) {
return propertyName;
}
PropertyAlias alias = this.propertyAliasMap.get(key);
if (alias != null) {
return alias.getAlias();
}
return null;
}
}