1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.vaadin.gwt.client.editor.dom.processor;
35
36 import info.magnolia.ui.vaadin.gwt.client.editor.dom.Comment;
37 import info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlArea;
38 import info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlComponent;
39 import info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlElement;
40 import info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlPage;
41 import info.magnolia.ui.vaadin.gwt.client.editor.model.Model;
42 import info.magnolia.ui.vaadin.gwt.client.shared.ErrorType;
43
44 import java.util.HashMap;
45 import java.util.Map;
46
47 import com.google.gwt.core.client.GWT;
48 import com.google.gwt.dom.client.BodyElement;
49 import com.google.gwt.dom.client.Element;
50 import com.google.gwt.dom.client.HeadElement;
51 import com.google.gwt.dom.client.Node;
52 import com.google.gwt.event.shared.EventBus;
53 import com.google.gwt.regexp.shared.MatchResult;
54 import com.google.gwt.regexp.shared.RegExp;
55
56
57
58
59
60
61
62
63 public class CommentProcessor {
64
65 public MgnlElementadin/gwt/client/editor/dom/MgnlElement.html#MgnlElement">MgnlElement process(Model model, EventBus eventBus, Node node, MgnlElement currentElement) throws ProcessException {
66
67 CMSComment comment = getCmsComment(node);
68
69
70 MgnlElement mgnlElement = currentElement;
71
72 if (!comment.isClosing()) {
73
74 validateAreaAndComponentComments(node, comment);
75
76 mgnlElement = createMgnlElement(comment, currentElement, eventBus);
77 mgnlElement.setStartComment((Element) node.cast());
78
79
80 if (mgnlElement.getParent() == null) {
81 if (!(mgnlElement instanceof MgnlPage)) {
82 throw new ProcessException(ErrorType.EXPECTED_PAGE_TAG, comment.getTagName());
83 }
84 model.setRootPage((MgnlPage) mgnlElement);
85
86 } else {
87
88 if (mgnlElement.getParent().asMgnlElement().isPage()) {
89 if (!(mgnlElement instanceof MgnlArea)) {
90 throw new ProcessException(ErrorType.EXPECTED_AREA_TAG, comment.getTagName());
91 }
92 model.addRootArea((MgnlArea) mgnlElement);
93 }
94 mgnlElement.getParent().getChildren().add(mgnlElement);
95 }
96 }
97
98 else if (currentElement != null && !currentElement.isPage()) {
99 currentElement.setEndComment((Element) node.cast());
100 mgnlElement = currentElement.getParent().asMgnlElement();
101 }
102
103 return mgnlElement;
104
105 }
106
107 private CMSComment getCmsComment(Node node) throws IllegalArgumentException {
108
109 CMSComment cmsComment = new CMSComment();
110
111 Comment domComment = node.cast();
112 String comment = domComment.getData().trim();
113
114 GWT.log("processing comment " + comment);
115
116 String tagName = "";
117 boolean isClosing = false;
118
119 int delimiter = comment.indexOf(" ");
120 String attributeString = "";
121
122 if (delimiter < 0) {
123 tagName = comment;
124 } else {
125 tagName = comment.substring(0, delimiter);
126 attributeString = comment.substring(delimiter + 1);
127 }
128
129 if (tagName.startsWith("/")) {
130 isClosing = true;
131 tagName = tagName.substring(1);
132 }
133
134 if (tagName.startsWith(Model.CMS_TAG)) {
135 cmsComment.setTagName(tagName);
136 cmsComment.setAttribute(attributeString);
137 cmsComment.setClosing(isClosing);
138
139 } else {
140 throw new IllegalArgumentException("Tagname must start with +'" + Model.CMS_TAG + "'.");
141 }
142 return cmsComment;
143 }
144
145
146
147
148 private void validateAreaAndComponentComments(Node node, CMSComment comment) throws ProcessException {
149 String tagName = comment.getTagName();
150 boolean isAreaOrComponentTag = tagName.startsWith(Model.CMS_AREA) || tagName.startsWith(Model.CMS_COMPONENT);
151 BodyElement body = BodyElement.as(node.getOwnerDocument().getElementsByTagName("body").getItem(0));
152 HeadElement head = HeadElement.as(node.getOwnerDocument().getElementsByTagName("head").getItem(0));
153 if (isAreaOrComponentTag && !(head.isOrHasChild(node) || body.isOrHasChild(node))) {
154 throw new ProcessException(ErrorType.TAG_OUTSIDE_DOCUMENT, tagName);
155 }
156 }
157
158
159
160
161
162
163
164 private Map<String, String> getAttributes(String attributeString, MgnlElement parent) {
165 String[] keyValue;
166 Map<String, String> attributes = new HashMap<String, String>();
167
168 RegExp regExp = RegExp.compile("(\\S+=[\"'][^\"]*[\"'])", "g");
169 for (MatchResult matcher = regExp.exec(attributeString); matcher != null; matcher = regExp.exec(attributeString)) {
170 keyValue = matcher.getGroup(0).split("=");
171 if (keyValue[0].equals("content")) {
172 String content = keyValue[1].replace("\"", "");
173 int i = content.indexOf(':');
174 attributes.put("workspace", content.substring(0, i));
175 attributes.put("path", content.substring(i + 1));
176 } else {
177 attributes.put(keyValue[0], keyValue[1].replace("\"", ""));
178 }
179 }
180 if (parent != null) {
181 for (String inheritedAttribute : Model.INHERITED_ATTRIBUTES) {
182 if (parent.containsAttribute(inheritedAttribute)) {
183 attributes.put(inheritedAttribute, parent.getAttribute(inheritedAttribute));
184 }
185 }
186 }
187 return attributes;
188 }
189
190 private MgnlElementagnolia/ui/vaadin/gwt/client/editor/dom/MgnlElement.html#MgnlElement">MgnlElement createMgnlElement(CMSComment comment, MgnlElement parent, EventBus eventBus) throws IllegalArgumentException {
191 String tagName = comment.getTagName();
192 MgnlElement mgnlElement;
193 if (Model.CMS_PAGE.equals(tagName)) {
194 mgnlElement = new MgnlPage(parent);
195 } else if (Model.CMS_AREA.equals(tagName)) {
196 mgnlElement = new MgnlArea(parent, eventBus);
197 } else if (Model.CMS_COMPONENT.equals(tagName)) {
198 mgnlElement = new MgnlComponent(parent, eventBus);
199 } else {
200 throw new IllegalArgumentException("The tagname must be one of the defined marker Strings.");
201 }
202
203 mgnlElement.setAttributes(getAttributes(comment.getAttributes(), parent));
204
205 return mgnlElement;
206 }
207
208
209
210
211 private class CMSComment {
212
213 private String tagName;
214 private String attributes;
215 private boolean isClosing = false;
216
217 public String getTagName() {
218 return tagName;
219 }
220
221 public void setTagName(String tagName) {
222 this.tagName = tagName;
223 }
224
225 public boolean isClosing() {
226 return isClosing;
227 }
228
229 public void setClosing(boolean isClosing) {
230 this.isClosing = isClosing;
231 }
232
233 public void setAttribute(String attributes) {
234 this.attributes = attributes;
235 }
236
237 public String getAttributes() {
238 return attributes;
239 }
240 }
241 }