/// <summary>Find or create a schema node if <code>createNodes</code> is true.</summary> /// <param name="tree">the root of the xmp tree.</param> /// <param name="namespaceURI">a namespace</param> /// <param name="suggestedPrefix">If a prefix is suggested, the namespace is allowed to be registered.</param> /// <param name="createNodes"> /// a flag indicating if the node shall be created if not found. /// <em>Note:</em> The namespace must be registered prior to this call. /// </param> /// <returns> /// Returns the schema node if found, <code>null</code> otherwise. /// Note: If <code>createNodes</code> is <code>true</code>, it is <b>always</b> /// returned a valid node. /// </returns> /// <exception cref="Com.Adobe.Xmp.XMPException"> /// An exception is only thrown if an error occurred, not if a /// node was not found. /// </exception> internal static XMPNode FindSchemaNode(XMPNode tree, string namespaceURI, string suggestedPrefix, bool createNodes) { System.Diagnostics.Debug.Assert(tree.GetParent() == null); // make sure that its the root XMPNode schemaNode = tree.FindChildByName(namespaceURI); if (schemaNode == null && createNodes) { schemaNode = new XMPNode(namespaceURI, new PropertyOptions().SetSchemaNode(true)); schemaNode.SetImplicit(true); // only previously registered schema namespaces are allowed in the XMP tree. string prefix = XMPMetaFactory.GetSchemaRegistry().GetNamespacePrefix(namespaceURI); if (prefix == null) { if (suggestedPrefix != null && suggestedPrefix.Length != 0) { prefix = XMPMetaFactory.GetSchemaRegistry().RegisterNamespace(namespaceURI, suggestedPrefix); } else { throw new XMPException("Unregistered schema namespace URI", XMPErrorConstants.Badschema); } } schemaNode.SetValue(prefix); tree.AddChild(schemaNode); } return(schemaNode); }
/// <summary>Find or create a schema node if <code>createNodes</code> is true.</summary> /// <param name="tree">the root of the xmp tree.</param> /// <param name="namespaceURI">a namespace</param> /// <param name="suggestedPrefix">If a prefix is suggested, the namespace is allowed to be registered.</param> /// <param name="createNodes"> /// a flag indicating if the node shall be created if not found. /// <em>Note:</em> The namespace must be registered prior to this call. /// </param> /// <returns> /// Returns the schema node if found, <code>null</code> otherwise. /// Note: If <code>createNodes</code> is <code>true</code>, it is <b>always</b> /// returned a valid node. /// </returns> /// <exception cref="Com.Adobe.Xmp.XMPException"> /// An exception is only thrown if an error occurred, not if a /// node was not found. /// </exception> internal static XMPNode FindSchemaNode(XMPNode tree, string namespaceURI, string suggestedPrefix, bool createNodes) { System.Diagnostics.Debug.Assert(tree.GetParent() == null); // make sure that its the root XMPNode schemaNode = tree.FindChildByName(namespaceURI); if (schemaNode == null && createNodes) { schemaNode = new XMPNode(namespaceURI, new PropertyOptions().SetSchemaNode(true)); schemaNode.SetImplicit(true); // only previously registered schema namespaces are allowed in the XMP tree. string prefix = XMPMetaFactory.GetSchemaRegistry().GetNamespacePrefix(namespaceURI); if (prefix == null) { if (suggestedPrefix != null && suggestedPrefix.Length != 0) { prefix = XMPMetaFactory.GetSchemaRegistry().RegisterNamespace(namespaceURI, suggestedPrefix); } else { throw new XMPException("Unregistered schema namespace URI", XMPErrorConstants.Badschema); } } schemaNode.SetValue(prefix); tree.AddChild(schemaNode); } return schemaNode; }
/// <summary> /// The initial support for WAV files mapped a legacy ID3 audio copyright /// into a new xmpDM:copyright property. /// </summary> /// <remarks> /// The initial support for WAV files mapped a legacy ID3 audio copyright /// into a new xmpDM:copyright property. This is special case code to migrate /// that into dc:rights['x-default']. The rules: /// <pre> /// 1. If there is no dc:rights array, or an empty array - /// Create one with dc:rights['x-default'] set from double linefeed and xmpDM:copyright. /// 2. If there is a dc:rights array but it has no x-default item - /// Create an x-default item as a copy of the first item then apply rule #3. /// 3. If there is a dc:rights array with an x-default item, /// Look for a double linefeed in the value. /// A. If no double linefeed, compare the x-default value to the xmpDM:copyright value. /// A1. If they match then leave the x-default value alone. /// A2. Otherwise, append a double linefeed and /// the xmpDM:copyright value to the x-default value. /// B. If there is a double linefeed, compare the trailing text to the xmpDM:copyright value. /// B1. If they match then leave the x-default value alone. /// B2. Otherwise, replace the trailing x-default text with the xmpDM:copyright value. /// 4. In all cases, delete the xmpDM:copyright property. /// </pre> /// </remarks> /// <param name="xmp">the metadata object</param> /// <param name="dmCopyright">the "dm:copyright"-property</param> private static void MigrateAudioCopyright(XMPMeta xmp, XMPNode dmCopyright) { try { XMPNode dcSchema = XMPNodeUtils.FindSchemaNode(((XMPMetaImpl)xmp).GetRoot(), XMPConstConstants.NsDc, true); string dmValue = dmCopyright.GetValue(); string doubleLF = "\n\n"; XMPNode dcRightsArray = XMPNodeUtils.FindChildNode(dcSchema, "dc:rights", false); if (dcRightsArray == null || !dcRightsArray.HasChildren()) { // 1. No dc:rights array, create from double linefeed and xmpDM:copyright. dmValue = doubleLF + dmValue; xmp.SetLocalizedText(XMPConstConstants.NsDc, "rights", string.Empty, XMPConstConstants.XDefault, dmValue, null); } else { int xdIndex = XMPNodeUtils.LookupLanguageItem(dcRightsArray, XMPConstConstants.XDefault); if (xdIndex < 0) { // 2. No x-default item, create from the first item. string firstValue = dcRightsArray.GetChild(1).GetValue(); xmp.SetLocalizedText(XMPConstConstants.NsDc, "rights", string.Empty, XMPConstConstants.XDefault, firstValue, null); xdIndex = XMPNodeUtils.LookupLanguageItem(dcRightsArray, XMPConstConstants.XDefault); } // 3. Look for a double linefeed in the x-default value. XMPNode defaultNode = dcRightsArray.GetChild(xdIndex); string defaultValue = defaultNode.GetValue(); int lfPos = defaultValue.IndexOf(doubleLF); if (lfPos < 0) { // 3A. No double LF, compare whole values. if (!dmValue.Equals(defaultValue)) { // 3A2. Append the xmpDM:copyright to the x-default // item. defaultNode.SetValue(defaultValue + doubleLF + dmValue); } } else { // 3B. Has double LF, compare the tail. if (!Sharpen.Runtime.Substring(defaultValue, lfPos + 2).Equals(dmValue)) { // 3B2. Replace the x-default tail. defaultNode.SetValue(Sharpen.Runtime.Substring(defaultValue, 0, lfPos + 2) + dmValue); } } } // 4. Get rid of the xmpDM:copyright. dmCopyright.GetParent().RemoveChild(dmCopyright); } catch (XMPException) { } }
/// <param name="currNode">the node that will be added to the path.</param> /// <param name="parentPath">the path up to this node.</param> /// <param name="currentIndex">the current array index if an arrey is traversed</param> /// <returns>Returns the updated path.</returns> protected internal virtual string AccumulatePath(XMPNode currNode, string parentPath, int currentIndex) { string separator; string segmentName; if (currNode.GetParent() == null || currNode.GetOptions().IsSchemaNode()) { return(null); } else { if (currNode.GetParent().GetOptions().IsArray()) { separator = string.Empty; segmentName = "[" + currentIndex.ToString() + "]"; } else { separator = "/"; segmentName = currNode.GetName(); } } if (parentPath == null || parentPath.Length == 0) { return(segmentName); } else { if (this._enclosing.GetOptions().IsJustLeafname()) { return(!segmentName.StartsWith("?") ? segmentName : Sharpen.Runtime.Substring(segmentName, 1)); } else { // qualifier return(parentPath + separator + segmentName); } } }
/// <summary>Prepares the next node to return if not already done.</summary> /// <seealso cref="Sharpen.Iterator{E}.HasNext()"/> public override bool HasNext() { if (this.GetReturnProperty() != null) { // hasNext has been called before return(true); } else { if (this._enclosing.skipSiblings) { return(false); } else { if (this.childrenIterator.HasNext()) { XMPNode child = (XMPNode)this.childrenIterator.Next(); this.index++; string path = null; if (child.GetOptions().IsSchemaNode()) { this._enclosing.SetBaseNS(child.GetName()); } else { if (child.GetParent() != null) { // for all but the root node and schema nodes path = this.AccumulatePath(child, this.parentPath, this.index); } } // report next property, skip not-leaf nodes in case options is set if (!this._enclosing.GetOptions().IsJustLeafnodes() || !child.HasChildren()) { this.SetReturnProperty(this.CreatePropertyInfo(child, this._enclosing.GetBaseNS(), path)); return(true); } else { return(this.HasNext()); } } else { return(false); } } } }
/// <summary>Deletes the the given node and its children from its parent.</summary> /// <remarks> /// Deletes the the given node and its children from its parent. /// Takes care about adjusting the flags. /// </remarks> /// <param name="node">the top-most node to delete.</param> internal static void DeleteNode(XMPNode node) { XMPNode parent = node.GetParent(); if (node.GetOptions().IsQualifier()) { // root is qualifier parent.RemoveQualifier(node); } else { // root is NO qualifier parent.RemoveChild(node); } // delete empty Schema nodes if (!parent.HasChildren() && parent.GetOptions().IsSchemaNode()) { parent.GetParent().RemoveChild(parent); } }
/// <seealso cref="Com.Adobe.Xmp.XMPUtils.RemoveProperties(Com.Adobe.Xmp.XMPMeta, string, string, bool, bool)"/> /// <param name="xmp">The XMP object containing the properties to be removed.</param> /// <param name="schemaNS"> /// Optional schema namespace URI for the properties to be /// removed. /// </param> /// <param name="propName">Optional path expression for the property to be removed.</param> /// <param name="doAllProperties"> /// Option flag to control the deletion: do internal properties in /// addition to external properties. /// </param> /// <param name="includeAliases"> /// Option flag to control the deletion: Include aliases in the /// "named schema" case above. /// </param> /// <exception cref="Com.Adobe.Xmp.XMPException">If metadata processing fails</exception> public static void RemoveProperties(XMPMeta xmp, string schemaNS, string propName, bool doAllProperties, bool includeAliases) { ParameterAsserts.AssertImplementation(xmp); XMPMetaImpl xmpImpl = (XMPMetaImpl)xmp; if (propName != null && propName.Length > 0) { // Remove just the one indicated property. This might be an alias, // the named schema might not actually exist. So don't lookup the // schema node. if (schemaNS == null || schemaNS.Length == 0) { throw new XMPException("Property name requires schema namespace", XMPErrorConstants.Badparam); } XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName); XMPNode propNode = XMPNodeUtils.FindNode(xmpImpl.GetRoot(), expPath, false, null); if (propNode != null) { if (doAllProperties || !Utils.IsInternalProperty(expPath.GetSegment(XMPPath.StepSchema).GetName(), expPath.GetSegment(XMPPath.StepRootProp).GetName())) { XMPNode parent = propNode.GetParent(); parent.RemoveChild(propNode); if (parent.GetOptions().IsSchemaNode() && !parent.HasChildren()) { // remove empty schema node parent.GetParent().RemoveChild(parent); } } } } else { if (schemaNS != null && schemaNS.Length > 0) { // Remove all properties from the named schema. Optionally include // aliases, in which case // there might not be an actual schema node. // XMP_NodePtrPos schemaPos; XMPNode schemaNode = XMPNodeUtils.FindSchemaNode(xmpImpl.GetRoot(), schemaNS, false); if (schemaNode != null) { if (RemoveSchemaChildren(schemaNode, doAllProperties)) { xmpImpl.GetRoot().RemoveChild(schemaNode); } } if (includeAliases) { // We're removing the aliases also. Look them up by their // namespace prefix. // But that takes more code and the extra speed isn't worth it. // Lookup the XMP node // from the alias, to make sure the actual exists. XMPAliasInfo[] aliases = XMPMetaFactory.GetSchemaRegistry().FindAliases(schemaNS); for (int i = 0; i < aliases.Length; i++) { XMPAliasInfo info = aliases[i]; XMPPath path = XMPPathParser.ExpandXPath(info.GetNamespace(), info.GetPropName()); XMPNode actualProp = XMPNodeUtils.FindNode(xmpImpl.GetRoot(), path, false, null); if (actualProp != null) { XMPNode parent = actualProp.GetParent(); parent.RemoveChild(actualProp); } } } } else { // Remove all appropriate properties from all schema. In this case // we don't have to be // concerned with aliases, they are handled implicitly from the // actual properties. for (Iterator it = xmpImpl.GetRoot().IterateChildren(); it.HasNext();) { XMPNode schema = (XMPNode)it.Next(); if (RemoveSchemaChildren(schema, doAllProperties)) { it.Remove(); } } } } }
/// <param name="currNode">the node that will be added to the path.</param> /// <param name="parentPath">the path up to this node.</param> /// <param name="currentIndex">the current array index if an arrey is traversed</param> /// <returns>Returns the updated path.</returns> protected internal virtual string AccumulatePath(XMPNode currNode, string parentPath, int currentIndex) { string separator; string segmentName; if (currNode.GetParent() == null || currNode.GetOptions().IsSchemaNode()) { return null; } else { if (currNode.GetParent().GetOptions().IsArray()) { separator = string.Empty; segmentName = "[" + currentIndex.ToString() + "]"; } else { separator = "/"; segmentName = currNode.GetName(); } } if (parentPath == null || parentPath.Length == 0) { return segmentName; } else { if (this._enclosing.GetOptions().IsJustLeafname()) { return !segmentName.StartsWith("?") ? segmentName : Sharpen.Runtime.Substring(segmentName, 1); } else { // qualifier return parentPath + separator + segmentName; } } }