com.sap.cds.adapter.odata.v4.metadata.provider.DefaultEdmxProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cds-adapter-odata-v4 Show documentation
Show all versions of cds-adapter-odata-v4 Show documentation
OData V4 adapter for CDS Services Java
/**************************************************************************
* (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
**************************************************************************/
package com.sap.cds.adapter.odata.v4.metadata.provider;
import java.io.InputStream;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
import com.sap.cds.adapter.odata.v4.metadata.MetadataInfo;
import com.sap.cds.services.environment.CdsProperties.ODataV4;
import com.sap.cds.services.request.RequestContext;
import com.sap.cds.services.runtime.CdsRuntime;
import com.sap.cds.services.utils.CdsErrorStatuses;
import com.sap.cds.services.utils.ErrorStatusException;
import com.sap.cds.services.utils.LocaleUtils;
/**
* Default implementation of the EDMX parsing. It looks for the EDMX in the applications resource folder.
*/
public class DefaultEdmxProvider implements OlingoAwareEdmxV4Provider {
// base path for unlocalized EDMX files
private final static String UNLOCALIZED_BASE_PATH = "edmx/odata/v4";
private final Map metadataInfoMap = new ConcurrentHashMap<>();
private final CdsRuntime runtime;
private String basePath = "edmx";
public DefaultEdmxProvider(CdsRuntime runtime) {
this.runtime = runtime;
ODataV4 config = runtime.getEnvironment().getCdsProperties().getOdataV4();
if(getClass().getClassLoader().getResource(config.getEdmxPath()) != null) {
this.basePath = config.getEdmxPath();
} else if (config.getLazyI18n().isEnabled() && getClass().getClassLoader().getResource(UNLOCALIZED_BASE_PATH) != null) {
this.basePath = UNLOCALIZED_BASE_PATH;
}
}
@Override
public String getETag(String serviceName) {
return getMetadataInfo(serviceName).getETag();
}
@Override
public InputStream getEdmx(String serviceName) {
return getMetadataInfo(serviceName).getEdmx();
}
@Override
public CsdlEdmProvider getEdmProvider(String serviceName) {
return getMetadataInfo(serviceName).getEdmProvider();
}
MetadataInfo getMetadataInfo(String serviceName) {
Locale locale = RequestContext.getCurrent(runtime).getParameterInfo().getLocale();
MetadataInfo info = getMetadataInfo(serviceName, locale);
if(locale != null && info.isEmpty()) {
// retry without locale
info = getMetadataInfo(serviceName, null);
}
if (info.isEmpty()) {
throw new ErrorStatusException(CdsErrorStatuses.INVALID_METADATA, serviceName);
}
return info;
}
private MetadataInfo getMetadataInfo(String unlocalizedServiceName, Locale locale) {
String serviceName;
if(locale != null) {
String language = LocaleUtils.getLocaleForBundle(locale).toString();
serviceName = unlocalizedServiceName + "_" + language;
} else {
serviceName = unlocalizedServiceName;
}
return metadataInfoMap.computeIfAbsent(serviceName, (key) -> {
try {
String resourcePathToEdmx = basePath + "/" + serviceName + ".xml"; // getResourceAsStream accepts unnormalized paths containing e.g. "//"
try(InputStream resource = getClass().getClassLoader().getResourceAsStream(resourcePathToEdmx)) {
if (resource != null) {
return MetadataInfo.create(serviceName, resource.readAllBytes(), runtime);
}
}
return MetadataInfo.create(serviceName, null, runtime);
} catch (Exception e) {
throw new ErrorStatusException(CdsErrorStatuses.INVALID_METADATA, serviceName, e);
}
});
}
}