Skip to content

Commit

Permalink
Feature/issue 459, underscores in name of concept (#490)
Browse files Browse the repository at this point in the history
* Haskell-side changes for issue #459

* releasenotes

* #459 backend changes. concept name devided into escaped identifier (name) and unescaped name (label)

* Replace concept name as function param by concept object

* Replace concept param of new Atom constructor from string to Concept object

* Replace concept param of getRelation from string to Concept object

* Bugfix missing semicolon
  • Loading branch information
Michiel-s committed Jul 26, 2016
1 parent 094c7ba commit 40accc7
Show file tree
Hide file tree
Showing 22 changed files with 212 additions and 175 deletions.
3 changes: 2 additions & 1 deletion ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Release notes of Ampersand

## unreleased changes
* Performance enhancement: Added indexes on table columns when possible
* [Issue #488](https://github.com/AmpersandTarski/Ampersand/issues/488) Performance enhancement: Added indexes on table columns when possible
* [Issue #459](https://github.com/AmpersandTarski/Ampersand/issues/459) fix for underscores in Concept name

## v3.6.0 (8 july 2016)
* [Issue #406](https://github.com/AmpersandTarski/Ampersand/issues/406) Minor changes on syntax of INTERFACE statement.
Expand Down
14 changes: 8 additions & 6 deletions src/Database/Design/Ampersand/Output/ToJSON/Concepts.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import Data.List(nub)

data Concepts = Concepts [Concept] deriving (Generic, Show)
data Concept = Concept
{ cptJSONname :: String
{ cptJSONid :: String
, cptJSONlabel :: String
, cptJSONtype :: String
, cptJSONgeneralizations :: [String]
, cptJSONspecializations :: [String]
Expand Down Expand Up @@ -53,10 +54,11 @@ instance JSON FSpec Concepts where
fromAmpersand fSpec _ = Concepts (map (fromAmpersand fSpec) (concs fSpec))
instance JSON A_Concept Concept where
fromAmpersand fSpec cpt = Concept
{ cptJSONname = name cpt
{ cptJSONid = escapeIdentifier . name $ cpt
, cptJSONlabel = name cpt
, cptJSONtype = show . cptTType fSpec $ cpt
, cptJSONgeneralizations = map name . largerConcepts (vgens fSpec) $ cpt
, cptJSONspecializations = map name . smallerConcepts (vgens fSpec) $ cpt
, cptJSONgeneralizations = map (escapeIdentifier . name) . largerConcepts (vgens fSpec) $ cpt
, cptJSONspecializations = map (escapeIdentifier . name) . smallerConcepts (vgens fSpec) $ cpt
, cptJSONaffectedConjuncts = map rc_id . fromMaybe [] . lookup cpt . allConjsPerConcept $ fSpec
, cptJSONinterfaces = map name . filter hasAsSourceCpt . interfaceS $ fSpec
, cptJSONdefaultViewId = fmap name . getDefaultViewForConcept fSpec $ cpt
Expand All @@ -73,11 +75,11 @@ instance JSON A_Concept TableCols where
[t] -> if name t == name cptTable
then map (attName . snd) cols
else fatal 78 $ "Table names should match: "++name t++" "++name cptTable++"."
_ -> fatal 79 $ "All concepts in a typology should be in exactly one table."
_ -> fatal 79 "All concepts in a typology should be in exactly one table."
}
where
cols = concatMap (lookupCpt fSpec) $ cpt : largerConcepts (vgens fSpec) cpt
cptTable = case lookupCpt fSpec $ cpt of
cptTable = case lookupCpt fSpec cpt of
[(table,_)] -> table
[] -> fatal 80 $ "Concept `"++name cpt++"` not found in a table."
_ -> fatal 81 $ "Concept `"++name cpt++"` found in multiple tables."
Expand Down
8 changes: 4 additions & 4 deletions src/Database/Design/Ampersand/Output/ToJSON/Interfaces.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ data JSONCruds = JSONCruds
, crudJSONdelete :: Bool
} deriving (Generic, Show)
data JSONexpr = JSONexpr
{ exprJSONsrcConcept :: String
, exprJSONtgtConcept :: String
{ exprJSONsrcConceptId :: String
, exprJSONtgtConceptId :: String
, exprJSONisUni :: Bool
, exprJSONisTot :: Bool
, exprJSONisIdent :: Bool
Expand Down Expand Up @@ -100,8 +100,8 @@ instance JSON Cruds JSONCruds where

instance JSON ObjectDef JSONexpr where
fromAmpersand fSpec object = JSONexpr
{ exprJSONsrcConcept = name srcConcept
, exprJSONtgtConcept = name tgtConcept
{ exprJSONsrcConceptId = escapeIdentifier . name $ srcConcept
, exprJSONtgtConceptId = escapeIdentifier . name $ tgtConcept
, exprJSONisUni = isUni normalizedInterfaceExp
, exprJSONisTot = isTot normalizedInterfaceExp
, exprJSONisIdent = isIdent normalizedInterfaceExp
Expand Down
24 changes: 12 additions & 12 deletions src/Database/Design/Ampersand/Output/ToJSON/Relations.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import Data.Maybe

data Relations = Relations [Relation]deriving (Generic, Show)
data Relation = Relation
{ relJSONname :: String
, relJSONsignature :: String
, relJSONsrcConcept :: String
, relJSONtgtConcept :: String
, relJSONuni :: Bool
, relJSONtot :: Bool
, relJSONinj :: Bool
, relJSONsur :: Bool
, relJSONprop :: Bool
{ relJSONname :: String
, relJSONsignature :: String
, relJSONsrcConceptId :: String
, relJSONtgtConceptId :: String
, relJSONuni :: Bool
, relJSONtot :: Bool
, relJSONinj :: Bool
, relJSONsur :: Bool
, relJSONprop :: Bool
, relJSONaffectedConjuncts :: [String]
, relJSONmysqlTable :: RelTableInfo
, relJSONmysqlTable :: RelTableInfo
} deriving (Generic, Show)
data RelTableInfo = RelTableInfo -- Contains info about where the relation is implemented in SQL
{ rtiJSONname :: String
Expand All @@ -47,8 +47,8 @@ instance JSON Declaration Relation where
fromAmpersand fSpec dcl = Relation
{ relJSONname = name dcl
, relJSONsignature = name dcl ++ (show . sign) dcl
, relJSONsrcConcept = name . source $ dcl
, relJSONtgtConcept = name . target $ dcl
, relJSONsrcConceptId = escapeIdentifier . name . source $ dcl
, relJSONtgtConceptId = escapeIdentifier . name . target $ dcl
, relJSONuni = isUni dcl
, relJSONtot = isTot dcl
, relJSONinj = isInj dcl
Expand Down
22 changes: 11 additions & 11 deletions src/Database/Design/Ampersand/Output/ToJSON/Rules.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ data Rules = Rules
, rulJSONsignals :: [JsonRule]
} deriving (Generic, Show)
data JsonRule = JsonRule
{ rulJSONname :: String
, rulJSONruleAdl :: String
, rulJSONorigin :: String
, rulJSONmeaning :: String
, rulJSONmessage :: String
, rulJSONsrcConcept :: String
, rulJSONtgtConcept :: String
, rulJSONconjunctIds :: [String]
, rulJSONpairView :: Maybe JsonPairView
{ rulJSONname :: String
, rulJSONruleAdl :: String
, rulJSONorigin :: String
, rulJSONmeaning :: String
, rulJSONmessage :: String
, rulJSONsrcConceptId :: String
, rulJSONtgtConceptId :: String
, rulJSONconjunctIds :: [String]
, rulJSONpairView :: Maybe JsonPairView
} deriving (Generic, Show)
data JsonPairView = JsonPairView [JsonPairViewSegment]
deriving (Generic, Show)
Expand Down Expand Up @@ -55,8 +55,8 @@ instance JSON Rule JsonRule where
, rulJSONorigin = show.rrfps $ rule
, rulJSONmeaning = showMeaning
, rulJSONmessage = showMessage
, rulJSONsrcConcept = name . source . rrexp $ rule
, rulJSONtgtConcept = name . target . rrexp $ rule
, rulJSONsrcConceptId = escapeIdentifier . name . source . rrexp $ rule
, rulJSONtgtConceptId = escapeIdentifier . name . target . rrexp $ rule
, rulJSONconjunctIds = map rc_id $ fromMaybe [] (lookup rule $ allConjsPerRule fSpec)
, rulJSONpairView = fmap (fromAmpersand fSpec) (rrviol rule)
}
Expand Down
4 changes: 2 additions & 2 deletions src/Database/Design/Ampersand/Output/ToJSON/Views.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Database.Design.Ampersand.Output.ToJSON.Concepts
data Views = Views [View] deriving (Generic, Show)
data View = View
{ vwJSONlabel :: String
, vwJSONconcept :: String
, vwJSONconceptId :: String
, vwJSONisDefault :: Bool
, vwJSONsegments :: [Segment]
} deriving (Generic, Show)
Expand All @@ -25,7 +25,7 @@ instance JSON FSpec Views where
instance JSON ViewDef View where
fromAmpersand fSpec vd = View
{ vwJSONlabel = name vd
, vwJSONconcept = name . vdcpt $ vd
, vwJSONconceptId = escapeIdentifier . name . vdcpt $ vd
, vwJSONisDefault = vdIsDefault vd
, vwJSONsegments = map (fromAmpersand fSpec) . vdats $ vd
}
Expand Down
7 changes: 4 additions & 3 deletions static/zwolle/api/v1/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@
foreach((array)$allAtoms as $cpt => $atoms) if(!empty($atoms)) Concept::getConcept($cpt);
foreach((array)$allLinks as $rel => $links) if(!empty($links)) Relation::getRelation($rel);

foreach((array)$allAtoms as $cpt => $atoms){
foreach((array)$allAtoms as $cpt => $atoms){
$concept = Concept::getConcept($cpt);
foreach($atoms as $atomId){
$atom = new Atom($atomId, $cpt);
$atom = new Atom($atomId, $concept);
$atom->addAtom();
}
}
Expand All @@ -81,7 +82,7 @@
foreach($links as $link){
if(is_null($link['src']) || is_null($link['tgt'])) continue; // skip

$relation->addLink(new Atom($link['src'], $relation->srcConcept->name), new Atom($link['tgt'], $relation->tgtConcept->name));
$relation->addLink(new Atom($link['src'], $relation->srcConcept), new Atom($link['tgt'], $relation->tgtConcept));
}
}

Expand Down
10 changes: 5 additions & 5 deletions static/zwolle/api/v1/resources.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
$roleIds = $app->request->params('roleIds');
$session->activateRoles($roleIds);

$resource = new Atom($resourceId, $resourceType);
$resource = new Atom($resourceId, Concept::getConcept($resourceType));

// Checks
if(!$session->isEditableConcept($resource->concept)) throw new Exception ("You do not have access for this call", 403);
Expand Down Expand Up @@ -77,7 +77,7 @@
$options = $app->request->params();
$ifcPath = implode ('/', $ifcPath);

$atom = new Atom($resourceId, $resourceType);
$atom = new Atom($resourceId, Concept::getConcept($resourceType));
$atomOrIfc = $atom->walkIfcPath($ifcPath);

$content = $atomOrIfc->getContent($options);
Expand Down Expand Up @@ -106,7 +106,7 @@

$ifcPath = implode ('/', $ifcPath);

$atom = new Atom($resourceId, $resourceType);
$atom = new Atom($resourceId, Concept::getConcept($resourceType));
$atom->topLevelIfcId = $topLevelIfcId;

// Create atom if not exists and crudC is allowed
Expand Down Expand Up @@ -138,7 +138,7 @@
$options = $app->request->params();
$ifcPath = implode ('/', $ifcPath);

$atom = new Atom($resourceId, $resourceType);
$atom = new Atom($resourceId, Concept::getConcept($resourceType));
$atomOrIfc = $atom->walkIfcPath($ifcPath);

// Perform create
Expand All @@ -163,7 +163,7 @@
$options = $app->request->params();
$ifcPath = implode ('/', $ifcPath);

$atom = new Atom($resourceId, $resourceType);
$atom = new Atom($resourceId, Concept::getConcept($resourceType));
$atomOrIfc = $atom->walkIfcPath($ifcPath);

// Perform delete
Expand Down
24 changes: 12 additions & 12 deletions static/zwolle/extensions/ExcelImport/ExcelImport.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private function ParseWorksheetWithIfc($worksheet, $ifc){
$highestcolumn = $worksheet->getHighestColumn();
$highestcolumnnr = PHPExcel_Cell::columnIndexFromString($highestcolumn);

$leftConcept = Concept::getConcept((string)$worksheet->getCell('A1'));
$leftConcept = Concept::getConceptByLabel((string)$worksheet->getCell('A1'));
if($leftConcept != $ifc->tgtConcept) throw new Exception("Target concept of interface '{$ifc->path}' does not match concept specified in cell {$worksheet->getTitle()}:A1", 500);

// Parse other columns of first row
Expand All @@ -133,8 +133,8 @@ private function ParseWorksheetWithIfc($worksheet, $ifc){
if(!$ifc->crudC) throw new Exception("Trying to create new atom in cell A{$row}. This is not allowed.", 403);
$leftAtom = $leftConcept->createNewAtom()->addAtom();
}else{
$leftAtom = new Atom($firstCol, $leftConcept->name);
if(!$leftAtom->atomExists() && !$ifc->crudC) throw new Exception("Trying to create new {$leftConcept->name} in cell A{$row}. This is not allowed.", 403);
$leftAtom = new Atom($firstCol, $leftConcept);
if(!$leftAtom->atomExists() && !$ifc->crudC) throw new Exception("Trying to create new {$leftConcept} in cell A{$row}. This is not allowed.", 403);
$leftAtom->addAtom();
}

Expand All @@ -152,8 +152,8 @@ private function ParseWorksheetWithIfc($worksheet, $ifc){
// the @ is a php indicator for a unix timestamp (http://php.net/manual/en/datetime.formats.compound.php), later used for typeConversion
if(PHPExcel_Shared_Date::isDateTime($cell) && !empty($cellvalue)) $cellvalue = '@'.(string)PHPExcel_Shared_Date::ExcelToPHP($cellvalue);

$rightAtom = new Atom($cellvalue, $header[$columnletter]->tgtConcept->name);
if(!$rightAtom->atomExists() && !$header[$columnletter]->crudC) throw new Exception("Trying to create new {$header[$columnletter]->tgtConcept->name} in cell {$columnletter}{$row}. This is not allowed.", 403);
$rightAtom = new Atom($cellvalue, $header[$columnletter]->tgtConcept);
if(!$rightAtom->atomExists() && !$header[$columnletter]->crudC) throw new Exception("Trying to create new {$header[$columnletter]->tgtConcept} in cell {$columnletter}{$row}. This is not allowed.", 403);

$header[$columnletter]->relation->addLink($leftAtom, $rightAtom, $header[$columnletter]->relationIsFlipped, 'ExcelImport');
}
Expand Down Expand Up @@ -244,10 +244,10 @@ private function ParseLines($lines){
// The cell contains either 'Concept' or '[Conceptx]' where x is a separator character (e.g. ';', ',', ...)
}elseif ((substr($cellvalue, 0, 1) == '[') && (substr($cellvalue, -1) == ']') ){
if($col == 0) throw new Exception ("Seperator character not allowed for first column of excel import. Specified '{$line[$col]}'", 500);
$concept[$col] = Concept::getConcept(substr($cellvalue, 1, -2));
$concept[$col] = Concept::getConceptByLabel(substr($cellvalue, 1, -2));
$separator[$col] = substr($cellvalue, -2, 1);
}else{
$concept[$col] = Concept::getConcept($cellvalue);
$concept[$col] = Concept::getConceptByLabel($cellvalue);
$separator[$col] = false;
}

Expand All @@ -256,10 +256,10 @@ private function ParseLines($lines){
if($relations[$col] == '' || $concept[$col] == ''){
$relations[$col] = null;
}elseif(substr($relations[$col], -1) == '~'){ // Relation is flipped is last character is a tilde (~)
$relations[$col] = Relation::getRelation(substr($relations[$col], 0, -1), $concept[$col]->name, $concept[0]->name);
$relations[$col] = Relation::getRelation(substr($relations[$col], 0, -1), $concept[$col], $concept[0]);
$flipped[$col] = true;
}else{
$relations[$col] = Relation::getRelation($relations[$col], $concept[0]->name, $concept[$col]->name);
$relations[$col] = Relation::getRelation($relations[$col], $concept[0], $concept[$col]);
$flipped[$col] = false;
}
}
Expand All @@ -272,7 +272,7 @@ private function ParseLines($lines){
// Determine left atom (column 0) of line
if ($line[0] == '') continue; // Don't process lines that start with an empty first cell
elseif ($line[0] == '_NEW') $leftAtom = $concept[0]->createNewAtom(); // Create a unique atom name
else $leftAtom = new Atom($line[0], $concept[0]->name);
else $leftAtom = new Atom($line[0], $concept[0]);

// Insert $leftAtom into the DB if it does not yet exist
$leftAtom->addAtom();
Expand All @@ -291,9 +291,9 @@ private function ParseLines($lines){
elseif ($cell == '_NEW') $rightAtoms[] = $leftAtom; // If the cell contains '_NEW', the same atom as the $leftAtom is used. Useful for property-relations
elseif($separator[$col]){
$atomsIds = explode($separator[$col],$cell); // atomnames may have surrounding whitespace
foreach($atomsIds as $atomId) $rightAtoms[] = new Atom(trim($atomId), $concept[$col]->name);
foreach($atomsIds as $atomId) $rightAtoms[] = new Atom(trim($atomId), $concept[$col]);
}else{
$rightAtoms[] = new Atom($line[$col], $concept[$col]->name); // DO NOT TRIM THIS CELL CONTENTS as it contains an atom that may need leading/trailing spaces
$rightAtoms[] = new Atom($line[$col], $concept[$col]); // DO NOT TRIM THIS CELL CONTENTS as it contains an atom that may need leading/trailing spaces
}

foreach ($rightAtoms as $rightAtom){
Expand Down
Loading

0 comments on commit 40accc7

Please sign in to comment.