1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.trinidad.change;
20
21 import org.w3c.dom.DocumentFragment;
22 import org.w3c.dom.NamedNodeMap;
23 import org.w3c.dom.Node;
24 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
25
26 /**
27 * Change specialization for adding a child component using document mark up.
28 * While applying this Change, the child component is created and added to
29 * the document.
30 */
31 public class AddChildDocumentChange extends AddComponentDocumentChange
32 {
33 /**
34 * Constructs an AddChildDocumentChange with the specified child component
35 * mark up.
36 * @param componentFragment DOM mark up for child component to be appended.
37 * @throws IllegalArgumentException if componentFragment is <code>null</code>
38 */
39 public AddChildDocumentChange(DocumentFragment componentFragment)
40 {
41 this(null, componentFragment);
42 }
43
44 /**
45 * Constructs an AddChildDocumentChange with the specified child component
46 * mark up and the identifier of the neighbour. If the neighbour were not to
47 * be found while applying this Change, the child is appended to the end of
48 * the list of children.
49 * @param insertBeforeId The identifier of the sibling before which this new
50 * child is to be inserted or <code>null</code> to append the child
51 * @param componentFragment DOM mark up for child component to be inserted.
52 * @throws IllegalArgumentException if componentFragment is <code>null</code>
53 */
54 public AddChildDocumentChange(
55 String insertBeforeId,
56 DocumentFragment componentFragment)
57 {
58 super(componentFragment);
59
60 _insertBeforeId = insertBeforeId;
61 }
62
63 /**
64 * Returns the identifier of the sibling before which this new child needs to
65 * be inserted.
66 */
67 public String getInsertBeforeId()
68 {
69 return _insertBeforeId;
70 }
71
72 /**
73 * Given the DOM Node representing a Component, apply any necessary
74 * DOM changes.
75 */
76 public void changeDocument(Node componentNode)
77 {
78 if (componentNode == null)
79 throw new IllegalArgumentException(_LOG.getMessage(
80 "NO_NODE_SPECIFIED"));
81
82 // get the fragement, imported into the target document
83 DocumentFragment targetFragment =
84 getImportedComponentFragment(componentNode);
85
86 // assume that we'll be appending
87 Node insertBeforeNode = null;
88
89 // search children for the _insertBefore id
90 if (_insertBeforeId != null)
91 {
92 String insertBeforeID = _insertBeforeId;
93
94 Node currChild = componentNode.getFirstChild();
95 Node idAttr;
96
97 while (currChild != null)
98 {
99 NamedNodeMap attributes = currChild.getAttributes();
100
101 if (attributes != null)
102 {
103 idAttr = attributes.getNamedItem("id");
104 if (idAttr != null && insertBeforeID.equals(idAttr.getNodeValue()))
105 {
106 insertBeforeNode = currChild;
107 break;
108 }
109 }
110 currChild = currChild.getNextSibling();
111 }
112 }
113
114 // insert our DocumentFragment in the correct position
115 componentNode.insertBefore(targetFragment, insertBeforeNode);
116 }
117
118 private final String _insertBeforeId;
119 private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
120 AddChildDocumentChange.class);
121 }