public bool AddObject(ObjDigital objDigital) { try { string newPid = manager.getNextPID("1", serverNamespace)[0]; if (objDigital.pid == "-1") objDigital.pid = newPid; FoxmlExporter foxml; if (objDigital.GetType() == typeof(ObjDigSimples)) foxml = new FoxmlExporter(objDigital as ObjDigSimples, gisaOperator, newPid, serverNamespace); else foxml = new FoxmlExporter(objDigital as ObjDigComposto, gisaOperator, newPid, ((ObjDigComposto)objDigital).objSimples, serverNamespace); if (Ingest(foxml, newPid) != null) { Trace.WriteLine(newPid + " foi ingerido."); objDigital.pid = newPid; objDigital.state = State.unchanged; return true; } Trace.WriteLine(newPid + " não foi ingerido."); return false; } catch (Exception ex) { Trace.WriteLine(ex.ToString()); return false; } }
private bool UpdateMetadata(ObjDigital obj, string[] logMessage, out string newTimestamp) { DublinCoreExporter dcExporter; MetsExporter metsExporter; newTimestamp = null; try { // Create new versions of XML for METS and DC if (obj.GetType() == typeof(ObjDigComposto)) { var objComposto = obj as ObjDigComposto; dcExporter = new DublinCoreExporter(objComposto); metsExporter = new MetsExporter(objComposto, gisaOperator, logMessage); } else { var objSimples = obj as ObjDigSimples; dcExporter = new DublinCoreExporter(objSimples); metsExporter = new MetsExporter(objSimples, gisaOperator, logMessage); } } catch (Exception ex) { Trace.Write("Erro ao recriar DC/METS do " + obj.pid + ": "); Trace.WriteLine(ex.ToString()); return(false); } // Reingerir o DC e o METS try { manager.modifyDatastreamByValue(obj.pid, "DC", null, null, "text/xml", null, ConvertToBytes(dcExporter.DublinCore), "MD5", null, "Atualização de metadados", false); newTimestamp = manager.modifyDatastreamByValue(obj.pid, "METS", null, null, "text/xml", null, ConvertToBytes(metsExporter.METS), "MD5", null, "Atualização de metadados", false); return(true); } catch (Exception ex) { Trace.Write("Erro ao reingerir DC/METS do " + obj.pid + ": "); Trace.WriteLine(ex.ToString()); return(false); } }
public bool AddObject(ObjDigital objDigital) { try { string newPid = manager.getNextPID("1", serverNamespace)[0]; if (objDigital.pid == "-1") { objDigital.pid = newPid; } FoxmlExporter foxml; if (objDigital.GetType() == typeof(ObjDigSimples)) { foxml = new FoxmlExporter(objDigital as ObjDigSimples, gisaOperator, newPid, serverNamespace); } else { foxml = new FoxmlExporter(objDigital as ObjDigComposto, gisaOperator, newPid, ((ObjDigComposto)objDigital).objSimples, serverNamespace); } if (Ingest(foxml, newPid) != null) { Trace.WriteLine(newPid + " foi ingerido."); objDigital.pid = newPid; objDigital.state = State.unchanged; return(true); } Trace.WriteLine(newPid + " não foi ingerido."); return(false); } catch (Exception ex) { Trace.WriteLine(ex.ToString()); return(false); } }
private void DoTheFOXML(ObjDigital obj) { var title = obj.titulo; // Construir os headers foxml = new FoxmlDigitalObject("1.1", this.pid); foxml.properties = new FoxmlObjectProperties(); foxml.properties.AddProperty(new FoxmlProperty("info:fedora/fedora-system:def/model#state", "A")); foxml.properties.AddProperty(new FoxmlProperty("info:fedora/fedora-system:def/model#label", title)); // Add the DC datastream DublinCoreExporter dcXml; MetsExporter metsXml; if (obj.GetType() == typeof(ObjDigSimples)) { ObjDigSimples objSimples = obj as ObjDigSimples; metsXml = new MetsExporter(objSimples, userName, new string[] { "Ingestão do documento " + this.pid }); dcXml = new DublinCoreExporter(obj as ObjDigSimples); } else { ObjDigComposto objComposto = obj as ObjDigComposto; metsXml = new MetsExporter(objComposto, userName, new string[] { "Ingestão do documento " + this.pid }); dcXml = new DublinCoreExporter(obj as ObjDigComposto); } FoxmlDatastream dcStream = new FoxmlDatastream("DC", FoxmlDatastreamState.Active, FoxmlControlGroup.InlineXML, true); FoxmlDatastreamVersion dcStream1 = new FoxmlDatastreamVersion("DC.0", "http://www.openarchives.org/OAI/2.0/oai_dc/", "text/xml", "Metadados em Dublin Core", null, null); dcStream1.inlineXML = dcXml.DublinCore; dcStream1.contentDigest = new FoxmlContentDigest(FoxmlChecksumTypes.DEFAULT, null); dcStream.AddVersion(dcStream1); foxml.AddDatastream(dcStream); // Add the RELS-EXT datastream FoxmlDatastream relsStream = new FoxmlDatastream("RELS-EXT", FoxmlDatastreamState.Active, FoxmlControlGroup.InlineXML, true); FoxmlDatastreamVersion relsStream1 = new FoxmlDatastreamVersion("RELS-EXT.0", "info:fedora/fedora-system:FedoraRELSExt-1.0", "application/rdf+xml", "RDF Statements about this object", null, null); relsStream1.inlineXML = GetRdf(this.pid, this.nmspace); relsStream.AddVersion(relsStream1); foxml.AddDatastream(relsStream); // Add the METS datastream for this document FoxmlDatastream metsStream = new FoxmlDatastream("METS", FoxmlDatastreamState.Active, FoxmlControlGroup.InlineXML, true); FoxmlDatastreamVersion metsStream1 = new FoxmlDatastreamVersion("METS.0", "http://www.loc.gov/METS/", "text/xml", "Metadados adicionais em METS", null, null); metsStream1.inlineXML = metsXml.METS; metsStream1.contentDigest = new FoxmlContentDigest(FoxmlChecksumTypes.DEFAULT, null); metsStream.AddVersion(metsStream1); foxml.AddDatastream(metsStream); // Add the content datastreams FoxmlDatastream datastream; FoxmlDatastreamVersion dsversion; if (obj.GetType() == typeof(ObjDigSimples)) { int cnt = 1; ObjDigSimples objSimples = obj as ObjDigSimples; foreach (Anexo s in objSimples.fich_associados) { string uName = s.dataStreamID; datastream = new FoxmlDatastream(uName, FoxmlDatastreamState.Active, FoxmlControlGroup.ExternallyReferenceContent, true); dsversion = new FoxmlDatastreamVersion(uName + ".0", null, s.mimeType, null, null, null); dsversion.contentLocation = new FoxmlContentLocation(s.url, "URL"); dsversion.contentDigest = new FoxmlContentDigest(FoxmlChecksumTypes.DEFAULT, null); datastream.AddVersion(dsversion); foxml.AddDatastream(datastream); cnt++; } } }
private void DoTheMETS(ObjDigital obj, string[] logMessage) { var idsGisa = new string[] { obj.gisa_id }; var title = obj.titulo; var type = obj.tipologia; // Ficheiro METS mets = new MetsFile(null, null, title, type, null); // Header - criador, hora de criação, e IDs alternativos mets.header = new MetsHeaderSection(null, null, Utility.Now(), null, null); mets.header.AddAgent(new MetsAgent(null, MetsAgentRole.Archivist, null, MetsAgentType.Individual, null, userName, logMessage)); foreach (string s in idsGisa.Where(id => id.Length > 0)) { string typeID = s.Substring(0, s.IndexOf(':')); mets.header.AddAltID(new MetsAlternativeIdentifier(null, typeID, s)); } // Criar a secção de Ficheiros mets.fileSection = new MetsFileSection(null); MetsFileGroup fileGrp = new MetsFileGroup(null, null, null, "Conteúdos"); mets.fileSection.AddFileGroupElement(fileGrp); MetsStructMap structa = null; MetsStructDivision largeFile = null; if (obj.GetType() == typeof(ObjDigSimples)) { ObjDigSimples objSimples = obj as ObjDigSimples; structa = new MetsStructMap(null, "PHYSICAL", "Estruturação em imagens do " + title); largeFile = new MetsStructDivision(null, type, title, null, null, null, null, null, null); for (int i = 0; i < objSimples.fich_associados.Count; i++) { Anexo ficheiro = objSimples.fich_associados[i]; if (ficheiro.dataStreamID == null) { ficheiro.dataStreamID = "IMG" + objSimples.nextDatastreamId; objSimples.nextDatastreamId++; } string uName = ficheiro.dataStreamID; MetsFileElement file = new MetsFileElement(uName, ficheiro.mimeType, (i + 1).ToString(), null, null, null, MetsChecksumType.NONE, null, null, null, null, null); file.AddFLocat(new MetsXLinkElement(null, null, MetsLocatorType.Other, "Nome de Datastream", uName, null, null, null, null, null)); fileGrp.AddFileElement(file); MetsStructDivision div = new MetsStructDivision(null, ficheiro.mimeType, title, null, null, (i + 1).ToString(), null, null, null); div.AddFilePointer(new MetsFilePointer(null, uName, null)); largeFile.AddDivision(div); } } else { ObjDigComposto objComposto = obj as ObjDigComposto; structa = new MetsStructMap(null, "LOGICAL", "Estruturação em partes do " + title); largeFile = new MetsStructDivision(null, type, title, null, null, null, null, null, null); foreach (ObjDigSimples sd in objComposto.objSimples) { // Apenas queremos fazer isto se o objecto não estiver marcado como apagado if (sd.state != State.deleted) { string pid = sd.pid; MetsStructDivision div = new MetsStructDivision(null, sd.tipologia, sd.titulo, null, null, (objComposto.objSimples.IndexOf(sd) + 1).ToString(), null, null, null); div.AddFilePointer(new MetsFilePointer(null, pid, null)); largeFile.AddDivision(div); } } } structa.AddDivision(largeFile); mets.AddStructMap(structa); }
private bool UpdateMetadata(ObjDigital obj, string[] logMessage, out string newTimestamp) { DublinCoreExporter dcExporter; MetsExporter metsExporter; newTimestamp = null; try { // Create new versions of XML for METS and DC if (obj.GetType() == typeof(ObjDigComposto)) { var objComposto = obj as ObjDigComposto; dcExporter = new DublinCoreExporter(objComposto); metsExporter = new MetsExporter(objComposto, gisaOperator, logMessage); } else { var objSimples = obj as ObjDigSimples; dcExporter = new DublinCoreExporter(objSimples); metsExporter = new MetsExporter(objSimples, gisaOperator, logMessage); } } catch (Exception ex) { Trace.Write("Erro ao recriar DC/METS do " + obj.pid + ": "); Trace.WriteLine(ex.ToString()); return false; } // Reingerir o DC e o METS try { manager.modifyDatastreamByValue(obj.pid, "DC", null, null, "text/xml", null, ConvertToBytes(dcExporter.DublinCore), "MD5", null, "Atualização de metadados", false); newTimestamp = manager.modifyDatastreamByValue(obj.pid, "METS", null, null, "text/xml", null, ConvertToBytes(metsExporter.METS), "MD5", null, "Atualização de metadados", false); return true; } catch(Exception ex) { Trace.Write("Erro ao reingerir DC/METS do " + obj.pid + ": "); Trace.WriteLine(ex.ToString()); return false; } }
private bool Update(ObjDigital objDigital) { bool success = true; bool update = false; var original = objDigital.original; List<string> changeset = new List<string>(); // Se objecto não tem modificações, não fazer nada if (objDigital.state != State.modified) return true; // Mesmo pid? if (original.pid != objDigital.pid || original.GetType() != objDigital.GetType()) { Trace.WriteLine("Objecto a atualizar não tem o mesmo PID do objecto original."); return false; } // Se for simples, verificar imagens if (objDigital.GetType() == typeof(ObjDigSimples)) { // Verificar se é um simples e se mexemos nas imagens var simpleOriginal = original as ObjDigSimples; var simpleChanged = objDigital as ObjDigSimples; // Detectar alterações na ordem (pelo menos dos documentos que se mantiverem da versão anterior) for (int i = 0; i < simpleOriginal.fich_associados.Count; i++) { if (i + 1 > simpleChanged.fich_associados.Count) break; if (simpleChanged.fich_associados[i].url != simpleOriginal.fich_associados[i].url) { AddChange(IMAGES_ORDER, out update, changeset); break; } } // Adicionar novas datastreams if (simpleChanged.fich_associados.Exists(fich => fich.dataStreamID == null)) { AddChange(IMAGES_NEW, out update, changeset); foreach (Anexo anexo in simpleChanged.fich_associados.Where(anx => anx.dataStreamID == null)) { try { anexo.dataStreamID = manager.addDatastream(simpleChanged.pid, "IMG" + simpleChanged.nextDatastreamId, null, null, true, anexo.mimeType, null, anexo.url, "E", "A", "MD5", null, "Adição de imagem"); simpleChanged.nextDatastreamId++; } catch (Exception ex) { Trace.WriteLine(ex.ToString()); return false; } } } // Detectar remoções feitas no objecto if (!simpleOriginal.fich_associados.TrueForAll(anexoOriginal => simpleChanged.fich_associados.Exists(anexoNovo => anexoNovo.url == anexoOriginal.url && anexoNovo.dataStreamID == anexoOriginal.dataStreamID))) { changeset.Add(IMAGES_DELETE); update = true; } /* if (simpleOriginal.fich_associados.Count > simpleChanged.fich_associados.Count) { changeset.Add(IMAGES_DELETE); update = true; } */ } else if (objDigital.GetType() == typeof(ObjDigComposto)) { // Se for um composto, verificar também se alteramos o título / tipologia de um dos simples var compostoOriginal = original as ObjDigComposto; var compostoChanged = objDigital as ObjDigComposto; // Vemos se o composto tem o mesmo número de objectos simples que o original if (compostoChanged.objSimples.Count == compostoOriginal.objSimples.Count) { for (int i = 0; i < compostoChanged.objSimples.Count; i++) { ObjDigSimples simples = compostoChanged.objSimples[i]; ObjDigSimples simplesOriginal = compostoOriginal.objSimples[i]; if (simples.pid != simplesOriginal.pid) { AddChange(DOCUMENT_ORDER, out update, changeset); break; } } // Verificamos se algum dos simples associados a este composto teve o seu título ou tipologia alterada foreach (ObjDigSimples simples in compostoChanged.objSimples) { ObjDigSimples simplesOriginal = simples.original as ObjDigSimples; if (simplesOriginal == null || simples.titulo != simplesOriginal.titulo || simples.tipologia != simplesOriginal.tipologia) { AddChange(METADATA_CHILD, out update, changeset); break; } } // Actualizações ao estado de publicação não ficam registados como nova versão if (compostoChanged.publicado != compostoOriginal.publicado) PokeObject(compostoChanged); else { foreach (ObjDigSimples simples in compostoChanged.objSimples) { ObjDigSimples simplesOriginal = simples.original as ObjDigSimples; if (simplesOriginal != null && simples.publicado != simplesOriginal.publicado) { PokeObject(compostoChanged); break; } } } } else { // Neste caso, ou adicionamos novos sub-documentos, ou os removemos if (compostoChanged.objSimples.Count > compostoOriginal.objSimples.Count) AddChange(DOCUMENT_CHILD_NEW, out update, changeset); else AddChange(DOCUMENT_CHILD_DELETE, out update, changeset); update = true; } } // Verificar alteração na lista de assuntos if (original.assuntos.Count != objDigital.assuntos.Count || !objDigital.assuntos.TrueForAll(assunto => original.assuntos.Contains(assunto))) AddChange(DOCUMENT_THEME, out update, changeset); // A tipologia foi alterada? if (original.tipologia != objDigital.tipologia) AddChange(DOCUMENT_TYPE, out update, changeset); // O título foi alterado? if (original.titulo != objDigital.titulo) AddChange(DOCUMENT_TITLE, out update, changeset); if (update) { if (changeset.Count == 0) changeset.Add(METADATA_DEFAULT); // Refazer DC e METS string newStamp; success = UpdateMetadata(objDigital, changeset.ToArray(), out newStamp); // Actualizar versão, se tudo correu bem if (success) { objDigital.version = newStamp; objDigital.state = State.unchanged; } } return success; }
public IngestResult Ingest(ObjDigital obj) { if (obj.GetType() == typeof(ObjDigComposto)) { var docComposto = obj as ObjDigComposto; bool updateComplex = false; bool allUnchanged = true; IngestResult result = IngestResult.Success; List<ObjDigSimples> toRemove = new List<ObjDigSimples>(); //if (obj.state == State.notFound) // return IngestResult.Error; //if (docComposto.objSimples.Count(od => od.state == State.notFound) > 0) // return IngestResult.Error; foreach (var sd in docComposto.objSimples) { // So olhamos para objectos que foram alterados if (sd.state != State.unchanged) { allUnchanged = false; if (AtomicIngest(sd)) { updateComplex = true; if (sd.state == State.deleted) toRemove.Add(sd); } else result = IngestResult.Partial; } } if (allUnchanged && obj.state == State.unchanged) return IngestResult.Success; else if (updateComplex || (obj.state != State.unchanged)) { // Se houverem documentos que foram marcados como removidos, remover da lista do objecto composto toRemove.ForEach(doc => docComposto.objSimples.Remove(doc)); // Tentar actualizar complexo if (AtomicIngest(obj)) return result; else return IngestResult.Error; } else return IngestResult.Error; } else { // Documento simples solto if (obj.state != State.notFound && AtomicIngest(obj)) return IngestResult.Success; else return IngestResult.Error; } }
private bool Update(ObjDigital objDigital) { bool success = true; bool update = false; var original = objDigital.original; List <string> changeset = new List <string>(); // Se objecto não tem modificações, não fazer nada if (objDigital.state != State.modified) { return(true); } // Mesmo pid? if (original.pid != objDigital.pid || original.GetType() != objDigital.GetType()) { Trace.WriteLine("Objecto a atualizar não tem o mesmo PID do objecto original."); return(false); } // Se for simples, verificar imagens if (objDigital.GetType() == typeof(ObjDigSimples)) { // Verificar se é um simples e se mexemos nas imagens var simpleOriginal = original as ObjDigSimples; var simpleChanged = objDigital as ObjDigSimples; // Detectar alterações na ordem (pelo menos dos documentos que se mantiverem da versão anterior) for (int i = 0; i < simpleOriginal.fich_associados.Count; i++) { if (i + 1 > simpleChanged.fich_associados.Count) { break; } if (simpleChanged.fich_associados[i].url != simpleOriginal.fich_associados[i].url) { AddChange(IMAGES_ORDER, out update, changeset); break; } } // Adicionar novas datastreams if (simpleChanged.fich_associados.Exists(fich => fich.dataStreamID == null)) { AddChange(IMAGES_NEW, out update, changeset); foreach (Anexo anexo in simpleChanged.fich_associados.Where(anx => anx.dataStreamID == null)) { try { anexo.dataStreamID = manager.addDatastream(simpleChanged.pid, "IMG" + simpleChanged.nextDatastreamId, null, null, true, anexo.mimeType, null, anexo.url, "E", "A", "MD5", null, "Adição de imagem"); simpleChanged.nextDatastreamId++; } catch (Exception ex) { Trace.WriteLine(ex.ToString()); return(false); } } } // Detectar remoções feitas no objecto if (!simpleOriginal.fich_associados.TrueForAll(anexoOriginal => simpleChanged.fich_associados.Exists(anexoNovo => anexoNovo.url == anexoOriginal.url && anexoNovo.dataStreamID == anexoOriginal.dataStreamID))) { changeset.Add(IMAGES_DELETE); update = true; } /* if (simpleOriginal.fich_associados.Count > simpleChanged.fich_associados.Count) * { * changeset.Add(IMAGES_DELETE); * update = true; * } */ } else if (objDigital.GetType() == typeof(ObjDigComposto)) { // Se for um composto, verificar também se alteramos o título / tipologia de um dos simples var compostoOriginal = original as ObjDigComposto; var compostoChanged = objDigital as ObjDigComposto; // Vemos se o composto tem o mesmo número de objectos simples que o original if (compostoChanged.objSimples.Count == compostoOriginal.objSimples.Count) { for (int i = 0; i < compostoChanged.objSimples.Count; i++) { ObjDigSimples simples = compostoChanged.objSimples[i]; ObjDigSimples simplesOriginal = compostoOriginal.objSimples[i]; if (simples.pid != simplesOriginal.pid) { AddChange(DOCUMENT_ORDER, out update, changeset); break; } } // Verificamos se algum dos simples associados a este composto teve o seu título ou tipologia alterada foreach (ObjDigSimples simples in compostoChanged.objSimples) { ObjDigSimples simplesOriginal = simples.original as ObjDigSimples; if (simplesOriginal == null || simples.titulo != simplesOriginal.titulo || simples.tipologia != simplesOriginal.tipologia) { AddChange(METADATA_CHILD, out update, changeset); break; } } // Actualizações ao estado de publicação não ficam registados como nova versão if (compostoChanged.publicado != compostoOriginal.publicado) { PokeObject(compostoChanged); } else { foreach (ObjDigSimples simples in compostoChanged.objSimples) { ObjDigSimples simplesOriginal = simples.original as ObjDigSimples; if (simplesOriginal != null && simples.publicado != simplesOriginal.publicado) { PokeObject(compostoChanged); break; } } } } else { // Neste caso, ou adicionamos novos sub-documentos, ou os removemos if (compostoChanged.objSimples.Count > compostoOriginal.objSimples.Count) { AddChange(DOCUMENT_CHILD_NEW, out update, changeset); } else { AddChange(DOCUMENT_CHILD_DELETE, out update, changeset); } update = true; } } // Verificar alteração na lista de assuntos if (original.assuntos.Count != objDigital.assuntos.Count || !objDigital.assuntos.TrueForAll(assunto => original.assuntos.Contains(assunto))) { AddChange(DOCUMENT_THEME, out update, changeset); } // A tipologia foi alterada? if (original.tipologia != objDigital.tipologia) { AddChange(DOCUMENT_TYPE, out update, changeset); } // O título foi alterado? if (original.titulo != objDigital.titulo) { AddChange(DOCUMENT_TITLE, out update, changeset); } if (update) { if (changeset.Count == 0) { changeset.Add(METADATA_DEFAULT); } // Refazer DC e METS string newStamp; success = UpdateMetadata(objDigital, changeset.ToArray(), out newStamp); // Actualizar versão, se tudo correu bem if (success) { objDigital.version = newStamp; objDigital.state = State.unchanged; } } return(success); }
public IngestResult Ingest(ObjDigital obj) { if (obj.GetType() == typeof(ObjDigComposto)) { var docComposto = obj as ObjDigComposto; bool updateComplex = false; bool allUnchanged = true; IngestResult result = IngestResult.Success; List <ObjDigSimples> toRemove = new List <ObjDigSimples>(); //if (obj.state == State.notFound) // return IngestResult.Error; //if (docComposto.objSimples.Count(od => od.state == State.notFound) > 0) // return IngestResult.Error; foreach (var sd in docComposto.objSimples) { // So olhamos para objectos que foram alterados if (sd.state != State.unchanged) { allUnchanged = false; if (AtomicIngest(sd)) { updateComplex = true; if (sd.state == State.deleted) { toRemove.Add(sd); } } else { result = IngestResult.Partial; } } } if (allUnchanged && obj.state == State.unchanged) { return(IngestResult.Success); } else if (updateComplex || (obj.state != State.unchanged)) { // Se houverem documentos que foram marcados como removidos, remover da lista do objecto composto toRemove.ForEach(doc => docComposto.objSimples.Remove(doc)); // Tentar actualizar complexo if (AtomicIngest(obj)) { return(result); } else { return(IngestResult.Error); } } else { return(IngestResult.Error); } } else { // Documento simples solto if (obj.state != State.notFound && AtomicIngest(obj)) { return(IngestResult.Success); } else { return(IngestResult.Error); } } }