# Path: datawire/core.py
# def url_for(*a, **kw):
# 
# Path: datawire/model/user.py
# class User(db.Model):
#     id = db.Column(db.Integer, primary_key=True)
#     login = db.Column(db.Unicode(255))
#     email = db.Column(db.Unicode, nullable=True)
#     oauth_id = db.Column(db.Unicode)
#     api_key = db.Column(db.Unicode, default=make_token)
# 
#     is_admin = db.Column(db.Boolean, nullable=False, default=False)
# 
#     created_at = db.Column(db.DateTime, default=datetime.utcnow)
#     updated_at = db.Column(db.DateTime, default=datetime.utcnow,
#                            onupdate=datetime.utcnow)
# 
#     def is_active(self):
#         return True
# 
#     def is_authenticated(self):
#         return True
# 
#     def is_anonymous(self):
#         return False
# 
#     def get_id(self):
#         return self.login
# 
#     def __repr__(self):
#         return '<User(%r,%r)>' % (self.id, self.login)
# 
#     def __unicode__(self):
#         return self.login
# 
#     def to_dict(self):
#         return {
#             'id': self.id,
#             'login': self.login,
#             'is_admin': self.is_admin,
#             'created_at': self.created_at,
#             'updated_at': self.updated_at,
#             'api_url': url_for('users.view', login=self.login)
#         }
# 
#     def update(self, data):
#         data = UserForm().deserialize(data)
#         self.email = data.get('email')
# 
#     @classmethod
#     def load(cls, data):
#         user = cls.by_oauth_id(data.get('oauth_id'))
# 
#         if user is None:
#             user = cls()
#             user.login = data.get('login')
#             user.oauth_id = data.get('oauth_id')
# 
#         if data.get('email'):
#             # FIXME: better to overwrite with upstream or keep?
#             user.email = data.get('email')
#         db.session.add(user)
#         return user
# 
#     @classmethod
#     def all(cls):
#         q = db.session.query(cls)
#         return q
# 
#     @classmethod
#     def by_login(cls, login):
#         q = db.session.query(cls).filter_by(login=login)
#         return q.first()
# 
#     @classmethod
#     def by_api_key(cls, api_key):
#         q = db.session.query(cls).filter_by(api_key=api_key)
#         return q.first()
# 
#     @classmethod
#     def by_oauth_id(cls, oauth_id):
#         q = db.session.query(cls).filter_by(oauth_id=unicode(oauth_id))
#         return q.first()
# 
# Path: datawire/model/selector.py
# class Selector(db.Model):
#     id = db.Column(db.Integer, primary_key=True)
#     _text = db.Column('text', db.Unicode, index=True)
#     normalized = db.Column(db.Unicode, index=True)
# 
#     created_at = db.Column(db.DateTime, default=datetime.utcnow)
#     updated_at = db.Column(db.DateTime, default=datetime.utcnow,
#                            onupdate=datetime.utcnow)
# 
#     entity_id = db.Column(db.Unicode(50), db.ForeignKey('entity.id'))
#     entity = db.relationship('Entity', backref=db.backref('selectors',
#                              lazy='dynamic', cascade='all, delete-orphan'))
# 
#     @hybrid_property
#     def text(self):
#         return self._text
# 
#     @text.setter
#     def text(self, text):
#         self._text = text
#         self.normalized = self.normalize(text)
# 
#     @classmethod
#     def normalize(cls, text):
#         return normalize(text)
# 
#     def __repr__(self):
#         return '<Selector(%r, %r)>' % (self.entity_id, self.text)
# 
#     def __unicode__(self):
#         return self.text
# 
# Path: datawire/model/forms.py
# class EntityForm(colander.MappingSchema):
#     label = colander.SchemaNode(colander.String())
#     category = colander.SchemaNode(colander.String(),
#                                    validator=colander.OneOf(CATEGORIES))
#     selectors = EntitySelectors()
#     collection = colander.SchemaNode(CollectionRef())
# 
# CATEGORIES = [PERSON, COMPANY, ORGANIZATION, OTHER]
# 
# Path: datawire/model/util.py
# def make_textid():
#     return uuid.uuid4().hex
# 
# def db_compare(col, text):
#     if text is None:
#         return col == text
#     text_ = text.lower().strip()
#     return db_norm(col) == text_


import logging
from datetime import datetime
from sqlalchemy import or_
from sqlalchemy.orm import aliased
from datawire.core import db, url_for
from datawire.model.user import User
from datawire.model.selector import Selector
from datawire.model.forms import EntityForm, CATEGORIES
from datawire.model.util import make_textid, db_compare
        ent.update(data)
        ent.creator = user
        db.session.add(ent)
        return ent

    def update(self, data):
        data = EntityForm().deserialize(data)
        self.label = data.get('label')
        self.collection = data.get('collection')
        self.category = data.get('category')

        selectors = set(data.get('selectors'))
        selectors.add(self.label)
        existing = list(self.selectors)
        for sel in list(existing):
            if sel.text in selectors:
                selectors.remove(sel.text)
                existing.remove(sel)
        for sel in existing:
            db.session.delete(sel)
        for text in selectors:
            sel = Selector()
            sel.entity = self
            sel.text = text
            db.session.add(sel)

    @classmethod
    def by_normalized_label(cls, label, collection):
        q = db.session.query(cls)
        q = q.filter_by(collection=collection)

# Path: datawire/core.py
# def url_for(*a, **kw):
# 
# Path: datawire/model/user.py
# class User(db.Model):
#     id = db.Column(db.Integer, primary_key=True)
#     login = db.Column(db.Unicode(255))
#     email = db.Column(db.Unicode, nullable=True)
#     oauth_id = db.Column(db.Unicode)
#     api_key = db.Column(db.Unicode, default=make_token)
# 
#     is_admin = db.Column(db.Boolean, nullable=False, default=False)
# 
#     created_at = db.Column(db.DateTime, default=datetime.utcnow)
#     updated_at = db.Column(db.DateTime, default=datetime.utcnow,
#                            onupdate=datetime.utcnow)
# 
#     def is_active(self):
#         return True
# 
#     def is_authenticated(self):
#         return True
# 
#     def is_anonymous(self):
#         return False
# 
#     def get_id(self):
#         return self.login
# 
#     def __repr__(self):
#         return '<User(%r,%r)>' % (self.id, self.login)
# 
#     def __unicode__(self):
#         return self.login
# 
#     def to_dict(self):
#         return {
#             'id': self.id,
#             'login': self.login,
#             'is_admin': self.is_admin,
#             'created_at': self.created_at,
#             'updated_at': self.updated_at,
#             'api_url': url_for('users.view', login=self.login)
#         }
# 
#     def update(self, data):
#         data = UserForm().deserialize(data)
#         self.email = data.get('email')
# 
#     @classmethod
#     def load(cls, data):
#         user = cls.by_oauth_id(data.get('oauth_id'))
# 
#         if user is None:
#             user = cls()
#             user.login = data.get('login')
#             user.oauth_id = data.get('oauth_id')
# 
#         if data.get('email'):
#             # FIXME: better to overwrite with upstream or keep?
#             user.email = data.get('email')
#         db.session.add(user)
#         return user
# 
#     @classmethod
#     def all(cls):
#         q = db.session.query(cls)
#         return q
# 
#     @classmethod
#     def by_login(cls, login):
#         q = db.session.query(cls).filter_by(login=login)
#         return q.first()
# 
#     @classmethod
#     def by_api_key(cls, api_key):
#         q = db.session.query(cls).filter_by(api_key=api_key)
#         return q.first()
# 
#     @classmethod
#     def by_oauth_id(cls, oauth_id):
#         q = db.session.query(cls).filter_by(oauth_id=unicode(oauth_id))
#         return q.first()
# 
# Path: datawire/model/selector.py
# class Selector(db.Model):
#     id = db.Column(db.Integer, primary_key=True)
#     _text = db.Column('text', db.Unicode, index=True)
#     normalized = db.Column(db.Unicode, index=True)
# 
#     created_at = db.Column(db.DateTime, default=datetime.utcnow)
#     updated_at = db.Column(db.DateTime, default=datetime.utcnow,
#                            onupdate=datetime.utcnow)
# 
#     entity_id = db.Column(db.Unicode(50), db.ForeignKey('entity.id'))
#     entity = db.relationship('Entity', backref=db.backref('selectors',
#                              lazy='dynamic', cascade='all, delete-orphan'))
# 
#     @hybrid_property
#     def text(self):
#         return self._text
# 
#     @text.setter
#     def text(self, text):
#         self._text = text
#         self.normalized = self.normalize(text)
# 
#     @classmethod
#     def normalize(cls, text):
#         return normalize(text)
# 
#     def __repr__(self):
#         return '<Selector(%r, %r)>' % (self.entity_id, self.text)
# 
#     def __unicode__(self):
#         return self.text
# 
# Path: datawire/model/forms.py
# class EntityForm(colander.MappingSchema):
#     label = colander.SchemaNode(colander.String())
#     category = colander.SchemaNode(colander.String(),
#                                    validator=colander.OneOf(CATEGORIES))
#     selectors = EntitySelectors()
#     collection = colander.SchemaNode(CollectionRef())
# 
# CATEGORIES = [PERSON, COMPANY, ORGANIZATION, OTHER]
# 
# Path: datawire/model/util.py
# def make_textid():
#     return uuid.uuid4().hex
# 
# def db_compare(col, text):
#     if text is None:
#         return col == text
#     text_ = text.lower().strip()
#     return db_norm(col) == text_


# Path: datawire/model/entity.py
import logging
from datetime import datetime
from sqlalchemy import or_
from sqlalchemy.orm import aliased
from datawire.core import db, url_for
from datawire.model.user import User
from datawire.model.selector import Selector
from datawire.model.forms import EntityForm, CATEGORIES
from datawire.model.util import make_textid, db_compare

        ent.update(data)
        ent.creator = user
        db.session.add(ent)
        return ent

    def update(self, data):
        data = EntityForm().deserialize(data)
        self.label = data.get('label')
        self.collection = data.get('collection')
        self.category = data.get('category')

        selectors = set(data.get('selectors'))
        selectors.add(self.label)
        existing = list(self.selectors)
        for sel in list(existing):
            if sel.text in selectors:
                selectors.remove(sel.text)
                existing.remove(sel)
        for sel in existing:
            db.session.delete(sel)
        for text in selectors:
            sel = Selector()
            sel.entity = self
            sel.text = text
            db.session.add(sel)

    @classmethod
    def by_normalized_label(cls, label, collection):
        q = db.session.query(cls)
        q = q.filter_by(collection=collection)

        q = q.filter(db_compare(cls.label, label))