}else
return false;
}else
+ if(tn=="Transaction"){
+ WocTransaction trn(el);
+ if(trn.isValid()){
+ m_transactions.append(trn);
+ emit newTransaction(trn);
+ }else
+ return false;
+ }else
if(tn=="Project"){
if(el.hasAttribute("baseDir"))
m_baseDir=el.attribute("baseDir");
}else
if(tn=="DataBase"){
if(el.hasAttribute("instance"))
- m_dbInst=el.attribute("instance");
+ m_dbInst=el.attribute("instance","dbInst");
if(el.hasAttribute("schema"))
- m_dbSchema=el.attribute("schema");
+ m_dbSchema=el.attribute("schema","dbSchema");
if(el.hasAttribute("version"))
m_dbVer=el.attribute("version");
}else
qDebug("Warning: file %s has unknown element '%s' at line %i column %i", fn.toLocal8Bit().data(), tn.toLocal8Bit().data(), el.lineNumber(), el.columnNumber());
}
}
+ //TODO: verify classes
+ //TODO: verify transactions
+
+ //return success
return true;
}
emit sfinalize();
}
-bool WocProcessor::haveTable(QString n)const
+bool WocProcessor::hasTable(QString n)const
{
for(int i=0;i<m_tables.size();i++)
if(m_tables[i].name()==n)return true;
return WocTable();
}
+bool WocProcessor::hasClass(QString n)const
+{
+ for(int i=0;i<m_classes.size();i++)
+ if(m_classes[i].name()==n)return true;
+ return false;
+}
+
+/******************************************************************************
+ * WocOutput
+ ******************************************************************************/
WocOutput::WocOutput()
{
connect(WocProcessor::instance(),SIGNAL(sfinalize()),this,SLOT(finalize()));
connect(WocProcessor::instance(),SIGNAL(newClass(const WocClass&)),this,SLOT(newClass(const WocClass&)));
connect(WocProcessor::instance(),SIGNAL(newTable(const WocTable&)),this,SLOT(newTable(const WocTable&)));
+ connect(WocProcessor::instance(),SIGNAL(newTransaction(const WocTransaction&)),this,SLOT(newTransaction(const WocTransaction&)));
}
WocOutput::~WocOutput(){}
+/******************************************************************************
+ * WocClass
+ ******************************************************************************/
+
WocClass::WocClass(const QDomElement&cls)
{
+ //scan basics
m_valid=true;
- qDebug("not really parsing class %s",cls.attribute("name").toAscii().data());
-
+ m_abstract=str2bool(cls.attribute("abstract","0"));
+ WocProcessor *woc=WocProcessor::instance();
+ QRegExp symok("[a-z_][a-z0-9_]*",Qt::CaseInsensitive);
+ m_name=cls.attribute("name");
+ if(m_name==""){
+ qDebug("Error: unnamed class at line %i column %i.",cls.lineNumber(),cls.columnNumber());
+ m_valid=false;
+ return;
+ }
+ if(woc->hasClass(m_name)){
+ qDebug("Error: double definition of class %s at line %i column %i.",m_name.toAscii().data(),cls.lineNumber(),cls.columnNumber());
+ m_valid=false;
+ return;
+ }
+ if(!symok.exactMatch(m_name)){
+ qDebug("Error: Illegal class name %s.",m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ qDebug("Info: parsing class %s",m_name.toAscii().data());
+ m_base=cls.attribute("base","WObject");
+ //scan properties
+ QDomNodeList nl=cls.elementsByTagName("Property");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ s_prop p;
+ p.name=el.attribute("name");
+ if(!symok.exactMatch(p.name)){
+ qDebug("Error: Illegal property %s in class %s.",p.name.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ if(hasProperty(p.name)){
+ qDebug("Error: Double definition of property %s in class %s.",p.name.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ p.type=el.attribute("type");
+ p.isid=str2bool(el.attribute("id","0"));
+ p.isabstract=str2bool(el.attribute("abstract","0"));
+ m_props.append(p);
+ }
+ //scan enums
+ nl=cls.elementsByTagName("Enum");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ QString nm=el.attribute("name");
+ QList<QPair<QString,int> >ev;
+ //check whether there is a reference
+ if(el.hasAttribute("refColumn")){
+ QStringList ref=el.attribute("refColumn").split(":");
+ if(ref.size()!=2){
+ qDebug("Error: illegal enum reference in class %s enum %s.",m_name.toAscii().data(),nm.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ if(!woc->hasTable(ref[0])){
+ qDebug("Error: enum reference in class %s enum %s points to non-existant table.",m_name.toAscii().data(),nm.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ WocTable tab=woc->table(ref[0]);
+ if(!tab.hasColumn(ref[1])){
+ qDebug("Error: enum reference in class %s enum %s points to non-existant column.",m_name.toAscii().data(),nm.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ ev=tab.columnEnums(ref[1]);
+ }
+ //scan values
+ QDomNodeList nl2=el.elementsByTagName("Value");
+ int nxval=0;
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ QString n=el2.attribute("name");
+ if(n==""){
+ qDebug("Warning: anonymous enum value in class %s enum %s. Ignoring it.",m_name.toAscii().data(),nm.toAscii().data());
+ continue;
+ }
+ nxval=el2.attribute("value",QString::number(nxval)).toInt(0,0);
+ ev.append(QPair<QString,int>(n,nxval));
+ nxval++;
+ }
+ m_enumvals.insert(nm,ev);
+ }
+ //scan mappings
+ nl=cls.elementsByTagName("Mapping");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ QString name=el.attribute("name");
+ QList<QPair<QString,QString> >map;
+ QDomNodeList nl2=el.elementsByTagName("Map");
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ QString col=el2.attribute("column");
+ QString prp=el2.attribute("property");
+ if(prp=="")prp=col;
+ if(col=="")col=prp;
+ if(col==""){
+ qDebug("Warning: empty mapping in class %s mapping %s. Ignoring it.",m_name.toAscii().data(),name.toAscii().data());
+ continue;
+ }
+ map.append(QPair<QString,QString>(col,prp));
+ }
+ m_maps.insert(name,map);
+ }
+ //check abstraction
+ if(!m_abstract && isAbstract()){
+ qDebug("Warning: class %s should be declared abstract.",m_name.toAscii().data());
+ }
}
+bool WocClass::hasProperty(QString p)const
+{
+ for(int i=0;i<m_props.size();i++)
+ if(m_props[i].name==p)return true;
+ return false;
+}
+
+bool WocClass::isAbstract()const
+{
+ for(int i=0;i<m_props.size();i++)
+ if(m_props[i].isabstract)return true;
+ return m_abstract;
+}
+
+
+/******************************************************************************
+ * WocTable
+ ******************************************************************************/
+
WocTable::WocTable()
{
m_backup=m_valid=false;
WocProcessor*woc=WocProcessor::instance();
QRegExp good("[a-z][a-z0-9_]*",Qt::CaseInsensitive);
//check name syntax, check it does not exist yet
- if(woc->haveTable(m_name)){
+ if(woc->hasTable(m_name)){
qDebug("Error: double definition of table %s.",m_name.toAscii().data());
m_valid=false;
return;
m_valid=false;
return;
}
- if(!woc->haveTable(fgn[0])){
+ if(!woc->hasTable(fgn[0])){
qDebug("Error: table %s column %s: foreign key target table %s does not exist",m_name.toAscii().data(),cl.name.toAscii().data(),fgn[0].toAscii().data());
m_valid=false;
return;
WocClass(const QDomElement&);
bool isValid()const{return m_valid;}
+
+ QString name()const{return m_name;}
+ QString baseClass()const{return m_base;}
+
+ bool hasProperty(QString)const;
+
+ bool isAbstract()const;
+
private:
- bool m_valid;
+ bool m_valid,m_abstract;
+ QString m_name,m_base;
+ struct s_prop{
+ QString name,type;
+ bool isid,isabstract;
+ };
+ QList<s_prop> m_props;
+ QMap<QString,QList<QPair<QString,QString> > >m_maps;
+ QMap<QString,QList<QPair<QString,int> > >m_enumvals;
};
class WocTable
QList<QMap<QString,QString> >m_presets;
};
+class WocTransaction
+{
+ public:
+ WocTransaction(const QDomElement&){}
+ bool isValid(){return true;}
+
+};
+
class WocOutput:public QObject
{
Q_OBJECT
virtual void finalize()=0;
virtual void newClass(const WocClass&)=0;
virtual void newTable(const WocTable&)=0;
+ virtual void newTransaction(const WocTransaction&)=0;
};
class WocProcessor:public QObject
QString dbSchema()const{return m_dbSchema;}
QString dbVersion()const{return m_dbVer;}
- bool haveTable(QString)const;
+ bool hasTable(QString)const;
WocTable table(QString)const;
+
+ bool hasClass(QString)const;
signals:
void sfinalize();
void newClass(const WocClass&);
void newTable(const WocTable&);
+ void newTransaction(const WocTransaction&);
private:
QString m_baseDir,m_wobDir,m_verComm,m_verNeedComm,m_verHR;
QList<WocTable> m_tables;
QList<WocClass> m_classes;
+ QList<WocTransaction> m_transactions;
static WocProcessor*inst;