/// <summary>Returns a property, but the result value can be requested.</summary> /// <remarks> /// Returns a property, but the result value can be requested. It can be one /// of /// <see cref="VALUE_STRING"/> /// , /// <see cref="VALUE_BOOLEAN"/> /// , /// <see cref="VALUE_INTEGER"/> /// , /// <see cref="VALUE_LONG"/> /// , /// <see cref="VALUE_DOUBLE"/> /// , /// <see cref="VALUE_DATE"/> /// , /// <see cref="VALUE_CALENDAR"/> /// , /// <see cref="VALUE_BASE64"/> /// . /// </remarks> /// <seealso cref="iText.Kernel.XMP.XMPMeta.GetProperty(System.String, System.String) /// "/> /// <param name="schemaNS">a schema namespace</param> /// <param name="propName">a property name or path</param> /// <param name="valueType">the type of the value, see VALUE_...</param> /// <returns>Returns an <code>XMPProperty</code></returns> /// <exception cref="iText.Kernel.XMP.XMPException">Collects any exception that occurs.</exception> protected internal virtual XMPProperty GetProperty(String schemaNS, String propName , int valueType) { ParameterAsserts.AssertSchemaNS(schemaNS); ParameterAsserts.AssertPropName(propName); XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName); XMPNode propNode = XMPNodeUtils.FindNode(tree, expPath, false, null); if (propNode != null) { if (valueType != VALUE_STRING && propNode.GetOptions().IsCompositeProperty()) { throw new XMPException("Property must be simple when a value type is requested", XMPError.BADXPATH); } Object value = EvaluateNodeValue(valueType, propNode); return new _XMPProperty_703(value, propNode); } else { return null; } }
/// <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(); } } } } }
/// <summary>Constructor with optionsl initial values.</summary> /// <remarks> /// Constructor with optionsl initial values. If <code>propName</code> is provided, /// <code>schemaNS</code> has also be provided. /// </remarks> /// <param name="xmp">the iterated metadata object.</param> /// <param name="schemaNS">the iteration is reduced to this schema (optional)</param> /// <param name="propPath">the iteration is redurce to this property within the <code>schemaNS</code></param> /// <param name="options"> /// advanced iteration options, see /// <see cref="Com.Adobe.Xmp.Options.IteratorOptions"/> /// </param> /// <exception cref="Com.Adobe.Xmp.XMPException">If the node defined by the paramters is not existing.</exception> public XMPIteratorImpl(XMPMetaImpl xmp, string schemaNS, string propPath, IteratorOptions options) { // make sure that options is defined at least with defaults this.options = options != null ? options : new IteratorOptions(); // the start node of the iteration depending on the schema and property filter XMPNode startNode = null; string initialPath = null; bool baseSchema = schemaNS != null && schemaNS.Length > 0; bool baseProperty = propPath != null && propPath.Length > 0; if (!baseSchema && !baseProperty) { // complete tree will be iterated startNode = xmp.GetRoot(); } else { if (baseSchema && baseProperty) { // Schema and property node provided XMPPath path = XMPPathParser.ExpandXPath(schemaNS, propPath); // base path is the prop path without the property leaf XMPPath basePath = new XMPPath(); for (int i = 0; i < path.Size() - 1; i++) { basePath.Add(path.GetSegment(i)); } startNode = XMPNodeUtils.FindNode(xmp.GetRoot(), path, false, null); baseNS = schemaNS; initialPath = basePath.ToString(); } else { if (baseSchema && !baseProperty) { // Only Schema provided startNode = XMPNodeUtils.FindSchemaNode(xmp.GetRoot(), schemaNS, false); } else { // !baseSchema && baseProperty // No schema but property provided -> error throw new XMPException("Schema namespace URI is required", XMPErrorConstants.Badschema); } } } // create iterator if (startNode != null) { if (!this.options.IsJustChildren()) { nodeIterator = new XMPIteratorImpl.NodeIterator(this, startNode, initialPath, 1); } else { nodeIterator = new XMPIteratorImpl.NodeIteratorChildren(this, startNode, initialPath); } } else { // create null iterator nodeIterator = Collections.EmptyList().ListIterator(); } }
public virtual void SetLocalizedText(String schemaNS, String altTextName, String genericLang, String specificLang, String itemValue, PropertyOptions options) { ParameterAsserts.AssertSchemaNS(schemaNS); ParameterAsserts.AssertArrayName(altTextName); ParameterAsserts.AssertSpecificLang(specificLang); genericLang = genericLang != null ? iText.Kernel.XMP.Impl.Utils.NormalizeLangValue (genericLang) : null; specificLang = iText.Kernel.XMP.Impl.Utils.NormalizeLangValue(specificLang); XMPPath arrayPath = XMPPathParser.ExpandXPath(schemaNS, altTextName); // Find the array node and set the options if it was just created. XMPNode arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, true, new PropertyOptions (PropertyOptions.ARRAY | PropertyOptions.ARRAY_ORDERED | PropertyOptions.ARRAY_ALTERNATE | PropertyOptions.ARRAY_ALT_TEXT)); if (arrayNode == null) { throw new XMPException("Failed to find or create array node", XMPError.BADXPATH); } else { if (!arrayNode.GetOptions().IsArrayAltText()) { if (!arrayNode.HasChildren() && arrayNode.GetOptions().IsArrayAlternate()) { arrayNode.GetOptions().SetArrayAltText(true); } else { throw new XMPException("Specified property is no alt-text array", XMPError.BADXPATH ); } } } // Make sure the x-default item, if any, is first. bool haveXDefault = false; XMPNode xdItem = null; foreach (XMPNode currItem in arrayNode.GetChildren()) { if (!currItem.HasQualifier() || !XMPConst.XML_LANG.Equals(currItem.GetQualifier(1 ).GetName())) { throw new XMPException("Language qualifier must be first", XMPError.BADXPATH); } else { if (XMPConst.X_DEFAULT.Equals(currItem.GetQualifier(1).GetValue())) { xdItem = currItem; haveXDefault = true; break; } } } // Moves x-default to the beginning of the array if (xdItem != null && arrayNode.GetChildrenLength() > 1) { arrayNode.RemoveChild(xdItem); arrayNode.AddChild(1, xdItem); } // Find the appropriate item. // chooseLocalizedText will make sure the array is a language // alternative. Object[] result = XMPNodeUtils.ChooseLocalizedText(arrayNode, genericLang, specificLang ); int match = (int)result[0]; XMPNode itemNode = (XMPNode)result[1]; bool specificXDefault = XMPConst.X_DEFAULT.Equals(specificLang); switch (match) { case XMPNodeUtils.CLT_NO_VALUES: { // Create the array items for the specificLang and x-default, with // x-default first. XMPNodeUtils.AppendLangItem(arrayNode, XMPConst.X_DEFAULT, itemValue); haveXDefault = true; if (!specificXDefault) { XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue); } break; } case XMPNodeUtils.CLT_SPECIFIC_MATCH: { if (!specificXDefault) { // Update the specific item, update x-default if it matches the // old value. if (haveXDefault && xdItem != itemNode && xdItem != null && xdItem.GetValue().Equals (itemNode.GetValue())) { xdItem.SetValue(itemValue); } // ! Do this after the x-default check! itemNode.SetValue(itemValue); } else { // Update all items whose values match the old x-default value. System.Diagnostics.Debug.Assert(haveXDefault && xdItem == itemNode); for (IEnumerator it_1 = arrayNode.IterateChildren(); it_1.MoveNext(); ) { XMPNode currItem = (XMPNode)it_1.Current; if (currItem == xdItem || !currItem.GetValue().Equals(xdItem != null ? xdItem.GetValue () : null)) { continue; } currItem.SetValue(itemValue); } // And finally do the x-default item. if (xdItem != null) { xdItem.SetValue(itemValue); } } break; } case XMPNodeUtils.CLT_SINGLE_GENERIC: { // Update the generic item, update x-default if it matches the old // value. if (haveXDefault && xdItem != itemNode && xdItem != null && xdItem.GetValue().Equals (itemNode.GetValue())) { xdItem.SetValue(itemValue); } itemNode.SetValue(itemValue); // ! Do this after // the x-default // check! break; } case XMPNodeUtils.CLT_MULTIPLE_GENERIC: { // Create the specific language, ignore x-default. XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue); if (specificXDefault) { haveXDefault = true; } break; } case XMPNodeUtils.CLT_XDEFAULT: { // Create the specific language, update x-default if it was the only // item. if (xdItem != null && arrayNode.GetChildrenLength() == 1) { xdItem.SetValue(itemValue); } XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue); break; } case XMPNodeUtils.CLT_FIRST_ITEM: { // Create the specific language, don't add an x-default item. XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue); if (specificXDefault) { haveXDefault = true; } break; } default: { // does not happen under normal circumstances throw new XMPException("Unexpected result from ChooseLocalizedText", XMPError.INTERNALFAILURE ); } } // Add an x-default at the front if needed. if (!haveXDefault && arrayNode.GetChildrenLength() == 1) { XMPNodeUtils.AppendLangItem(arrayNode, XMPConst.X_DEFAULT, itemValue); } }