Finished the following issues

26 - Reorganize and doc the main class

Also made changes in some XML values and properties to keep them up to date and in the main config file
Esse commit está contido em:
felipenmoura
2010-03-29 01:45:45 +00:00
commit f6ce50a345
4 arquivos alterados com 263 adições e 110 exclusões
+8 -7
Ver Arquivo
@@ -22,7 +22,7 @@
$_MIND['imageDir'] = 'images'; // directory to load images to Mind Interface
$_MIND['scriptSrc'] = 'framework/scripts'; // directory to load scripts to Mind Interface
$_MIND['styleSrc'] = 'framework/styles'; // directory to load CSS styles to Mind Interface
$_MIND['themeSrc'] = 'framework/styles/themes'; // directory to load CSS styles to Mind Interface
$_MIND['themeSrc'] = 'framework/styles/themes'; // directory to load CSS styles to Mind Interface
$_MIND['fwComponents'] = 'framework/components'; // components to be used by the mind framework
$_MIND['dbmsDir'] = 'dbmss'; // directory to load DBMS configuration and libraries
$_MIND['defaultDbms'] = 'postgres';
@@ -44,16 +44,17 @@
$_MIND['tipMessagesFile'] = 'messages/tip.php';
$_MIND['primaryKeyPrefix'] = 'pk_';
$_MIND['foreignKeyPrefix'] = 'fk_';
$_MIND['showDeveloperMenu'] = false; // shows the menu DEVELOPER, or not
$_MIND['parentOnSelfRelation'] = 'main_';
$_MIND['selfRelationalTable'] = '_pointer';
$_MIND['showDeveloperMenu'] = false; // shows the menu DEVELOPER, or not
$_MIND['load'] = Array();
$_MIND['load']['user'] = 'classes/user.php';
$_MIND['load']['project'] = 'classes/project.php';
$_MIND['load']['plugin'] = 'classes/plugin.php';
$_MIND['load']['module'] = 'classes/module.php';
//use $_MIND['load']['extraConfig'] = 'myConfigFile.php'; to load extra configuration of yours, to the system, it may be used by your own modules, or plugins that require so
// $_MIND['load']['extraConfig'] = 'myConfigFile.php'; //to load extra configuration of yours, to the system, it may be used by your own modules, or plugins that require so
$_MIND['version'] = '2.0';
$_MIND['year'] = '2009';
$_MIND['year'] = '2010';
$_MIND['month'] = '';
$_MIND['mindSpecificInfoAt'] = 'http://thewebmind.org/2.0';
$_MIND['developers'] = 'http://thewebmind.org/2.0/credits';
// end of configuration file ?>
$_MIND['mindSpecificInfoAt'] = 'http://thewebmind.org/';
$_MIND['developers'] = 'http://code.google.com/p/webmind/people/list';
+1 -1
Ver Arquivo
@@ -273,7 +273,7 @@
$attTypeSize= false;
$attName= false;
$attTypeName= false;
}else{ // ligação de tabela
}else{ // ligao de tabela
$cu++;
if(strpos($lin[0], $this->OR))
{ // min E max
+253 -101
Ver Arquivo
@@ -1,9 +1,9 @@
<?php
/**
* CLass: MindProcessor 1.0
* Class used to interpret and generate wml code
* @package processor
* Definition: class used to interpret and generate wml code
* Author: Felipe Nascimento
* @author Felipe Nascimento
*
* Observations:
* * tables without relations (neither pointed by nor pointing to other tables) will not exist
@@ -51,6 +51,7 @@
'max'=>' ||"||MIND_QUANTIFY_MAX_MAX||"|| '));
/**
* This method receives the text and parses it into an Array with all the expressions, separeted by "." or ";"
* @author Felipe Nascimento
* @name parse
* @param String $str
* @return numeric Array
@@ -60,16 +61,18 @@
$expressions= Array(); // will have all the expressions to be interpreted
$sep= Array('.', ';'); // expression separator
$str= preg_split('//', trim($str)); // separing comments
$str[]= $sep[0];
$inside= false;
$str[]= $sep[0]; // this will fix well the expressiona had a comment without a . in the end
$inside= false; // indicates whether the iterator is between ""
$comment= false;
$allow= false;
$insideAtt= false;
$allow= false; // this var indicates if the iterator is between {} or []
$insideAtt= false; // inside ( ) ??
$currentExpression= '';
// running through the string, letter by letter
for($i=0, $j= sizeof($str); $i<$j; $i++)
{
$letter= $str[$i];
// first, we gotta ignore the comment blocks
if($letter == '/')
{
if(!$comment)
@@ -86,9 +89,11 @@
}
}
}
// if it is inside a comment block, we skip to the next letter
if($comment)
continue;
// checking if it is scaping the next charachter, if so, we must add this and skip
if($i>0 && $str[$i-1] == '\\')
{
$currentExpression.= $str[$i];
@@ -124,28 +129,33 @@
}
return $expressions;
}
/**
* This is the constructor
* if it receives a project object by parameter, it processes this project, otherwise, it simply returns itself
* with its current properties
* @author Felipe Nascimento
* @name __construct
* @param [Project Object]
* @return void
*/
public function __construct($project=false) // obj of project
private function log($level, $msg)
{
if(!$project){
return $this;
}
$this->messages[]= Array(4, "Starting...");
$this->messages[]= Array($level, $msg);
}
/**
* This method has the responsability to understand (interpret) the code... this is the core
* @author Felipe Nascimento
* @name process
* @param [Project Object]
* @return MindProcessor Object
*/
private function process($project)
{
// again, we will use the global _MIND to have all the properties and methods as a singleton
GLOBAL $_MIND;
// lets log each step
$this->log(4, "Starting...");
// loading the language class, the interface and the selected idiom
$langDir= $_MIND['rootDir'].$_MIND['languageDir'].'/';
include($langDir.'language.php');
$lang= new Language($project->lang);
// two different classes we're gonna need here
include('table.php');
include('relation.php');
@@ -153,14 +163,19 @@
$this->fixedChars= $lang->fixedChars;
// identifying structures / subTypess
// e.g.: $sex:char(1, {F=Female|M=Male}).
$regExp= '\$\w[a-z0-9_]+:\w.+\)';
$this->sentences= preg_match_all('/'.$regExp.'/i', $project->wml, $matches);
// if there are subtypes, we will create a temp table to keep them
// we have to log it, too, and then parse it, as it was a simple attribute
if(sizeof($matches[0]) > 0)
{
$this->tables[$this->theWebMindLanguageTempTable]= new Table($this->theWebMindLanguageTempTable);
$matches= $matches[0];
$this->messages[]= Array(4, "Identifying subtypes...");
$this->log(4, "Identifying subtypes...");
// here, we will use all the identified subtypes, replacing with them in
// the lines where they were being used
for($i=0; $i<sizeof($matches); $i++)
{
$subTypesName= trim(substr($matches[$i], 1, strpos($matches[$i], ':')-1));
@@ -172,8 +187,11 @@
}
}
$this->messages[]= Array(4, "Analysing expressions...");
$this->log(4, "Analysing expressions...");
// here, we gotta parse our prepared sentences
// from now on, $this->sentences will be an array with each expression, already patternized
$this->sentences= $this->parse($project->wml);
// let's keep a copy of these sentences, before starting to change them
$originalSentences= $this->sentences;
// identify the "belong's
@@ -191,34 +209,44 @@
// identify the unique fields
$regExp= trim(implode('|', $lang->unique));
$this->sentences= preg_replace('/'.$regExp.'/i', $this->unique, $this->sentences);
// applying fieldtypes
reset($this->types);
$this->messages[]= Array(4, "Specifying attributes");
$this->log(4, "Specifying attributes");
while($cur= current($this->types))
{
if(isset($lang->types[$cur]))
if(is_array($lang->types[$cur]))
{
// first of all, we have to prepare our regular expression
$regExp= trim(implode('|', $lang->types[$cur]));
$regExp= str_replace('|', '\(|:', $regExp);
// and then, apply it to the sentences
// the result will be a code following theWebMind's rules
$this->sentences= preg_replace('/:'.$regExp.'/i', ':'.$cur.'(', $this->sentences);
}
next($this->types);
}
// the same will be done here, to identify the quantifiers identificators (like "or", for example)
$regExp= trim(implode('|', $lang->quantifiersId));
$this->sentences= preg_replace('/'.$regExp.'/i', $this->quantifierId, $this->sentences, 0);
$this->tmpSentences= $this->sentences;
// now, we will use a copy of the sentences, and will clean the array used before
$s= sizeof($this->tmpSentences);
$this->sentences= false;
$this->sentences= Array();
// preparing quantifiers regular expressions
$regExpQmm= (trim(implode('|', $lang->quantifiers['min']['min'])));
$regExpQmM= (trim(implode('|', $lang->quantifiers['min']['max'])));
$regExpQMm= (trim(implode('|', $lang->quantifiers['max']['min'])));
$regExpQMM= (trim(implode('|', $lang->quantifiers['max']['max'])));
$regExpQ= trim(implode('|', $lang->quantifiersId));
// let's iterate all the expressions
// $s was used to "cache" the size during the loop
$this->currentLine= 0;
for($i=0; $i<$s; $i++)
{
@@ -228,6 +256,13 @@
$extends= false;
$abstract= false;
// the verbs are the key... let's work with them, before continuing
/*
* There are three main verb types
* the possessive, mandatory and relational
* These possibilities are represented as VERB, BELONG and OBLIGATION and
* depending on them, Mind will decide how to deal with each relation
*/
if(trim($this->tmpSentences[$i]) != '' && preg_match('/'.preg_quote($this->verbId).'/', $this->tmpSentences[$i]))
{
$continue= true;
@@ -242,12 +277,17 @@
}else{
if(trim($this->currentLine) != '')
{
$this->messages[]= Array(3, "Expression with no known verb:<img src='images/engine.gif' align='right' style='cursor:poniter;' alt='Specify the verb manually' title='Specify the verb manually' onclick='Mind.Project.AddVerb(event, this);'/><br/><i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"" . $this->currentLine."\"</i>");
$this->log(3, "Expression with no known verb:<img src='images/engine.gif' align='right' style='cursor:poniter;'".
"alt='Specify the verb manually' title='Specify the verb manually' onclick='Mind.Project.AddVerb(event, ".
"this);'/><br/><i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"".
$this->currentLine."\"</i>");
$this->warnings++;
}
}
// if a verb was found
if($continue)
{
// we have to divide the expression by two using the verb
$curExpression= explode($this->verbId, $this->tmpSentences[$i]);
if(sizeOf($curExpression)==1)
$curExpression= explode($this->belongsId, $this->tmpSentences[$i]);
@@ -258,42 +298,52 @@
$delimiter= strrpos(trim($curExpression[0]), ' ');
if(!$delimiter) $delimiter= 0;
$curExpression[0]= trim(substr($curExpression[0], $delimiter, strlen($curExpression[0])-$delimiter)); // got the left entity
// defining if it has an attribute or another entity
$regExp= implode('|', $this->types);
$regExp= str_replace('|', '\(|', $regExp);
//print_r($curExpression);
/*
* from now, the $curExpression has in the first half,
* the left table, and in the second, the definition of
* an attribute or another entity
*/
// if there is not a second half, it means the only matched verb was the last valid word
// then, we will skip this expression
if(!isset($curExpression[1]))
continue;
$regExp= implode('|', $this->types);
$regExp= str_replace('|', '\(|', $regExp);
$ext= '';
// is this and attribute or what?
if(preg_match('/:'.$regExp.'/', $curExpression[1], $matches))
{ // it is an attribute
{
// this is an attribute
$matches= $matches[0];
}else{
// no, this is "what"
$ext= ($abstract)? $this->obligationId: (($extends)? $this->belongsId: '');
$curExpression[1]= preg_replace('/ ('.$regExpQ.') /i', $this->quantifierId, $curExpression[1], 1);
$curExpression[1]= preg_split('/'.preg_quote($this->quantifierId).'/', $curExpression[1]);
if(sizeof($curExpression[1]) == 1) // had not an OR statemant, then, the minimum quantifier is aplied
if(sizeof($curExpression[1]) == 1)
{
// had not an OR statemant, then, the minimum quantifier is aplied
$curExpression[1]= $this->quantifiers['min']['min'].$this->quantifierId.$curExpression[1][0];
else{
}else{
$exp= '/^( +)?('.$regExpQmm.')/i';
$curExpression[1][0]= preg_replace($exp, $this->quantifiers['min']['min'], $curExpression[1][0]);
$exp= '/^( +)?('.$regExpQmM.')/i';
$curExpression[1][0]= preg_replace($exp, $this->quantifiers['min']['max'], $curExpression[1][0], 1);
$curExpression[1]= implode($this->quantifierId, $curExpression[1]);
}
}
$exp= '/ ('.$regExpQMm.') /i';
$curExpression[1]= preg_replace($exp, $this->quantifiers['max']['min'], $curExpression[1], 1);
$exp= '/ ('.$regExpQMM.') /i';
$curExpression[1]= preg_replace($exp, $this->quantifiers['max']['max'], $curExpression[1], 1);
}
// let's use only the word next to the delimiter, as the riht entity's name
// let's use only the word next to the delimiter, as the right entity's name
if(strpos($curExpression[1], $this->quantifierId)) // if it is not an attribute definition
{
if(strpos($curExpression[1], $this->quantifiers['max']['min']))
@@ -307,28 +357,28 @@
$curExpression[1]= str_replace($this->quantifierId, $this->quantifierId.$this->quantifiers['max']['max'], $curExpression[1]);
$sharp= $this->quantifiers['max']['max'];
}
//echo $curExpression[1].'<hr>';
$curExpression[1] = explode($sharp, $curExpression[1]);
$curExpression[1][1]= explode(' ', trim($curExpression[1][1]));
//echo '<pre>'; print_r($curExpression[1][1]);
$curExpression[1][1]= $curExpression[1][1][0];
$curExpression[1] = implode($sharp, $curExpression[1]);
}
/**/
$curExpression= implode($this->verbId.$ext, $curExpression);
$this->sentences[]= $curExpression;
$this->execExpression($curExpression);
}
}
$this->messages[]= Array(4, "Treating cardinalities");
$this->log(4, "Treating cardinalities");
reset($this->relations);
$rels= Array(); // final array of valid relations
// now, we gotta use only the valid tables and relations
$rels= Array(); // this is going to be the final array of valid relations
$tables= Array();
while($rel= current($this->relations))
{
// here, we will check if already exists a relation between these entities, in opposite directions
// if it does exist, AND the relation here is N, then this is a N/N relation between these entities
if(isset($this->relations[$rel->rightTable.'|'.$rel->leftTable]) && $rel->max== 'n')
{
$tmpTable= $rel->leftTable.'_'.$rel->rightTable;
@@ -339,6 +389,9 @@
$this->tables[$rel->leftTable]->refered[]= $tmpRelation;
$this->tables[$rel->leftTable]->weight++;
// we have to create a new table to link both entities
// and also, two new relations
$tmpRelation= $rel->rightTable.'|'.$tmpTable;
$rels[$tmpRelation]= new Relation($tmpRelation);
$rels[$tmpRelation]->min= 0;
@@ -356,17 +409,21 @@
else{
}
$this->messages[]= Array(2, "Relation n/n between \"".$rel->leftTable."\" and \"".$rel->rightTable."\". I have to create a new table, \"".$tmpTable."\", to link them.");
$this->log(2, "Relation n/n between \"".$rel->leftTable.
"\" and \"".$rel->rightTable.
"\". I have to create a new table, \"".$tmpTable.
"\", to link them.");
$tables[$tmpTable]->addForeignKey($rel->leftTable);
$tables[$tmpTable]->addForeignKey($rel->rightTable);
// after that, we must remove the old relation between these two entities
$tables[$rel->rightTable]->removeForeignKey($rel->leftTable);
$tables[$rel->leftTable]->removeForeignKey($rel->rightTable);
unset($this->relations[$rel->rightTable.'|'.$rel->leftTable]);
}else{ // n/1 or 1/n or 1/1 => OK
}else{ // n/1 or 1/n or 1/1
$rels[$rel->name]= $rel;
// here, we have a commom relation between tables
if(!isset($tables[$rel->leftTable]))
$tables[$rel->leftTable]= $this->tables[$rel->leftTable];
if(!isset($tables[$rel->rightTable]))
@@ -380,13 +437,16 @@
}
next($this->relations);
}
if(sizeof($tables) == 0)
{
$this->messages[]= Array(0, "There are no entities in your project!");
$this->messages[]= Array(2, "Is the project running with the correct idiom?");
$this->messages[]= Array(2, "You can check if you haven't forgoten any \".\" or \";\" in the end of any line.");
$this->log(0, "There are no entities in your project!");
$this->log(2, "Is the project running with the correct idiom?");
$this->log(2, "You can check if you haven't forgoten any \".\" or \";\" in the end of any line.");
$this->errors++;
}else{
// here, any table that neither is pointed by nor points to another table will be removed
// it only happens if, of course, the size of tables decreased after the analysis
if(sizeof($this->tables) > sizeof($tables))
{
reset($tables);
@@ -394,7 +454,9 @@
{
if(!isset($tables[$table->name]) && $table->name != $this->theWebMindLanguageTempTable)
{
$this->messages[]= Array(3, '"'.$table->name.'" has no relation with any other entity. I will ignore it and will not create any "floating" table for it, or any output.');
$this->log(3, '"'.$table->name.
'" has no relation with any other entity. I will ignore it and will not '.
'create any "floating" table for it, or any output.');
$this->warnings++;
}
next($this->tables);
@@ -402,19 +464,25 @@
}
}
// now, we update the real table list
$this->tables= $tables;
$this->relations= $rels;
// we have to treat the 1/1 relations
reset($this->relations);
while($rel= current($this->relations))
{
if(isset($this->relations[$rel->rightTable.'|'.$rel->leftTable]))
{
if($rel->max == '1') // 1/1
// if there is a relation as specified with the last if and the current relation has the
// maximum of 1, then the relation is obviously 1/1
if($rel->max == '1')
{
// in this case, we will, for default, put one of the tables in evidence (the one which is more relevant to the application)
$evidence= &$this->tables[(($this->tables[$rel->leftTable]->weight > $this->tables[$rel->rightTable]->weight)? $rel->leftTable: $rel->rightTable)];
$other= &$this->tables[(($evidence->name == $rel->leftTable)? $rel->rightTable: $rel->leftTable)];
// then, the less relevant will have its atrtributes moved to the evidenced one
if(!isset($this->relations[$rel->leftTable.'|'.$rel->leftTable]) && $rel->rightTable != $rel->leftTable)
{
foreach($other->attributes as $att)
@@ -422,7 +490,9 @@
$att->name= $other->name.'_'.$att->name;
$evidence->attributes[$att->name]= $att;
}
// remove the relations between the evidenced table and the table that will be removed
// also, any relation this less relevant entity had must be moved to the other table
// (both, those which point to it, and those which point from it)
$other->refered= preg_replace('/'.$other->name.'/', $evidence->name, $other->refered);
$evidence->refered= array_merge($evidence->refered, $other->refered);
@@ -437,7 +507,7 @@
$evidence->removeForeignKey($other->name);
$other->removeReference($evidence->name.'|'.$evidence->name);
// fixing the tables pointed by the table that no longer exist
// fixing the tables pointed by the table that no longer exists
foreach($other->foreignKeys as $fk)
{
$this->tables[$fk[1]]->refered= preg_replace('/'.$other->name.'/', $evidence->name, $this->tables[$fk[1]]->refered);
@@ -445,14 +515,12 @@
$this->tables[$fk[1]]->removeReference($fk[1].'|'.$other->name);
}
// fixing the tables that were pointing to the table that no longer exist
// fixing the tables that were pointing to the table that no longer exists
foreach($other->refered as $ref)
{
$ref= explode('|', $ref);
$ref= $ref[1];
//echo '<pre>'; print_r($ref);
if(is_array($this->tables[$ref]->foreignKeys))
{
$this->tables[$ref]->foreignKeys[0]= preg_replace('/'.$other->name.'/', $evidence->name, $this->tables[$ref]->foreignKeys[0]);
@@ -462,9 +530,10 @@
}
// removing the table 'other', and the relations 1/1
$this->messages[]= Array(3, "Relation 1/1. The table <i>\"".$other->name.'"</i> has been removed. Its attributes were moved to "'.$rel->rightTable);
$this->log(3, "Relation 1/1. The table <i>\"".
$other->name.'"</i> has been removed. Its attributes were moved to "'.
$rel->rightTable);
$this->warnings++;
unset($this->tables[$other->name]);
unset($this->relations[$rel->leftTable.'|'.$rel->rightTable]);
@@ -475,6 +544,8 @@
next($this->relations);
}
// here, we will add to each table a primary key, as set in the choosen DBMS configuration
$this->log(4, "Dealing with Primary Keys");
reset($this->tables);
while($tab= current($this->tables))
{
@@ -489,11 +560,17 @@
$tmpAtt= $this->tables[$tab->name]->attributes;
$att= $this->tables[$tab->name]->addAttribute($att);
$this->tables[$tab->name]->attributes= array_merge(Array($att->name=>$att), $tmpAtt);
next($this->tables);
}
$this->messages[]= Array(4, "Exporting format to theWebMind's knowledge format");
// formating in WebMindLanguage (wml format)
$this->log(4, "Exporting format to theWebMind's knowledge format");
/* formating in WebMindLanguage (wml format)
* this is not being used YET... the idea is to build a "knowledge base center" with the main structure of many
* projects as people contribute to it. In the end, people will be able to start a project
* by its subject, loading automaticaly what most of the projects with that subject had
* I want to add some semanthic to it, and also the ability to learn with this base of knowledge
* Of course, any help is VERY welcome to reach this goal, too :)
*/
$this->verbId = trim(str_replace('|', '\|', $this->verbId));
$this->required = trim(str_replace('|', '\|', $this->required));
$this->quantifierId = trim(str_replace('|', '\|', $this->quantifierId));
@@ -509,24 +586,48 @@
$this->sentences= preg_replace('/'.trim($this->quantifiers['max']['max']).'/', '*}', $this->sentences);
$this->sentences= preg_replace('/'.trim($this->required).'/', 'not null', $this->sentences);
$this->sentences= preg_replace('/,( *)/', ',', $this->sentences);
// this structure, presented above is unders construction and may suffer modification
// here, we have to clear the mess and organize the house
$project->wml= trim(implode('
', $this->sentences));
$this->processedWML= '';
$this->tmpSentences= '';
$this->debug['status']= 1;
// messaging the end of the action, with its status
if($this->warnings == 0 && $this->errors == 0)
$this->messages[]= Array(1, "Final Status: Finished with no errors");
$this->log(1, "Final Status: Finished with no errors");
elseif($this->errors == 0)
{
$this->messages[]= Array(1, "Final Status: Finished with ".$this->warnings." warnings");
$this->log(1, "Final Status: Finished with ".$this->warnings." warnings");
}else{
$this->messages[]= Array(0, "<b>Final Status: Failed with ".$this->warnings." warning(s) and ".$this->errors.' error(s)</b>');
$this->log(0, "<b>Final Status: Failed with ".$this->warnings.
" warning(s) and ".$this->errors.' error(s)</b>');
}
$this->debug['messages']= $this->messages;
return $this;
}
/**
* This is the constructor
* if it receives a project object by parameter, it processes this project, otherwise, it simply returns itself
* with its current properties
* @author Felipe Nascimento
* @name __construct
* @param [Project Object]
* @return MindProcessor Object
*/
public function __construct($project=false) // obj of project
{
// if no project has been received, we simply return the new empty Object
if(!$project){
return $this;
}
// if a project Object has been sent to this method, then process it and return its result
return $this->process($project);
}
/**
* Get method to return the list of currently supported types
* @author Felipe Nascimento
@@ -589,44 +690,63 @@
*/
private function execExpression($mindExp)
{
// using the global _MIND to have access to its properties
GLOBAL $_MIND;
// keeping the original sentence, before changing it
$original_sentence= $mindExp;
if(strpos($mindExp, $this->quantifierId)) // it means it is a table relation
// let's check if it is a table relation
if(strpos($mindExp, $this->quantifierId))
{
// starting some variables
$selfReference= false;
$abstractLeftTable= false;
$abstractRightTable= false;
$oneByOneSelfRelation= false;
// here, everything we have is the important/useful part of the instruction
// in this case, we can do the following without fear
$mindExp= explode(' ', trim($mindExp));
// on a table relation, the first word is the left table
$leftTable= $this->filter(trim($mindExp[0]));
// and the left word is the secont entity
$rightTable= $this->filter(trim($mindExp[sizeof($mindExp)-1]));
/*
* if the name of right table has a ":" it means it is probably an attribute
* wrote with some mistake
* in this case, we will alert the developer about it
*/
if($pos = strpos($rightTable,':'))
{
$newTmpName= substr($rightTable, 0, $pos);
$tmpType= substr($rightTable, $pos+1, strpos($rightTable, '(') - ($pos+1));
$this->messages[]= Array(3, "Entity \"".$rightTable."\" renamed to \"".$newTmpName."\".".
"<img src='images/engine.gif' align='right' style='cursor:poniter;' alt='Add \"".$tmpType."\" as a type' title='Add \"".$tmpType."\" as a type'".
" onclick='Mind.Project.AddType(event, \"".$tmpType."\", ".JSON_encode($this->types).");'/>".
"<br/>I believe it should be a property, right? But I couldn't identify the type \"".$tmpType."\"!");
$this->log(3, "Entity \"".$rightTable."\" renamed to \"".$newTmpName."\".".
"<img src='images/engine.gif' align='right' style='cursor:poniter;' alt='Add \"".$tmpType.
"\" as a type' title='Add \"".$tmpType."\" as a type'".
" onclick='Mind.Project.AddType(event, \"".$tmpType."\", ".JSON_encode($this->types).");'/>".
"<br/>I believe it should be a property, right? But I couldn't identify the type \"".$tmpType."\"!");
// anyways... we will fix the name to a valid one
$rightTable= $newTmpName;
$this->warnings++;
//continue;
}
if($leftTable == $rightTable) // entity that points to itself
// here, we find those entities which point to themselves
if($leftTable == $rightTable)
{
// acording to its cardinality, it destroys the righttable, or create another table
// to implement the relation
if(in_array(trim($this->quantifiers['max']['min']), $mindExp))
{
$rightTable= false;
}else{
$rightTable= $rightTable.'_pointer';
$rightTable= $rightTable.$_MIND['selfRelationalTable'];
}
$selfReference= true;
}
// verify if the current entity is set to be abstract
// verify if the current entity was set manually to be abstract
if(substr($leftTable, 0, 1) == '#')
{
$abstractLeftTable= true;
@@ -640,20 +760,17 @@
$rightTable= preg_replace('/^#/', '', $rightTable);
}
if(!isset($this->tables[$rightTable]))
{ // the same with both entities
{
$this->tables[$rightTable]= new Table($rightTable);
}
}
// verifies if the entity does not exist, yet
if(!isset($this->tables[$leftTable]))
{ // then, creat it
{
// then, creat it
$this->tables[$leftTable]= new Table($leftTable);
}
if($abstractLeftTable)
$this->tables[$leftTable]->abstract= true;
if(!$rightTable)
{
if(!isset($this->relations[$leftTable.'|'.$leftTable]))
@@ -664,7 +781,7 @@
}
// let's see if this entity should extend another one
//echo implode(',', $mindExp).'\n </br/>';
// it depends on the type of verb, used to identify the relation
if($rightTable && preg_match('/'.preg_quote(trim($this->obligationId)).'/', implode(',', $mindExp)) > 0)
{
$this->tables[$leftTable]->extends= $rightTable;
@@ -674,26 +791,35 @@
if($rightTable && preg_match('/'.preg_quote(trim($this->belongsId)).'/', implode(',', $mindExp)) > 0)
{
$this->tables[$rightTable]->extends= $leftTable;
//$this->tables[$rightTable]->abstract= true;
}
// are they abstract?
if($abstractLeftTable)
$this->tables[$leftTable]->abstract= true;
if($abstractRightTable)
$this->tables[$rightTable]->abstract= true;
// treating cardinalities
$min= (in_array(trim($this->quantifiers['min']['min']), $mindExp))? '0': '1';
$max= (in_array(trim($this->quantifiers['max']['min']), $mindExp))? '1': 'n';
// deciding for the name this relation will have
if($rightTable)
$relName= ($max=='n')? $leftTable.'|'.$rightTable: $rightTable.'|'.$leftTable;
else
$relName= false;
// in case of self reference
if($selfReference)
{
// if it is not 1/1 to the same table
if(!$oneByOneSelfRelation)
{
if(!isset($this->relations[$relName]))
{
$att= new Attribute('main_'.$leftTable);
// we have to create a new table, and point it to the first one twice
// one to the current ID, and another to the reference
$att= new Attribute($_MIND['parentOnSelfRelation'].$leftTable);
$att->required= 1;
$att->unique= 0;
$att->type= 'integer';
@@ -705,79 +831,95 @@
$this->tables[$rightTable]->addAttribute($att);
}
}else{
// otherwise, Mind simply needs to have the first table referencing itself
$this->tables[$leftTable]->addForeignKey($leftTable);
}
}
// dealing with the the relation between entities
// creating the new relation
if($relName)
{
$this->relations[$relName]= new Relation($relName);
$this->relations[$relName]->min= $min;
$this->relations[$relName]->max= $max;
}
}else{ // attributes
}else{ // this is an attribute
$mindExp= explode(trim($this->verbId), $mindExp);
// firstly, we gotta create the left table, if it does not exist
$leftTable= $this->filter(trim($mindExp[0]));
if(!isset($this->tables[$leftTable]))
{
$this->tables[$leftTable]= new Table($leftTable);
}
// here, we will divide the attribute name of the rest
$mindExp= explode(':', $mindExp[1], 2);
$attName= explode(' ', trim($mindExp[0]));
$attName= $attName[sizeof($attName)-1];
if(!isset($mindExp[1]))
{
trigger_error('Undefined verb in the sentence: <b>'. $this->currentLine.'</b> at line <b>'. $this->currentLineNumber .'</b>',
E_USER_WARNING);
return false;
}
// let's parse the atribute properties
$mindExp= explode('(', $mindExp[1], 2);
$att= new Attribute($this->filter($attName));
/*
* Notice that, each property we set, must be removed from the
* expression, to not be processed twice
*/
// attributes with # will set as hidden, to the module
if(substr($att->name, 0,1) == '#')
{
$att->hidden= true;
$att->name= preg_replace('/^#/', '', $att->name);
}
if(strpos($mindExp[1], trim($this->required))) // if it's a required field
// Is this a required field?
if(strpos($mindExp[1], trim($this->required)))
{
$mindExp[1]= str_replace(trim($this->required), '', $mindExp[1]);
$att->required= 1;
}else{
$att->required= 0;
}
if(strpos($mindExp[1], trim($this->unique))) // if it's unique
// is it unique?
if(strpos($mindExp[1], trim($this->unique)))
{
$mindExp[1]= str_replace(trim($this->unique), '', $mindExp[1]);
$att->unique= 1;
}else{
$att->unique= 0;
}
// the type is the word which is before "("
$att->type= trim($mindExp[0]);
preg_match('/([^(\\\)])?"(.*)[^(\\\)]"/', preg_replace('/\)/', ') ', $mindExp[1]), $matches); // get the default value to the current attribute ( between "" )
// Let's get the default value to the current attribute ( between "" )
preg_match('/([^(\\\)])?"(.*)[^(\\\)]"/', preg_replace('/\)/', ') ', $mindExp[1]), $matches);
if(sizeof($matches)>0)
{
// if it does have a default value, we have to prepare it
$att->defaultValue= addslashes(preg_replace('/^("|.")|"$/', '', trim($matches[0])));
// default values may be executable, the "Exec:" keyword is required, then
if(substr($att->defaultValue, 0, 5) != "Exec:")
$att->defaultValue= "'".trim($att->defaultValue)."'";
else
$att->defaultValue= preg_replace('/^Exec:/', '', trim($att->defaultValue));
// removing the default value
$mindExp[1]= str_replace($matches[0], '', $mindExp[1]);
}
preg_match('/[^(\\\)]\[(.*)[^(\\\)]\]/', $mindExp[1], $matches); // get the mask for attribute ( betwee [] )
// checking for masks ( between [ ] )
preg_match('/[^(\\\)]\[(.*)[^(\\\)]\]/', $mindExp[1], $matches);
if(sizeof($matches)>0)
{
$mindExp[1]= str_replace($matches[0], '', $mindExp[1]);
$att->mask= preg_replace('/^(\[|.\[)|\]$/', '', trim($matches[0]));
}
// looking for comments the attribute have (identified by the use of // )
preg_match('/\/\/.*$/', $mindExp[1], $matches);
if(sizeof($matches)>0)
{
@@ -785,25 +927,35 @@
$att->comment= $matches[0];
}
preg_match('/[^(\\\)]\{(.*)[^(\\\)]\}/', $mindExp[1], $matches); // get the options for attribute ( between {} )
// get the options for attribute ( between { } )
preg_match('/[^(\\\)]\{(.*)[^(\\\)]\}/', $mindExp[1], $matches);
if(sizeof($matches)>0)
{
/* if there are valid options, we have to parse them
* the pattern is just like this:
* code=label|anotherCode=AnotherLabel
* E.g.: {F=Female|M=Male}
*/
$matches[0]= preg_replace('/^(\{|.\{)|\}$/', '', trim($matches[0]));
$mindExp[1]= str_replace($matches[0], '', $mindExp[1]);
$matches= preg_split('/(\|)/', $matches[0]); // parses the options, separated by |, using = to especify any value/label
$matches= preg_split('/(\|)/', $matches[0]);
$att->options= $matches;
for($i=0; $i<sizeof($att->options);$i++)
{
$att->options[$i]= explode('=', $att->options[$i], 2);
}
}
// te attribute size is the number that rested, parsed as real
$att->size= (real)$mindExp[1];
// finally, add the attribute to the global list of attributes and also to the current table
// if the same attribute was already used, with the same characteristics, we tell the developer
if(isset($this->globalAttributeList[$att->name]) && $this->globalAttributeList[$att->name] == $att)
$this->messages[]= Array(2, "Attribute \"".$att->name."\" used more than one time, with the same carachteristics.<br/>Aren't they the same property? You could set both in the same table, or in a new table creating an agreggation.");
$this->log(2, "Attribute \"".$att->name."\" used more than one time, with the same carachteristics.<br/>Aren't they the same property? You could set both in the same table, or in a new table creating an agreggation.");
$this->globalAttributeList[$att->name]= $att;
$this->tables[$leftTable]->addAttribute($att);
}
}
}
?>
@@ -1,4 +1,4 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE adodb_schema [
<!ELEMENT schema (table*, sql*)>
<!ATTLIST schema version CDATA #REQUIRED>