How to define a map in Xcore - eclipse-emf

According to the EMF FAQ, it is possible to create a Map in EMF:
An EMap is basically a List of java.util.Map$Entry instances.
Therefore to create a Map you need to first model your map entry by
following these steps:
Create an EClass with the name [Type1]To[Type2]Map where [Type1] represents the key's type and the [Type2] represents the value's type.
Set the Instance Class Name property of the newly created EClass to java.util.Map$Entry.
Create an EAttribute or EReference named "key" and set the EDataType or EClass for it.
Create an EAttribute or EReference called "value" and set the EDataType or EClass for it.
Now, when you create an EReference somewhere that uses this map entry
class as its EClass, the EMF code generator will detect this special
case and generate a properly typed EMap getter/setter for you instead
of a normal EList getter/setter.
Can I use this with Xcore models? I am not sure whether step #2 is doable in Xcore or whether it supports maps at all.

For me this works.
DataPoints.xcore:
...
class KeyValuePair wraps java.util.Map$Entry {
String key
String value
}
class KeyValueList {
contains KeyValuePair[] entries
}
The above results in a KeyValueListImpl class with a getEntries method that looks like this:
public EMap<String, String> getEntries() {
if (entries == null) {
entries = new EcoreEMap<String,String>(DataPointsPackage.Literals.KEY_VALUE_PAIR, KeyValuePairImpl.class, this, DataPointsPackage.KEY_VALUE_LIST__ENTRIES);
}
return entries;
}

Related

How to set list of map into javafx table view

The following code snippets show the declarations of the fields and how I set up the table.
Please tell me what went wrong. The data is not getting displayed.
#FXML
private TableColumn<Map<String, Object>, String> productNameCol ;
#FXML
private TableColumn<Map<String,Object>, String> requestedBarcodeCol;
#FXML
private TableColumn<Map<String,Object>, String> pickedBarcodeCol;
productNameCol.setCellValueFactory(new PropertyValueFactory<Map<String,Object>,String>("ProductName"));
requestedBarcodeCol.setCellValueFactory(new PropertyValueFactory<Map<String,Object>,String>("ActualBarcode"));
pickedBarcodeCol.setCellValueFactory(new PropertyValueFactory<Map<String,Object>,String>("PickedBarcode"));
requestedQuantityCol.setCellValueFactory(new PropertyValueFactory<Map<String,Object>,String>("ActualQuantity"));
actualQuantityCol.setCellValueFactory(new PropertyValueFactory<Map<String,Object>,String>("PickedQuantity"));
unMatchDataTableView.setItems(FXCollections.observableArrayList(unmatchedBarcodeMap));
Since the question does not contain a MCVE, I've got to make some assumptions; the solution I present may not work without modifications. Those are my assumptions:
unmatchedBarcodeMap is non-empty
The controller is properly used when loading the fxml
The fields contain the instances used in the TableView that is displayed on screen
PropertyValueFactory uses getters or property getters to retrieve values. These are not available for Map:
Let <property> denote the string passed to the PropertyValueFactory and <Property> the same string but with the first char converted to upper case:
PropertyValueFactory looks for a method named <property>Property that returns a ObservableValue containing the value to be displayed in the column first. If such a method exists, the result of invoking the method on the row item is returned from the call method. If this method is not available, PropertyValueFactory looks for a method named get<Property>; If this method is available, the result of invoking the method for the row item is wrapped in a ObservableValue object and returned from the call method. Otherwise null is returned resulting in an empty cell.
You need to use MapValueFactory instead of PropertyValueFactory to retrieve values from the Maps:
productNameCol.setCellValueFactory((Callback) new MapValueFactory("ProductName"));
...
This displays the result of calling using rowItem.get("ProductName") in the productNameCol column.

Manually set ID (PK) using QxOrm

I have created a new object, set the values (including the ID/PK) but when I use qx::dao::insert, it ignores the ID I have specified.
How can I specify the PK value of the row I want to persist?
I think you have defined your primary key as auto-increment (this is the default value for numeric types with QxOrm library).
If you want to define the primary key yourself before inserting an instance to database, register your ID like this :
template <>
void register_class(QxClass<MyClass> & t)
{
qx::IxDataMember * pId = t.id(& MyClass::m_my_id, "my_id");
pId->setAutoIncrement(false);
// etc...
}

Querying instances contained in a list

I have created a list (dd) which contains instances of a class. I want to be able to perform queries on some of its attributes (eg. finding the smallest numeric value), but cannot find a way to do this using the functionality of the class (I feel like going back to analysing the data by column). How do I access the values in one of the attributes when my instances are now on a list? Thanks!
Assuming you're using C# and having a class like this
class Foo
{
public double Bar { get; set; }
}
then LINQ is exactly what you are looking for
List<Foo> list = GetList();
var filtered = list.Where(p => p.Bar > 23.0);
Have a look at these examples:
https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

SQLAlchemy Reflection Using Metaclass with Column Override

I have a set of dynamic database tables (Postgres 9.3 with PostGIS) that I am mapping using a python metaclass:
cls = type(str(tablename), (db.Model,), {'__tablename__':tablename})
where, db.Model is the db object via flask-sqlalchemy and tablename is a bit of unicode.
The cls is then added to an application wide dictionary current_app.class_references (using Flask's current_app) to avoid attempts to instantiate the class multiple times.
Each table contains a geometry column, wkb_geometry stored in Well Known Binary. I want to map these to use geoalchemy2 with the final goal of retrieving GeoJSON.
If I was declaring the table a priori, I would use:
class GeoPoly():
__tablename__ = 'somename'
wkb_geometry = db.Column(Geometry("POLYGON"))
#more columns...
Since I am trying to do this dynamically, I need to be able to override the reflection of cls1 with the known type.
Attempts:
Define the column explicitly, using the reflection override syntax.
cls = type(str(tablename), (db.Model,), {'__tablename__':tablename,
'wkb_geometry':db.Column(Geometry("POLYGON"))})
which returns the following on a fresh restart, i.e. the class has not yet been instantiated:
InvalidRequestError: Table 'tablename' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object
Use mixins with the class defined above (sans tablename):
cls = type(str(tablename), (GeoPoly, db.Model), {'__tablename__':tablename})
Again MetaData issues.
Override the column definition attribute after the class is instantiated:
cls = type(str(tablename), (db.Model,), {'__tablename__':tablename})
current_app.class_references[tablename] = cls
cls.wkb_geometry = db.Column(Geometry("POLYGON"))
Which results in:
InvalidRequestError: Implicitly combining column tablename.wkb_geometry with column tablename.wkb_geometry under attribute 'wkb_geometry'. Please configure one or more attributes for these same-named columns explicitly.
Is it possible to use the metadata construction to support dynamic reflection **and* *override a column known will be available on all tables?
I'm not sure if I exactly follow what you're doing, but I've overridden reflected columns in the past inside my own __init__ method on a custom metaclass that inherits from DeclarativeMeta. Any time the new base class is used, it checks for a 'wkb_geometry' column name, and replaces it with (a copy of) the one you created.
import sqlalchemy as sa
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base
wkb_geometry = db.Column(Geometry("POLYGON"))
class MyMeta(DeclarativeMeta):
def __init__(cls, clsname, parents, dct):
for key, val in dct.iteritems():
if isinstance(sa.Column) and key is 'wkb_geometry':
dct[key] = wkb_geometry.copy()
MyBase = declarative_base(metaclass=MyMeta)
cls = type(str(tablename), (MyBase,), {'__tablename__':tablename})
This may not exactly work for you, but it's an idea. You probably need to add db.Model to the MyBase tuple, for example.
This is what I use to customize a particular column while relying on autoload for everything else. The code below assumes an existing declarative Base object for a table named my_table. It loads the metadata for all columns but overrides the definition of a column named polygon:
class MyTable(Base):
__tablename__ = 'my_table'
__table_args__ = (Column(name='polygon', type=Geometry("POLYGON"),
{'autoload':True})
Other arguments to the Table constructor can be provided in the dictionary. Note that the dictionary must appear last in the list!
The SQLAlchemy documentation Using a Hybrid Approach with __table__ provides more details and examples.

How to convert entity leaving it id

There are some entities (Region, Country, City) which used STI (or even CTI). How it possible convert Country to City leaving old id?
This is not supported in Doctrine 2 because type casting user objects is not supported by PHP.
With that said, Doctrine uses the discriminator column to determine what type of object to hydrate. If you change the value of the discriminator column in the database with a SQL UPDATE, the object type will be changed the next time the object is loaded. This works for STI, but CTI would be more complicated.
It may not be possible by standard using Doctrine, but you can work around it.
If you use the Class Metadata you can select your discriminator column.
Take a look at the Trait that I've created to solve the problem within my app:
namespace App\Doctrine\Repository;
trait DiscriminatorTrait
{
abstract public function getClassMetadata();
abstract public function getEntityManager();
private function updateDiscriminatorColumn($id, $class)
{
$classMetadata = $this->getClassMetadata();
if (!in_array($class, $classMetadata->discriminatorMap)) {
throw new \Exception("invalid discriminator class: " . $class);
}
$identifier = $classMetadata->fieldMappings[$classMetadata->identifier[0]]["columnName"];
$column = $classMetadata->discriminatorColumn["fieldName"];
$value = array_search($class, $classMetadata->discriminatorMap);
$connection = $this->getEntityManager()->getConnection();
$connection->update(
$classMetadata->table["name"],
[$column => $value],
[$identifier => $id]
);
}
}
I do have to warn you though, when your sub-classes have (a lot of) extra fields you will need to fill or clear them manually afterwards.