\r
package eu.etaxonomy.cdm.api.service;\r
\r
+import java.io.IOException;\r
import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
import java.util.List;\r
+import java.util.Map;\r
import java.util.Set;\r
import java.util.UUID;\r
+import java.util.stream.Collectors;\r
\r
+import org.apache.http.HttpException;\r
import org.springframework.beans.factory.annotation.Autowired;\r
import org.springframework.stereotype.Service;\r
import org.springframework.transaction.annotation.Transactional;\r
import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;\r
import eu.etaxonomy.cdm.api.service.config.MediaDeletionConfigurator;\r
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;\r
+import eu.etaxonomy.cdm.api.service.media.MediaInfoFactory;\r
import eu.etaxonomy.cdm.api.service.pager.Pager;\r
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;\r
+import eu.etaxonomy.cdm.common.media.CdmImageInfo;\r
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;\r
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
import eu.etaxonomy.cdm.model.common.CdmBase;\r
import eu.etaxonomy.cdm.model.location.NamedArea;\r
import eu.etaxonomy.cdm.model.media.Media;\r
import eu.etaxonomy.cdm.model.media.MediaRepresentation;\r
+import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;\r
import eu.etaxonomy.cdm.model.media.Rights;\r
+import eu.etaxonomy.cdm.model.metadata.CdmPreference;\r
+import eu.etaxonomy.cdm.model.metadata.PreferencePredicate;\r
+import eu.etaxonomy.cdm.model.metadata.PreferenceSubject;\r
import eu.etaxonomy.cdm.model.name.TaxonName;\r
import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;\r
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;\r
private ITaxonService taxonService;\r
@Autowired\r
private INameService nameService;\r
+ @Autowired\r
+ private IPreferenceService prefsService;\r
+ @Autowired\r
+ private MediaInfoFactory mediaInfoFactory; // FIXME define and use interface\r
\r
\r
@Override\r
return super.updateCachesImpl(clazz, stepSize, cacheStrategy, monitor);\r
}\r
\r
+ @Override\r
+ @Transactional(readOnly=false)\r
+ public DeleteResult delete(Set<UUID> mediaUuids, MediaDeletionConfigurator config) {\r
+ DeleteResult result = new DeleteResult();\r
+ for (UUID uuid:mediaUuids){\r
+ result.includeResult(delete(uuid, config));\r
+ }\r
+ return result;\r
+\r
+ }\r
+\r
@Override\r
@Transactional(readOnly=false)\r
public DeleteResult delete(UUID mediaUuid, MediaDeletionConfigurator config) {\r
while(textData.getMedia().contains(media)){\r
textData.removeMedia(media);\r
}\r
- //if the textData contains text it should not be deleted\r
- if (textData.getMedia().isEmpty() && textData.getMultilanguageText().isEmpty()){\r
- desc.removeElement(textData);\r
- }\r
- if (desc.getElements().isEmpty()){\r
- describable.removeDescription(desc);\r
- }\r
+\r
return describable;\r
}\r
\r
String message = null;\r
if (ref instanceof MediaRepresentation){\r
continue;\r
- }\r
- if (ref instanceof TextData){\r
+ }else if (ref instanceof TextData){\r
TextData textData = HibernateProxyHelper.deproxy(ref, TextData.class);\r
- DescriptionBase description = HibernateProxyHelper.deproxy(textData.getInDescription(), DescriptionBase.class);\r
+ DescriptionBase<?> description = HibernateProxyHelper.deproxy(textData.getInDescription(), DescriptionBase.class);\r
\r
if (description instanceof TaxonDescription){\r
TaxonDescription desc = HibernateProxyHelper.deproxy(description, TaxonDescription.class);\r
result.setAbort();\r
}\r
}\r
-\r
- }if (ref instanceof MediaSpecimen){\r
+ }else if (ref instanceof MediaSpecimen){\r
message = "The media can't be deleted from the database because it is referenced by a mediaspecimen. ("+((MediaSpecimen)ref).getTitleCache()+")";\r
result.setAbort();\r
}else {\r
if (message != null){\r
result.addException(new ReferencedObjectUndeletableException(message));\r
result.addRelatedObject(ref);\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Reads the metadata as stored in the file or web resource and filters the data by the include and exclude lists of key names\r
+ * as stored in the data base properties {@link PreferencePredicate#MediaMetadataKeynameExcludes} and {@link PreferencePredicate#MediaMetadataKeynameExcludes}\r
+ * <p>\r
+ * Metadata of multiple parts is merged into one common metadata map whereas the later part being read may overwrite data from previous parts.\r
+ * The consequences of this can be neglected since we don't expect that multiple parts are actually being used.\r
+ *\r
+ * @param representation\r
+ * @return\r
+ * @throws IOException\r
+ * @throws HttpException\r
+ */\r
+ @Override\r
+ public Map<String, String> readResourceMetadataFiltered(MediaRepresentation representation) throws IOException, HttpException {\r
\r
+ List<String> includes = mediaMetadataKeyIncludes();\r
+ List<String> excludes = mediaMetadataKeyExludes();\r
+ Map<String, String> metadata = new HashMap<>();\r
+\r
+ for(MediaRepresentationPart part : representation.getParts()) {\r
+ CdmImageInfo iInfo = mediaInfoFactory.cdmImageInfoWithMetaData(part.getUri());\r
+ if(iInfo.getMetaData() != null) {\r
+ metadata.putAll(iInfo.getMetaData());\r
}\r
+ }\r
\r
+ if(logger.isDebugEnabled()) {\r
+ logger.debug("meta data as read from all parts: " + metadata.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(", ", "{", "}")));\r
}\r
\r
- return result;\r
+ if(!includes.isEmpty()) {\r
+ metadata = metadata.entrySet()\r
+ .stream()\r
+ .filter( e -> containsCaseInsensitive(e.getKey(), includes))\r
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));\r
+ if(logger.isDebugEnabled()) {\r
+ logger.debug("meta filtered by includes: " + metadata.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(", ", "{", "}")));\r
+ }\r
+ }\r
+ if(!excludes.isEmpty()) {\r
+ metadata = metadata.entrySet()\r
+ .stream()\r
+ .filter( e -> !containsCaseInsensitive(e.getKey(), excludes))\r
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));\r
+ if(logger.isDebugEnabled()) {\r
+ logger.debug("meta filtered by excludes: " + metadata.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(", ", "{", "}")));\r
+ }\r
+ }\r
+\r
+ if(metadata == null) {\r
+ metadata = new HashMap<>();\r
+ }\r
+ return metadata;\r
+ }\r
+\r
+ private boolean containsCaseInsensitive(String s, List<String> l){\r
+ return l.stream().anyMatch(x -> x.equalsIgnoreCase(s));\r
+ }\r
+\r
+ protected List<String> mediaMetadataKeyExludes(){\r
+ CdmPreference pref = prefsService.findExact(CdmPreference.NewKey(PreferenceSubject.NewDatabaseInstance(), PreferencePredicate.MediaMetadataKeynameExcludes));\r
+ if(pref == null) {\r
+ return new ArrayList<>();\r
+ }\r
+ return pref.splitStringListValue();\r
+ }\r
+\r
+ protected List<String> mediaMetadataKeyIncludes(){\r
+ CdmPreference pref = prefsService.findExact(CdmPreference.NewKey(PreferenceSubject.NewDatabaseInstance(), PreferencePredicate.MediaMetadataKeynameIncludes));\r
+ if(pref == null) {\r
+ return Arrays.asList(PreferencePredicate.MediaMetadataKeynameIncludes.getDefaultValue().toString().split(","));\r
+ }\r
+ return pref.splitStringListValue();\r
}\r
}\r