github.com/boki/go-xmp@v1.0.1/xmp/xmp_ext.go (about)

     1  // Copyright (c) 2017-2018 Alexander Eichhorn
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package xmp
    16  
    17  import (
    18  	"encoding/xml"
    19  )
    20  
    21  // Raw nodes are used to keep custom data models inside a container. This
    22  // is used by extension nodes in the Adobe UMC SDK, but may be used in
    23  // private models as well.
    24  type Extension Node
    25  
    26  func (x *Extension) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    27  	return (*Node)(x).MarshalXML(e, start)
    28  }
    29  
    30  func (x *Extension) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    31  	return (*Node)(x).UnmarshalXML(d, start)
    32  }
    33  
    34  func (x *Extension) IsZero() bool {
    35  	return (*Node)(x).IsZero()
    36  }
    37  
    38  func (x *Extension) FindNodeByName(name string) *Node {
    39  	for _, n := range x.Nodes {
    40  		if n.Name() == name {
    41  			return n
    42  		}
    43  		if n.Model != nil && n.Model.Can(name) {
    44  			return n
    45  		}
    46  	}
    47  	return nil
    48  }
    49  
    50  func (x Extension) MarshalXMP(e *Encoder, node *Node, m Model) error {
    51  	for _, ext := range x.Nodes {
    52  		if ext.Model != nil {
    53  			if err := e.EncodeElement(ext.Model, node); err != nil {
    54  				return err
    55  			}
    56  		}
    57  
    58  		// unwrap one extra layer that we keep for identifying extensions
    59  		if x.XMLName.Local == "" {
    60  			for _, child := range ext.Nodes {
    61  				if child.Model != nil {
    62  					if err := e.EncodeElement(child.Model, node); err != nil {
    63  						return err
    64  					}
    65  				} else {
    66  					node.Nodes = append(node.Nodes, copyNode(child))
    67  				}
    68  			}
    69  		} else {
    70  			node.Nodes = append(node.Nodes, copyNode(ext))
    71  		}
    72  	}
    73  	return nil
    74  }
    75  
    76  func (x *Extension) UnmarshalXMPAttr(d *Decoder, a Attr) error {
    77  	return d.decodeAttribute(&x.Nodes, a)
    78  }
    79  
    80  func (x *Extension) UnmarshalXMP(d *Decoder, src *Node, m Model) error {
    81  	for _, v := range src.Attr {
    82  		if err := d.decodeAttribute(&x.Nodes, v); err != nil {
    83  			return err
    84  		}
    85  	}
    86  
    87  	for _, child := range src.Nodes {
    88  		// recurse if we see a new description element (used in xmpMM:pantry)
    89  		if child.FullName() == "rdf:Description" {
    90  			if err := x.UnmarshalXMP(d, child, m); err != nil {
    91  				return err
    92  			}
    93  			continue
    94  		}
    95  		if err := d.decodeNode(&x.Nodes, child); err != nil {
    96  			// when decoding fails, store as raw child node
    97  			x.Nodes = append(x.Nodes, copyNode(child))
    98  		}
    99  	}
   100  	return nil
   101  }
   102  
   103  // used for xmpMM:Pantry bags
   104  //
   105  // <xmpMM:Pantry>
   106  //   <rdf:Bag>
   107  //     <rdf:li>
   108  //       <rdf:Description>...</rdf:Description>
   109  //     </rdf:li>
   110  //   </rdf:Bag>
   111  // </xmpMM:Pantry>
   112  //
   113  type ExtensionArray []*Extension
   114  
   115  func (x ExtensionArray) Typ() ArrayType {
   116  	return ArrayTypeUnordered
   117  }
   118  
   119  func (x ExtensionArray) MarshalXMP(e *Encoder, node *Node, m Model) error {
   120  	if len(x) == 0 {
   121  		return nil
   122  	}
   123  	bag := NewNode(xml.Name{Local: "rdf:Bag"})
   124  	node.Nodes = append(node.Nodes, bag)
   125  	for _, v := range x {
   126  		li := NewNode(xml.Name{Local: "rdf:li"})
   127  		elem := NewNode(rdfDescription)
   128  		li.Nodes = append(li.Nodes, elem)
   129  		if err := e.EncodeElement(v, elem); err != nil {
   130  			return err
   131  		}
   132  		bag.Nodes = append(bag.Nodes, li)
   133  	}
   134  	return nil
   135  }
   136  
   137  func (x *ExtensionArray) UnmarshalXMP(d *Decoder, node *Node, m Model) error {
   138  	return UnmarshalArray(d, node, x.Typ(), x)
   139  }
   140  
   141  // Generates the following XMP/JSON structures from an array instead of
   142  // xmp:<rdf:Bag> / json:[]
   143  //
   144  // <iXML:extension>
   145  //    <PRIVATE-NAME-1 rdf:parseType="Resource">
   146  //        <PRIVATE-FIELD/>
   147  //    </PRIVATE-NAME-1>
   148  //    <PRIVATE-NAME-2 rdf:parseType="Resource">
   149  //        <PRIVATE-FIELD/>
   150  //    </PRIVATE-NAME-2>
   151  // </iXML:extension>
   152  //
   153  // iXML:extension: {
   154  //		"PRIVATE-NAME-1": {
   155  //	        "PRIVATE-FIELD": "",
   156  //      },
   157  //		"PRIVATE-NAME-2": {
   158  //	        "PRIVATE-FIELD": "",
   159  //      }
   160  // }
   161  //
   162  type NamedExtensionArray []*Extension
   163  
   164  func (x NamedExtensionArray) Typ() ArrayType {
   165  	return ArrayTypeUnordered
   166  }
   167  
   168  func (x *NamedExtensionArray) FindNodeByName(name string) *Node {
   169  	for _, v := range *x {
   170  		n := (*Node)(v)
   171  		if n.Name() == name {
   172  			return n
   173  		}
   174  		if n.Model != nil && n.Model.Can(name) {
   175  			return n
   176  		}
   177  	}
   178  	return nil
   179  }
   180  
   181  func (x NamedExtensionArray) MarshalXMP(e *Encoder, node *Node, m Model) error {
   182  	for _, v := range x {
   183  		ext := NewNode(NewName(v.XMLName.Local))
   184  		ext.AddAttr(rdfResourceAttr)
   185  		ext.Nodes = append(ext.Nodes, copyNodes(v.Nodes)...)
   186  		ext.Attr = append(ext.Attr, v.Attr...)
   187  		node.AddNode(ext)
   188  	}
   189  	return nil
   190  }
   191  
   192  func (x *NamedExtensionArray) UnmarshalXMP(d *Decoder, node *Node, m Model) error {
   193  	for _, v := range node.Nodes {
   194  		v.translate(d)
   195  		ext := (*Extension)(NewNode(NewName(v.XMLName.Local)))
   196  		ext.Nodes = append(ext.Nodes, copyNodes(v.Nodes)...)
   197  		ext.Attr = append(ext.Attr, v.Attr...)
   198  		*x = append(*x, ext)
   199  	}
   200  	return nil
   201  }