/** * personium.io * Modifications 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. * -------------------------------------------------- * This code is based on JsonFormatWriter.java of odata4j-core, and some modifications * for personium.io are applied by us. * -------------------------------------------------- * The copyright and the license text of the original code is as follows: */ /**************************************************************************** * Copyright (c) 2010 odata4j * * 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.odata; import java.io.Writer; import java.util.Iterator; import javax.ws.rs.core.UriInfo; import org.odata4j.core.OCollection; import org.odata4j.core.OComplexObject; import org.odata4j.core.OEntity; import org.odata4j.core.OEntityKey; import org.odata4j.core.OLink; import org.odata4j.core.OObject; import org.odata4j.core.OProperty; import org.odata4j.core.ORelatedEntitiesLinkInline; import org.odata4j.core.ORelatedEntityLinkInline; import org.odata4j.core.OSimpleObject; import org.odata4j.edm.EdmCollectionType; import org.odata4j.edm.EdmEntitySet; import org.odata4j.edm.EdmSimpleType; import org.odata4j.edm.EdmType; import org.odata4j.format.json.JsonFormatWriter; import org.odata4j.format.json.JsonWriter; import com.fujitsu.dc.core.rs.odata.AbstractODataResource; import com.fujitsu.dc.core.rs.odata.ODataResource; /** * DcJsonFormatWriterクラス. * @param <T> */ public abstract class DcJsonFormatWriter<T> extends JsonFormatWriter<T> { /** * "results". */ protected static final String RESULTS_PROPERTY = "results"; /** * コンストラクタ. * @param jsonpCallback コールバック */ public DcJsonFormatWriter(String jsonpCallback) { super(jsonpCallback); } @Override public void write(UriInfo uriInfo, Writer w, T target) { JsonWriter jw = new DcJsonWriter(w); if (getJsonpCallback() != null) { jw.startCallback(getJsonpCallback()); } jw.startObject(); jw.writeName("d"); writeContent(uriInfo, jw, target); jw.endObject(); if (getJsonpCallback() != null) { jw.endCallback(); } } @Override protected void writeOEntity(UriInfo uriInfo, JsonWriter jw, OEntity oe, EdmEntitySet ees, boolean isResponse) { jw.startObject(); String baseUri = null; if (isResponse && null != oe.getEntityType()) { baseUri = uriInfo.getBaseUri().toString(); jw.writeName("__metadata"); jw.startObject(); String absId = baseUri + getEntityRelId(oe); OEntityWrapper oew = (OEntityWrapper) oe; String etag = ODataResource.renderEtagHeader(oew.getEtag()); jw.writeName("uri"); jw.writeString(absId); // etagを返却する jw.writeSeparator(); jw.writeName("etag"); jw.writeString(etag); jw.writeSeparator(); jw.writeName("type"); jw.writeString(oe.getEntityType().getFullyQualifiedTypeName()); jw.endObject(); jw.writeSeparator(); } writeOProperties(jw, oe.getProperties()); writeLinks(jw, oe, uriInfo, isResponse); jw.endObject(); } @Override protected void writeResponseLink(JsonWriter jw, OLink link, OEntity oe, UriInfo uriInfo) { jw.writeSeparator(); jw.writeName(link.getTitle()); if (link.isInline()) { if (link.isCollection()) { jw.startArray(); if (((ORelatedEntitiesLinkInline) link).getRelatedEntities() != null) { boolean isFirstInlinedEntity = true; for (OEntity re : ((ORelatedEntitiesLinkInline) link).getRelatedEntities()) { if (isFirstInlinedEntity) { isFirstInlinedEntity = false; } else { jw.writeSeparator(); } writeOEntity(uriInfo, jw, re, re.getEntitySet(), true); } } jw.endArray(); } else { OEntity re = ((ORelatedEntityLinkInline) link).getRelatedEntity(); if (re == null) { jw.writeNull(); } else { writeOEntity(uriInfo, jw, re, re.getEntitySet(), true); } } } else { // deferred jw.startObject(); jw.writeName("__deferred"); jw.startObject(); String absId = uriInfo.getBaseUri().toString() + getEntityRelId(oe); jw.writeName("uri"); // jw.writeString(absId + "/" + link.getTitle()); jw.endObject(); jw.endObject(); } } @Override protected void writeProperty(JsonWriter jw, OProperty<?> prop) { jw.writeName(prop.getName()); if (prop.getValue() != null && AbstractODataResource.isDummy(prop.getValue())) { writeValue(jw, prop.getType(), null); } else { writeValue(jw, prop.getType(), prop.getValue()); } } /** * Collectionに対する応答データ作成. * @param jw JsonWriter * @param type コレクションタイプ * @param coll OCollection */ @SuppressWarnings("rawtypes") @Override protected void writeCollection(JsonWriter jw, EdmCollectionType type, OCollection<? extends OObject> coll) { // Ocollectionの応答データ作成時に[results]が追加されてしまうためオーバーライド jw.startArray(); boolean isFirst = true; Iterator<? extends OObject> iter = coll.iterator(); while (iter.hasNext()) { OObject obj = iter.next(); if (isFirst) { isFirst = false; } else { jw.writeSeparator(); } if (obj instanceof OComplexObject) { writeComplexObject(jw, obj.getType().getFullyQualifiedTypeName(), ((OComplexObject) obj).getProperties()); } else if (obj instanceof OSimpleObject) { writeValue(jw, obj.getType(), ((OSimpleObject) obj).getValue()); } } jw.endArray(); } /** * EntityRelIdを返却する. * @param oe OEntity * @return EntityRelId */ public static String getEntityRelId(OEntity oe) { return getEntityRelId(oe.getEntitySet(), oe.getEntityKey()); } /** * EntityRelIdを返却する. * @param entitySet エンティティセット * @param entityKey エンティティキー * @return EntityRelId */ public static String getEntityRelId(EdmEntitySet entitySet, OEntityKey entityKey) { String key = AbstractODataResource.replaceDummyKeyToNull(entityKey.toKeyString()); return entitySet.getName() + key; } /** * JSONのフィールド値をデータ型に合わせて出力する. * @param jw 出力先ライター * @param type フィールドのデータ型 * @param pvalue フィールド値 */ @Override protected void writeValue(JsonWriter jw, EdmType type, Object pvalue) { if (pvalue != null && type.equals(EdmSimpleType.DOUBLE)) { ((DcJsonWriter) jw).writeNumber((Double) pvalue); } else { super.writeValue(jw, type, pvalue); } } }