metadata-profile-form-build.../src/main/java/org/gcube/portlets/widgets/mpformbuilder/server/MetadataDiscovery.java

400 lines
14 KiB
Java

package org.gcube.portlets.widgets.mpformbuilder.server;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import javax.xml.bind.JAXBException;
import org.gcube.common.metadataprofilediscovery.MetadataProfileReader;
import org.gcube.common.metadataprofilediscovery.bean.MetadataProfile;
import org.gcube.common.metadataprofilediscovery.jaxb.MetadataField;
import org.gcube.common.metadataprofilediscovery.jaxb.MetadataFormat;
import org.gcube.common.metadataprofilediscovery.jaxb.MetadataGrouping;
import org.gcube.common.metadataprofilediscovery.jaxb.MetadataTagging;
import org.gcube.common.metadataprofilediscovery.jaxb.MetadataValidator;
import org.gcube.common.metadataprofilediscovery.jaxb.MetadataVocabulary;
import org.gcube.common.metadataprofilediscovery.jaxb.NamespaceCategory;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portlets.widgets.mpformbuilder.server.util.WsUtil;
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.CategoryWrapper;
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.DataTypeWrapper;
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.FieldAsGroup;
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.FieldAsTag;
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.MetaDataProfileBean;
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.MetadataFieldWrapper;
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.TaggingGroupingValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class MetadataDiscovery.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Sep 30, 2020
*/
public class MetadataDiscovery {
private static final Logger LOG = LoggerFactory.getLogger(MetadataDiscovery.class);
/**
* Gets the profiles names.
*
* @param scope the scope
* @param genericResourceSecondaryType the generic resource secondary type in
* which discover "gCube Metadata Profiles"
* @return the profiles names
* @throws Exception the exception
*/
public static List<String> getProfilesNames(String scope, String genericResourceSecondaryType) throws Exception {
String currentContext = ScopeProvider.instance.get();
try {
ScopeProvider.instance.set(scope);
List<String> toReturn = new ArrayList<String>();
MetadataProfileReader reader = new MetadataProfileReader(genericResourceSecondaryType);
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
if (listProfiles != null && !listProfiles.isEmpty()) {
for (MetadataProfile profile : listProfiles) {
toReturn.add(profile.getName());
}
}
return toReturn;
} catch (Exception e) {
LOG.error("Failed to fetch profiles", e);
} finally {
ScopeProvider.instance.set(currentContext);
}
return null;
}
/**
* Gets the metadata profiles list.
*
* @param scope the scope
* @param gRSecondaryType the g R secondary type
* @param resourceName the resource name
* @return the metadata profiles list
* @throws Exception the exception
*/
public static List<MetaDataProfileBean> getMetadataProfilesList(String scope, String gRSecondaryType, String resourceName)
throws Exception {
List<MetaDataProfileBean> beans = new ArrayList<MetaDataProfileBean>();
LOG.debug("Discovering into scope " + scope);
String currentContext = ScopeProvider.instance.get();
try {
ScopeProvider.instance.set(scope);
// TODO two reset methods could be added to force the reader to read again these
// information (after a while)
MetadataProfileReader reader = new MetadataProfileReader(gRSecondaryType, resourceName);
List<MetadataProfile> profiles = reader.getListOfMetadataProfiles();
prettyPrintProfiles(profiles);
LOG.info("Profiles are " + profiles.size());
List<NamespaceCategory> categories = reader.getListOfNamespaceCategories();
if (categories == null)
categories = new ArrayList<NamespaceCategory>();
LOG.debug("All Categories are " + categories);
for (MetadataProfile profile : profiles) {
LOG.debug("Wrapping profile with name " + profile.getName() + " and type " + profile.getMetadataType());
MetadataFormat metadata = reader.getMetadataFormatForMetadataProfile(profile);
MetaDataProfileBean bean = toMetaDataProfileBean(metadata, categories, profile.getName());
beans.add(bean);
if(!WsUtil.isWithinPortal()) {
LOG.info("DEV MODE ENABLED - Out of portal!");
randomizeCurrentValues(bean.getMetadataFields());
}
}
prettyPrintList(beans);
LOG.info("Returning " + beans.size() + " profile/s");
} catch (Exception e) {
LOG.error("Error while retrieving metadata beans ", e);
throw new Exception("Failed to parse Types: " + e.getMessage());
} finally {
ScopeProvider.instance.set(currentContext);
}
return beans;
}
private static void randomizeCurrentValues(List<MetadataFieldWrapper> listFields) {
LOG.info("DEV MODE ENABLED - Generationg random current value");
for (MetadataFieldWrapper metadataFieldWrapper : listFields) {
DataTypeWrapper dtw = metadataFieldWrapper.getType();
switch (dtw) {
case Boolean:
metadataFieldWrapper.setCurrentValue(Boolean.FALSE.toString());
break;
case Number:
metadataFieldWrapper.setCurrentValue(new Random().nextInt()+"");
break;
case String:
case Text:
metadataFieldWrapper.setCurrentValue("Text "+UUID.randomUUID());
break;
default:
break;
}
}
}
/**
* Gets the metadata profiles list.
*
* @param scope the scope
* @param gRSecondaryType the g R secondary type
* @return the metadata profiles list
* @throws Exception the exception
*/
public static List<MetaDataProfileBean> getMetadataProfilesList(String scope, String gRSecondaryType)
throws Exception {
List<MetaDataProfileBean> beans = new ArrayList<MetaDataProfileBean>();
LOG.debug("Discovering into scope " + scope);
String currentContext = ScopeProvider.instance.get();
try {
ScopeProvider.instance.set(scope);
// TODO two reset methods could be added to force the reader to read again these
// information (after a while)
MetadataProfileReader reader = new MetadataProfileReader(gRSecondaryType);
List<MetadataProfile> profiles = reader.getListOfMetadataProfiles();
prettyPrintProfiles(profiles);
LOG.info("Profiles are " + profiles.size());
List<NamespaceCategory> categories = reader.getListOfNamespaceCategories();
if (categories == null)
categories = new ArrayList<NamespaceCategory>();
LOG.debug("All Categories are " + categories);
for (MetadataProfile profile : profiles) {
LOG.debug("Wrapping profile with name " + profile.getName() + " and type " + profile.getMetadataType());
MetadataFormat metadata = reader.getMetadataFormatForMetadataProfile(profile);
MetaDataProfileBean bean = toMetaDataProfileBean(metadata, categories, profile.getName());
beans.add(bean);
}
prettyPrintList(beans);
LOG.info("Returning " + beans.size() + " profile/s");
} catch (Exception e) {
LOG.error("Error while retrieving metadata beans ", e);
throw new Exception("Failed to parse Types: " + e.getMessage());
} finally {
ScopeProvider.instance.set(currentContext);
}
return beans;
}
private static void prettyPrintProfiles(List<MetadataProfile> profiles) {
if(LOG.isDebugEnabled() && profiles!=null) {
LOG.debug("Pretty print list of profiles: ");
for (MetadataProfile profile : profiles) {
LOG.debug(profile.toString());
}
}
}
private static void prettyPrintList(List<MetaDataProfileBean> beans) {
if(LOG.isDebugEnabled() && beans!=null) {
LOG.debug("Pretty print list of beans: ");
for (MetaDataProfileBean metaDataProfileBean : beans) {
LOG.debug(metaDataProfileBean.toString());
}
}
}
/**
* Gets the metadata profile.
*
* @param metadataProfileStream the metadata profile stream
* @return the metadata profile
* @throws JAXBException the JAXB exception
*/
public static MetaDataProfileBean getMetadataProfile(InputStream metadataProfileStream) throws JAXBException {
MetadataFormat metadata = MetadataProfileReader.toMetadataFormat(metadataProfileStream);
return toMetaDataProfileBean(metadata, null, null);
}
/**
* To meta data profile bean.
*
* @param metadata the metadata
* @param categories the categories
* @param profileName the profile name
* @return the meta data profile bean
*/
private static MetaDataProfileBean toMetaDataProfileBean(MetadataFormat metadata, List<NamespaceCategory> categories, String profileName){
String type = metadata.getType();
String title = profileName!=null?profileName:type;
List<MetadataField> fields = metadata.getMetadataFields();
// we need to wrap the list of metadata and categories
List<MetadataFieldWrapper> fieldsWrapper = new ArrayList<MetadataFieldWrapper>(
fields != null ? fields.size() : 0);
List<CategoryWrapper> categoriesWrapper = new ArrayList<CategoryWrapper>(categories.size());
Map<String, CategoryWrapper> idToCategory = new HashMap<String, CategoryWrapper>(categories.size());
// manage the categories
for (NamespaceCategory category : categories) {
CategoryWrapper categoryWrapped = new CategoryWrapper(category.getId(), category.getTitle(),
category.getDescription());
categoriesWrapper.add(categoryWrapped);
idToCategory.put(category.getId(), categoryWrapped);
}
// also evaluate the fields for each category
Map<String, List<MetadataFieldWrapper>> fieldsPerCategory = new HashMap<String, List<MetadataFieldWrapper>>(
categoriesWrapper.size());
// manage the fields
if (fields != null)
for (MetadataField metadataField : fields) {
MetadataFieldWrapper wrapperObj = new MetadataFieldWrapper();
wrapperObj.setFieldNameFromCategory(metadataField.getCategoryFieldQName());
try {
wrapperObj.setType(DataTypeWrapper.valueOf(metadataField.getDataType().toString()));
}catch (Exception e) {
// TODO: handle exception
LOG.warn("No valueOf to DataTypeWrapper for value "+metadataField.getDataType().toString() +", using default String");
wrapperObj.setType(DataTypeWrapper.String);
}
wrapperObj.setDefaultValue(metadataField.getDefaultValue());
wrapperObj.setFieldId(metadataField.getFieldId());
wrapperObj.setFieldName(metadataField.getFieldName());
wrapperObj.setMandatory(metadataField.getMandatory());
wrapperObj.setNote(metadataField.getNote());
MetadataValidator validator = metadataField.getValidator();
LOG.debug(metadataField.getFieldName() +" validator is: "+validator);
if (validator != null)
wrapperObj.setValidator(validator.getRegularExpression());
MetadataVocabulary vocabulary = metadataField.getVocabulary();
if (vocabulary != null) {
wrapperObj.setVocabulary(vocabulary.getVocabularyFields());
wrapperObj.setMultiSelection(vocabulary.isMultiSelection());
}
MetadataTagging tagging = metadataField.getTagging();
if (tagging != null) {
FieldAsTag tag = new FieldAsTag();
tag.setCreate(tagging.getCreate());
tag.setSeparator(tagging.getSeparator());
tag.setTaggingValue(TaggingGroupingValue.valueOf(tagging.getTaggingValue().toString()));
wrapperObj.setAsTag(tag);
}
MetadataGrouping grouping = metadataField.getGrouping();
if (grouping != null) {
FieldAsGroup group = new FieldAsGroup();
group.setCreate(grouping.getCreate());
group.setPropagateUp(grouping.getPropagateUp());
group.setGroupingValue(
TaggingGroupingValue.valueOf(grouping.getGroupingValue().toString()));
wrapperObj.setAsGroup(group);
}
// set to which category this field belongs to and vice-versa
if (metadataField.getCategoryRef() != null) {
CategoryWrapper ownerCategory = idToCategory.get(metadataField.getCategoryRef());
if (ownerCategory == null) {
LOG.warn("A field with categoryref " + metadataField.getCategoryRef()
+ " has been found, but"
+ " such category is not defined within the namespaces");
} else {
wrapperObj.setOwnerCategory(ownerCategory);
List<MetadataFieldWrapper> fieldsPerCategoryN = fieldsPerCategory
.get(metadataField.getCategoryRef());
if (fieldsPerCategoryN == null)
fieldsPerCategoryN = new ArrayList<MetadataFieldWrapper>();
fieldsPerCategoryN.add(wrapperObj);
fieldsPerCategory.put(metadataField.getCategoryRef(), fieldsPerCategoryN);
// instead of re-looping on the fieldsPerCategory map later, just set this
// potentially partial list
ownerCategory.setFieldsForThisCategory(fieldsPerCategoryN);
}
}
// Added by Francesco
int maxOccurs = 1; // Default value is 1. A field should occur once.
if (metadataField.getMaxOccurs() != null) {
try {
// the field can appear an unlimited number of times.
if (metadataField.getMaxOccurs().equals("*")) {
maxOccurs = Integer.MAX_VALUE;
} else {
// the field must appear N times;
maxOccurs = Integer.parseInt(metadataField.getMaxOccurs());
}
} catch (Exception e) {
// silent
}
wrapperObj.setMaxOccurs(maxOccurs);
}
fieldsWrapper.add(wrapperObj);
}
// filter the categories without children here
Iterator<CategoryWrapper> categoryToRemoveIT = categoriesWrapper.iterator();
while (categoryToRemoveIT.hasNext()) {
CategoryWrapper categoryWrapper = (CategoryWrapper) categoryToRemoveIT.next();
if (categoryWrapper.getFieldsForThisCategory() == null)
categoryToRemoveIT.remove();
}
return new MetaDataProfileBean(type, title, fieldsWrapper, categoriesWrapper);
}
}