001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.xslt.tmap.model.xsltmap;
020:
021: import java.io.IOException;
022: import java.io.OutputStream;
023: import java.util.ArrayList;
024: import java.util.Collections;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029: import javax.swing.SwingUtilities;
030: import org.netbeans.api.project.Project;
031: import org.netbeans.modules.xslt.tmap.model.api.TMapModel;
032: import org.netbeans.modules.xslt.tmap.util.Util;
033: import org.openide.ErrorManager;
034: import org.openide.filesystems.FileAttributeEvent;
035: import org.openide.filesystems.FileChangeListener;
036: import org.openide.filesystems.FileEvent;
037: import org.openide.filesystems.FileLock;
038: import org.openide.filesystems.FileObject;
039: import org.openide.filesystems.FileRenameEvent;
040: import org.openide.xml.XMLUtil;
041: import org.w3c.dom.Document;
042: import org.w3c.dom.Element;
043: import org.w3c.dom.NamedNodeMap;
044: import org.w3c.dom.Node;
045: import org.w3c.dom.NodeList;
046:
047: /**
048: *
049: * @author Vitaly Bychkov
050: * @version 1.0
051: */
052: public class XsltMapModel {
053: private FileChangeListener xsltMapFileChangeListener;
054: private FileObject xsltMapFile;
055: private boolean isInit = false;
056:
057: private Document myDocument;
058: private List<TransformationUC> transformationUCs;
059: private ChangeXsltMapSupport changeModelSupport;
060:
061: protected XsltMapModel(FileObject xsltMapFile) {
062: if (!XsltMapAccessor.isValidXsltMapFile(xsltMapFile)) {
063: throw new IllegalArgumentException("Invalid xsltmap file"); // NOI18N
064: }
065: this .xsltMapFile = xsltMapFile;
066: xsltMapFileChangeListener = new XsltMapFileChangeListener();
067: xsltMapFile.addFileChangeListener(xsltMapFileChangeListener);
068: changeModelSupport = new ChangeXsltMapSupport();
069: }
070:
071: protected void finalize() throws Throwable {
072: super .finalize();
073: if (xsltMapFile != null && xsltMapFileChangeListener != null) {
074: xsltMapFile
075: .removeFileChangeListener(xsltMapFileChangeListener);
076: }
077: }
078:
079: /**
080: * Search for xsltmap file if no - create new one and return correspondent model
081: */
082: public static synchronized XsltMapModel getDefault(Project project)
083: throws IOException {
084: FileObject xsltMapFile = Util.getXsltMapFo(project);
085: if (xsltMapFile == null) {
086: xsltMapFile = XmlUtil.createTemplateXsltMapFo(project);
087: }
088:
089: if (xsltMapFile == null) {
090: return null;
091: }
092:
093: XsltMapModel xsltMapModel = new XsltMapModel(xsltMapFile);
094: xsltMapModel.initXsltMapModel();
095: return xsltMapModel.isInitModel() ? xsltMapModel : null;
096: }
097:
098: public FileObject getXsltMapFile() {
099: return xsltMapFile;
100: }
101:
102: /**
103: * save model to file
104: */
105: public synchronized void sync() throws IOException {
106: syncImpl();
107: }
108:
109: public void syncImpl() throws IOException {
110: if (!isInitModel()) {
111: throw new IllegalStateException(
112: "xsltMapModel hasn't been initialized"); // NOI18N
113: }
114:
115: FileObject xsltMapFile = getXsltMapFile();
116: FileLock fileLock = null;
117: OutputStream outputStream = null;
118: try {
119: fileLock = xsltMapFile.lock();
120: outputStream = xsltMapFile.getOutputStream(fileLock);
121: XMLUtil.write(myDocument, outputStream, XmlUtil.UTF8);
122: outputStream.flush();
123: outputStream.close();
124: } finally {
125: if (outputStream != null) {
126: outputStream.flush();
127: outputStream.close();
128: }
129:
130: if (fileLock != null) {
131: fileLock.releaseLock();
132: }
133: }
134: }
135:
136: /**
137: * add TransformationUC to the model
138: */
139: public synchronized void addTransformationUC(TransformationUC tUC) {
140: if (tUC == null) {
141: return;
142: }
143:
144: if (!isInitModel()) {
145: throw new IllegalStateException(
146: "xsltMapModel hasn't been initialized"); // NOI18N
147: }
148:
149: // TODO m
150: Node rootNode = XmlUtil.getElementByTagName(myDocument,
151: XsltMapConst.XSLTMAP);
152: assert rootNode != null;
153:
154: Element tUCElement = myDocument.createElement(tUC
155: .getTransformationType().getTagName());
156: assert tUCElement != null;
157:
158: List<TransformationDesc> tDescs = tUC.getTransformationDescs();
159: if (tDescs != null) {
160: for (TransformationDesc tmpDesc : tDescs) {
161: Element tDescElement = myDocument.createElement(tmpDesc
162: .getType().getTagName());
163:
164: String tmpPLink = tmpDesc.getPartnerLink();
165: if (tmpPLink != null) {
166: tDescElement.setAttribute(
167: XsltMapConst.PARTNER_LINK, tmpPLink);
168: }
169:
170: String tmpRoleName = tmpDesc.getRoleName();
171: if (tmpRoleName != null) {
172: tDescElement.setAttribute(XsltMapConst.ROLE_NAME,
173: tmpRoleName);
174: }
175: String tmpPortType = tmpDesc.getPortType();
176: if (tmpPortType != null) {
177: tDescElement.setAttribute(XsltMapConst.PORT_TYPE,
178: tmpPortType);
179: }
180: String tmpOperation = tmpDesc.getOperation();
181: if (tmpOperation != null) {
182: tDescElement.setAttribute(XsltMapConst.OPERATION,
183: tmpOperation);
184: }
185: String tmpMessageType = tmpDesc.getMessageType();
186: if (tmpMessageType != null) {
187: tDescElement.setAttribute(
188: XsltMapConst.MESSAGE_TYPE, tmpMessageType);
189: }
190: String tmpFile = tmpDesc.getFile();
191: if (tmpFile != null) {
192: tDescElement.setAttribute(XsltMapConst.FILE,
193: tmpFile);
194: }
195: String tmpTransformJBI = tmpDesc.getTransformJBI();
196: if (tmpTransformJBI != null) {
197: tDescElement
198: .setAttribute(XsltMapConst.TRANSFORM_JBI,
199: tmpTransformJBI);
200: }
201:
202: tUCElement.appendChild(tDescElement);
203: }
204: }
205: rootNode.appendChild(tUCElement);
206: }
207:
208: public synchronized List<TransformationUC> getTransformationUCs() {
209: return transformationUCs;
210: }
211:
212: public synchronized List<TransformationDesc> getTransformationDescs() {
213: List<TransformationDesc> transfDescsList = new ArrayList<TransformationDesc>();
214: List<TransformationUC> transformationUseCases = getTransformationUCs();
215: if (transformationUseCases == null) {
216: return transfDescsList;
217: }
218: for (TransformationUC ucElem : transformationUseCases) {
219: List<TransformationDesc> tmpDescs = ucElem
220: .getTransformationDescs();
221: if (tmpDescs != null && tmpDescs.size() > 0) {
222: transfDescsList.addAll(tmpDescs);
223: }
224: }
225:
226: return transfDescsList;
227: }
228:
229: public boolean isInitModel() {
230: return isInit;
231: }
232:
233: public synchronized void initXsltMapModel() {
234: Document document = XmlUtil.getDocument(xsltMapFile);
235: if (document == null) {
236: return;
237: }
238: myDocument = document;
239:
240: Map<TransformationType, Node> transformationUCNodes = new HashMap<TransformationType, Node>();
241: List<TransformationUC> tUCList = new ArrayList<TransformationUC>();
242:
243: for (TransformationType transformType : TransformationType
244: .values()) {
245: // Node tmpNode = XmlUtil.getElementByTagName(document, transformType.getTagName());
246: // TransformationUC tmpUc = createTransformationUCs(transformType, tmpNode);
247: NodeList nodeList = document
248: .getElementsByTagName(transformType.getTagName());
249: if (nodeList == null) {
250: continue;
251: }
252: for (int i = 0; i < nodeList.getLength(); i++) {
253: Node tmpNode = nodeList.item(i);
254: TransformationUC tmpUc = createTransformationUCs(
255: transformType, tmpNode);
256: if (tmpUc != null) {
257: tUCList.add(tmpUc);
258: }
259: }
260: }
261: this .transformationUCs = tUCList;
262:
263: isInit = true;
264: }
265:
266: /**
267: * Utililty method
268: */
269: public synchronized TransformationDesc getFirstTransformationDesc(
270: FileObject xsltFo) {
271: if (xsltFo == null) {
272: return null;
273: }
274:
275: TransformationDesc foundedDesc = null;
276: List<TransformationDesc> descs = getTransformationDescs();
277: for (TransformationDesc desc : descs) {
278: if (desc.isEqualInputFile(xsltFo)) {
279: foundedDesc = desc;
280: break;
281: }
282: }
283: return foundedDesc;
284: }
285:
286: private List<TransformationDesc> getTransformationDescs(
287: TransformationUC transfUC, Node transformNode,
288: TransformationType transformType) {
289: List<TransformationDesc> descList = new ArrayList<TransformationDesc>();
290: TransformationDescType[] tDescTypes = transformType
291: .getTransformationDescs();
292: for (TransformationDescType descType : tDescTypes) {
293: Node descNode = XmlUtil.getElementByTagName(transformNode
294: .getChildNodes(), descType.getTagName());
295: TransformationDesc tmpDesc = createTransformationDesc(
296: transfUC, descType, descNode);
297: if (tmpDesc != null) {
298: descList.add(tmpDesc);
299: }
300: }
301: return descList;
302: }
303:
304: private TransformationUC createTransformationUCs(
305: TransformationType type, Node ucNode) {
306: if (ucNode == null || type == null) {
307: return null;
308: }
309: TransformationUC tUC = null;
310: switch (type) {
311: case FILTER_ONE_WAY:
312: tUC = new FilterOneWayUC(this );
313: break;
314: case FILTER_REQUEST_REPLY:
315: tUC = new FilterRequestReplyUC(this );
316: break;
317: case REQUEST_REPLY_SERVICE:
318: tUC = new RequestReplyServiceUC(this );
319: break;
320: }
321: if (tUC != null) {
322: tUC.setTransformationDescs(getTransformationDescs(tUC,
323: ucNode, type));
324: }
325:
326: return tUC;
327: }
328:
329: private TransformationDesc createTransformationDesc(
330: TransformationUC transfUC, TransformationDescType type,
331: Node descNode) {
332: if (descNode == null || type == null) {
333: return null;
334: }
335: TransformationDesc desc = null;
336: switch (type) {
337: case INPUT:
338: desc = new InputTransformationDesc(this , transfUC);
339: break;
340: case OUTPUT:
341: desc = new OutputTransformationDesc(this , transfUC);
342: break;
343: }
344: if (desc != null) {
345: NamedNodeMap attrs = descNode.getAttributes();
346:
347: if (attrs != null) {
348: desc.setFile(XmlUtil.getAttrValue(attrs,
349: XsltMapConst.FILE));
350: desc.setMessageType(XmlUtil.getAttrValue(attrs,
351: XsltMapConst.MESSAGE_TYPE));
352: desc.setOperation(XmlUtil.getAttrValue(attrs,
353: XsltMapConst.OPERATION));
354: desc.setPartnerLink(XmlUtil.getAttrValue(attrs,
355: XsltMapConst.PARTNER_LINK));
356: desc.setPortType(XmlUtil.getAttrValue(attrs,
357: XsltMapConst.PORT_TYPE));
358: desc.setRoleName(XmlUtil.getAttrValue(attrs,
359: XsltMapConst.ROLE_NAME));
360: desc.setTransformJBI(XmlUtil.getAttrValue(attrs,
361: XsltMapConst.TRANSFORM_JBI));
362: }
363: }
364:
365: return desc;
366: }
367:
368: public void addPropertyChangeListener(
369: XsltMapPropertyChangeListener changeListener) {
370: changeModelSupport.addPropertyChangeListener(changeListener);
371: }
372:
373: public void removePropertyChangeListener(
374: XsltMapPropertyChangeListener changeListener) {
375: changeModelSupport.removePropertyChangeListener(changeListener);
376: }
377:
378: private synchronized void updateXsltMapModel() {
379: List<TransformationDesc> curTransfDesc = getTransformationDescs();
380:
381: List<TransformationDesc> oldDescs = null;
382: if (curTransfDesc != null && curTransfDesc.size() > 0) {
383: oldDescs = new ArrayList<TransformationDesc>(curTransfDesc);
384: Collections.copy(oldDescs, curTransfDesc);
385: }
386: initXsltMapModel();
387: curTransfDesc = getTransformationDescs();
388:
389: List<TransformationDesc> newDescs = null;//new ArrayList<TransformationDesc>();//curTransfDesc == null || curTransfDesc.length == 0 ? null : Arrays.asList(curTransfDesc.clone());
390: if (curTransfDesc != null && curTransfDesc.size() > 0) {
391: newDescs = new ArrayList<TransformationDesc>(curTransfDesc);
392: Collections.copy(newDescs, curTransfDesc);
393: }
394:
395: if (oldDescs == null || oldDescs.size() == 0) {
396: return;
397: }
398:
399: List<TransformationDesc> nonDeletedElems = new ArrayList<TransformationDesc>();
400: // in case all transformationUCs had been deleted
401: if (newDescs != null) {
402: for (TransformationDesc newElem : newDescs) {
403: assert newElem.getType() != null;
404: TransformationUC newParent = newElem.getParent();
405: if (newParent == null) {
406: continue;
407: }
408:
409: Iterator<TransformationDesc> oldDescIterator = oldDescs
410: .iterator();
411: while (oldDescIterator.hasNext()) {
412: TransformationDesc oldElem = oldDescIterator.next();
413: assert oldElem.getType() != null;
414:
415: // TODO m add unique id to compare an xsltmap elements
416: if (newParent.equals(oldElem.getParent())
417: && newElem.getType().equals(
418: oldElem.getType())) {
419: nonDeletedElems.add(oldElem);
420: if (!newElem.equals(oldElem)) {
421: fireTransformationDescChanged(oldElem,
422: newElem);
423: break;
424: }
425: }
426: }
427: }
428: }
429: oldDescs.removeAll(nonDeletedElems);
430:
431: for (TransformationDesc delElem : oldDescs) {
432: fireTransformationDescChanged(delElem, null);
433: }
434: }
435:
436: private void fireTransformationDescChanged(
437: TransformationDesc oldDesc, TransformationDesc newDesc) {
438: changeModelSupport.fireTransformationDescChanged(oldDesc,
439: newDesc);
440:
441: }
442:
443: private class XsltMapFileChangeListener implements
444: FileChangeListener {
445: public void fileFolderCreated(FileEvent fe) {
446: }
447:
448: public void fileDataCreated(FileEvent fe) {
449: }
450:
451: public void fileChanged(FileEvent fe) {
452: updateXsltMapModel();
453: }
454:
455: public void fileDeleted(FileEvent fe) {
456: }
457:
458: public void fileRenamed(FileRenameEvent fe) {
459: }
460:
461: public void fileAttributeChanged(FileAttributeEvent fe) {
462: }
463:
464: }
465:
466: }
|