1 /*=============================================================================
2 
3   Library: CTK
4 
5   Copyright (c) German Cancer Research Center,
6     Division of Medical and Biological Informatics
7 
8   Licensed under the Apache License, Version 2.0 (the "License");
9   you may not use this file except in compliance with the License.
10   You may obtain a copy of the License at
11 
12     http://www.apache.org/licenses/LICENSE-2.0
13 
14   Unless required by applicable law or agreed to in writing, software
15   distributed under the License is distributed on an "AS IS" BASIS,
16   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   See the License for the specific language governing permissions and
18   limitations under the License.
19 
20 =============================================================================*/
21 
22 
23 #include "ctkPluginGeneratorCodeModel.h"
24 
25 #include <QDir>
26 #include <QHash>
27 
28 #include <ctkException.h>
29 
30 
31 class ctkPluginGeneratorCodeModelPrivate
32 {
33 public:
34 
35   QHash<QString, ctkPluginGeneratorAbstractTemplate*> rootTemplates;
36   QHash<QString, QString> contentMap;
37 
38   QString symbolicNameWithPeriods;
39   QString symbolicNameWithUnderscores;
40   QString exportMacro;
41   QString exportMacroInclude;
42   QString license;
43 };
44 
45 class ctkPluginGeneratorFolderTemplate : public ctkPluginGeneratorAbstractTemplate
46 {
47 public:
48 
ctkPluginGeneratorFolderTemplate(const QString & name,ctkPluginGeneratorAbstractTemplate * parent=0)49   ctkPluginGeneratorFolderTemplate(const QString& name, ctkPluginGeneratorAbstractTemplate* parent = 0)
50     : ctkPluginGeneratorAbstractTemplate(name, parent)
51   {}
52 
generateContent()53   QString generateContent()
54   {
55     return "";
56   }
57 
create(const QString & location)58   void create(const QString& location)
59   {
60     QDir dir(location);
61     if (dir.mkdir(this->objectName()))
62     {
63       QString currLocation = location + QDir::separator() + this->objectName();
64       QListIterator<QObject*> it(this->children());
65       while (it.hasNext())
66       {
67         qobject_cast<ctkPluginGeneratorAbstractTemplate*>(it.next())->create(currLocation);
68       }
69     }
70     else
71     {
72       throw ctkRuntimeException("The directory " + location + this->objectName() + " could not be created");
73     }
74   }
75 };
76 
ctkPluginGeneratorCodeModel()77 ctkPluginGeneratorCodeModel::ctkPluginGeneratorCodeModel()
78   : d_ptr(new ctkPluginGeneratorCodeModelPrivate)
79 {
80 }
81 
~ctkPluginGeneratorCodeModel()82 ctkPluginGeneratorCodeModel::~ctkPluginGeneratorCodeModel()
83 {
84 }
85 
addContent(const QString & marker,const QString & content)86 void ctkPluginGeneratorCodeModel::addContent(const QString& marker, const QString& content)
87 {
88   Q_D(ctkPluginGeneratorCodeModel);
89   d->contentMap[marker] = content;
90 }
91 
getContent(const QString & marker) const92 QString ctkPluginGeneratorCodeModel::getContent(const QString& marker) const
93 {
94   Q_D(const ctkPluginGeneratorCodeModel);
95   if (d->contentMap.contains(marker))
96   {
97     return d->contentMap[marker];
98   }
99   return QString();
100 }
101 
setExportMacro(const QString & exportMacro)102 void ctkPluginGeneratorCodeModel::setExportMacro(const QString& exportMacro)
103 {
104   Q_D(ctkPluginGeneratorCodeModel);
105   d->exportMacro = exportMacro;
106 }
107 
getExportMacro() const108 QString ctkPluginGeneratorCodeModel::getExportMacro() const
109 {
110   Q_D(const ctkPluginGeneratorCodeModel);
111   return d->exportMacro;
112 }
113 
setExportMacroInclude(const QString & exportMacroInclude)114 void ctkPluginGeneratorCodeModel::setExportMacroInclude(const QString& exportMacroInclude)
115 {
116   Q_D(ctkPluginGeneratorCodeModel);
117   d->exportMacroInclude = exportMacroInclude;
118 }
119 
getExportMacroInclude() const120 QString ctkPluginGeneratorCodeModel::getExportMacroInclude() const
121 {
122   Q_D(const ctkPluginGeneratorCodeModel);
123   return d->exportMacroInclude;
124 }
125 
setSymbolicName(const QString & symbolicName)126 void ctkPluginGeneratorCodeModel::setSymbolicName(const QString& symbolicName)
127 {
128   Q_D(ctkPluginGeneratorCodeModel);
129   d->symbolicNameWithPeriods = QString(symbolicName).replace("_", ".");
130   d->symbolicNameWithUnderscores = QString(symbolicName).replace(".", "_");
131 }
132 
getSymbolicName(bool withPeriods) const133 QString ctkPluginGeneratorCodeModel::getSymbolicName(bool withPeriods) const
134 {
135   Q_D(const ctkPluginGeneratorCodeModel);
136   if (withPeriods)
137   {
138     return d->symbolicNameWithPeriods;
139   }
140  return d->symbolicNameWithUnderscores;
141 }
142 
setLicense(const QString & license)143 void ctkPluginGeneratorCodeModel::setLicense(const QString& license)
144 {
145   Q_D(ctkPluginGeneratorCodeModel);
146   d->license = license;
147 }
148 
getLicense() const149 QString ctkPluginGeneratorCodeModel::getLicense() const
150 {
151   Q_D(const ctkPluginGeneratorCodeModel);
152   return d->license;
153 }
154 
addTemplate(ctkPluginGeneratorAbstractTemplate * templ,const QString & path)155 void ctkPluginGeneratorCodeModel::addTemplate(ctkPluginGeneratorAbstractTemplate *templ,
156                                               const QString& path)
157 {
158   Q_D(ctkPluginGeneratorCodeModel);
159 
160   templ->setCodeModel(this);
161 
162   if (path.isEmpty())
163   {
164     d->rootTemplates.insert(templ->objectName(), templ);
165     templ->setParent(this);
166   }
167   else
168   {
169     ctkPluginGeneratorAbstractTemplate* parentTemplate = 0;
170     QStringList paths = path.split("/", QString::SkipEmptyParts);
171     QStringListIterator it(paths);
172     if (it.hasNext())
173     {
174       QString rootEntry = it.next();
175       // search the root templates
176       if (d->rootTemplates.contains(rootEntry))
177       {
178         if (!dynamic_cast<ctkPluginGeneratorFolderTemplate*>(d->rootTemplates[rootEntry]))
179         {
180           throw ctkRuntimeException("The segment \"" + rootEntry + "\" in \"" + path + "\" is not a folder");
181         }
182         parentTemplate = d->rootTemplates[rootEntry];
183       }
184       else
185       {
186         parentTemplate = new ctkPluginGeneratorFolderTemplate(rootEntry);
187         d->rootTemplates.insert(rootEntry, parentTemplate);
188       }
189       while (it.hasNext())
190       {
191         QString currEntry = it.next();
192         QListIterator<QObject*> children(parentTemplate->children());
193         bool childFound = false;
194         while (children.hasNext())
195         {
196           QObject* child = children.next();
197           if (child->objectName() == currEntry)
198           {
199             childFound = true;
200             parentTemplate = qobject_cast<ctkPluginGeneratorAbstractTemplate*>(child);
201             if (parentTemplate == 0)
202             {
203               throw ctkRuntimeException("The segment \"" + currEntry + "\" in \"" + path + "\" is not a folder");
204             }
205             break;
206           }
207         }
208 
209         if (!childFound)
210         {
211           parentTemplate = new ctkPluginGeneratorFolderTemplate(currEntry, parentTemplate);
212         }
213       }
214     }
215 
216     templ->setParent(parentTemplate);
217   }
218 }
219 
getTemplate(const QString & path) const220 ctkPluginGeneratorAbstractTemplate* ctkPluginGeneratorCodeModel::getTemplate(const QString& path) const
221 {
222   Q_D(const ctkPluginGeneratorCodeModel);
223 
224   if (!path.contains("/"))
225   {
226     foreach(ctkPluginGeneratorAbstractTemplate* t, d->rootTemplates)
227     {
228       if (t->objectName() == path) return t;
229       ctkPluginGeneratorAbstractTemplate* child =
230           t->findChild<ctkPluginGeneratorAbstractTemplate*>(path);
231       if (child) return child;
232     }
233     return 0;
234   }
235 
236   QStringList paths = path.split("/", QString::SkipEmptyParts);
237   if (paths.empty()) return 0;
238 
239   QObject* currChild = d->rootTemplates[paths.front()];
240   paths.pop_front();
241 
242   int depth = 0;
243   foreach (QString curr, paths)
244   {
245     foreach (QObject* child, currChild->children())
246     {
247       if (child->objectName() == curr)
248       {
249         currChild = child;
250         ++depth;
251         break;
252       }
253     }
254   }
255 
256   if (paths.size() == depth)
257   {
258     return qobject_cast<ctkPluginGeneratorAbstractTemplate*>(currChild);
259   }
260 
261   return 0;
262 }
263 
create(const QString & location)264 void ctkPluginGeneratorCodeModel::create(const QString& location)
265 {
266   Q_D(ctkPluginGeneratorCodeModel);
267 
268   QListIterator<ctkPluginGeneratorAbstractTemplate*> it(d->rootTemplates.values());
269   while (it.hasNext())
270   {
271     ctkPluginGeneratorAbstractTemplate* templ = it.next();
272     templ->create(location);
273   }
274 }
275 
reset()276 void ctkPluginGeneratorCodeModel::reset()
277 {
278   Q_D(ctkPluginGeneratorCodeModel);
279   qDeleteAll(d->rootTemplates.values());
280   d->rootTemplates.clear();
281 }
282