EasyCriteria evoluiu para uaiCriteria. Novo nome e novas funcionalidades

2

Posted on by

Share it now!

Olá, tudo bem?

É com muita felicidade que venho anunciar o uaiCriteria, a evolução do EasyCriteria.

Por que a mudança de nome? Descobri que já existia no mercado um framework com o mesmo nome e para evitar qualquer problema eu resolvi mudar o nome do framework. A diferença é que o uaiCriteria trabalha com String como parâmetro, e o outro framework trabalha com MetaModel diretamente.

Para esclarecer algumas dúvidas sobre a mudança:

  • Seu código antigo continuará funcionando sem problema algum, o código é retro compatível

  • As classes EasyCriteira estão marcadas com @Deprecated e serão removidas na próxima versão

  • As novas classes tem os mesmo métodos que as antigas e muitas outras novidades. Basta fazer um “replace” de EasyCriteria por UaiCriteria e todo problema estará resolvido

  • Novamente, eu não queria mudar o nome mas também não quero problemas com outras pessoas

O framework também ganhou um mascote, eu espero que vocês gostem:

mascote

mascote

De novidades temos muitas, mas muitas mesmo! Vamos ver primeiro mudanças de estrutura:

  1. O site mudou, agora o site é o: http://uaicriteria.com

  2. O repositório mudou, agora estamos hospedados no GIT. Após diversos pedidos movi para o GIT para melhorar a visualização do código: https://github.com/uaihebert/uaicriteria

  3. Para ajudar na cobertura do código e análise estática foi adicionado o plugin do SONAR. A imagem de cobertura agora ficou até mais bonita:

    uaicriteria cobertura

    uaicriteria cobertura

  4. O site antigo será desativado e todos os dados antigos foram levados para site novo, até mesmo a documentação legada. [=

  5. A API atual existe limitações, algo como não possibilitar o uso do HAVING e algumas outras funções, desse modo será criada para próxima versão uma Interface/API para Criterias Complexas – aceito sugestão de nome para a Interface (:

Com relação ao código, temos diversas novidades:

Boas vindas ao Batoo

O Batoo é um provedor de JPA assim como EclipseLink ou Hibernate. Com essa nova versão diversas funcionalidades foram cobertas com o Batoo.

Note que eu disse diversas, mas não todas. Infelizmente o Batoo ainda tem muitos, mas muitos problemas mesmo com consultas e Criterias.

O uaiCriteria ainda dá cobertura aos frameworks Hibernate, EclipseLink e OpenJPA na maioria dos métodos.

MultiSelect

É possível escolher quais campos serão retornados em uma consulta, veja a JPQL:

select 
    p.name, 
    p.age

from Person p

Transformando a consulta acima em criteria:

final UaiCriteria<Person> uaicriteria = 
    UaiCriteriaFactory.UaiCriteriaFactory.createMultiSelectCriteria(entityManager, Person.class);

uaiCriteria.addMultiSelectAttribute("name")
           .addMultiSelectAttribute("age");

final List multiselectList = uaiCriteria.getMultiSelectResult();

Algumas considerações sobre o código acima:

  • O resultado terá um Object caso você retorne apenas um campo

  • O resultado terá um Object[] caso você retorne diversos campos

  • A implementação pode variar de Object[] ou Vector (pelo menos comigo o EclipseLink estava retornando Vector)

SubQuery

Agora é possível fazer subQuery. Imagine uma JPQL como a abaixo:

select p from Person p 
where p.id in 
        (select dog.person.id from Dog dog where dog.cute = true)

Nem vou citar quantas linhas de código seriam necessárias para fazer o código acima, mas com o UaiCriteria ficou bem mais fácil:

final UaiCriteria<Person> uaiCriteria = UaiCriteriaFactory.createQueryCriteria(Person.class);

final UaiCriteria<Dog> subQuery = uaiCriteria.subQuery("person.id", Dog.class); // dog.person.id

subQuery.andEquals("cute", true);

uaiCriteria.andAttributeIn("id", subQuery); //person.id

Basta criar um objeto de subQuery passando qual será o retorno da subQuery. Depois chame o método o attributeIn(…) da query principal passando qual o campo a ser comparado.

MapIsEmpty [NOT]

Agora é possível utilizar a função isEmpty com Map:

uaiCriteria.andCollectionIsEmpty("ENTITY_MAP");

AttributeIn [NOT]

Existe a opção de verificar se um valor está ou não dentro de uma lista. Veja o exemplo abaixo:

select p
from Payment p
where
    p.statusEnum in :enumList

Para transformar o código acima em criteria:

final UaiCriteria<Payment> uaiCriteria = 
    UaiCriteriaFactory.createQueryCriteria(Payment.class);

uaiCriteria.andAttributeIn("statusEnum", 
                           Arrays.asList(StatusEnum.VALUE_01, StatusEnum.VALUE_02));

O atributo não precisa ser necessariamente um enum, poder ser número, string, etc.

MemberOf [NOT]

A consulta abaixo

select d
from Departament d
where :person member of d.employeeList

Pode ser criada como:

final UaiCriteria<Departament> uaiCriteria = UaiCriteriaFactory.createQueryCriteria(Departament.class);

uaiCriteria.andIsMemberOf(person, "employeeList");

Count e CountRegularCriteria

Agora como é possível realizar uma consulta MultiSelect o método count() foi renomeado como countRegularCriteria(). Funciona do mesmo modo, houve apenas uma alteração no nome para ficar mais claro seu funcionamento.

CountAttribute

Existe situações onde é necessário realizar o count em cima de um atributo, algo como:

select count(p.id)
from Person p

E para executar como Criteria:

final UaiCriteria<Person> uaiCriteria = 
    UaiCriteriaFactory.createMultiSelectCriteria(Person.class);

uaiCriteria.countAttribute("id");

final List result = uaiCriteria.getMultiSelectResult();

GroupBy e funções de Agregação

Agora é possível realizar groupBy juntamente com diversas funções de agregação. Funções como sum, diff, divide, module, etc.

select sum(p.value), p.status
from Payment p
group by p.status

Poderia se executada como:

final UaiCriteria<Payment> uaiCriteria = 
    UaiCriteriaFactory.createMultiSelectCriteria(Payment.class);

uaiCriteria.sum("id").groupBy("status");

final List result = uaiCriteria.getMultiSelectResult();

Novo Import no Maven

Para utilizar a nova versão em seu projeto, basta adicionar o código abaixo ao seu pom.xml

<dependency>
    <groupId>uaihebert.com</groupId>
    <artifactId>uaiCriteria</artifactId>
    <version>4.0.0</version>
</dependency>

Bem, espero que você tenha gostado das novidades.

Não esqueça de visitar o site —————-> http://uaicriteria.com

Qualquer dúvida/crítica/sugestão basta falar.

Até mais. \o_

EasyCriteria has evolved to uaiCriteria. New name and more features

0

Posted on by

Share it now!

Hello, how are you?

I am very happy to announce the release of the uaiCriteria, the EasyCriteria evolution.

Was it really needed to change the framework name? Yes, sadly it was. I found another framework with the same name, that is why I decided to change the name (I do not want any kind of legal problems). The difference of the framework is that the other framework works with MetaModel, and uaiCriteria works with strings as parameters.

About the framework name change:

  • Your code will work with this new version without a problem, the code is retro compatible
  • All EasyCriteria classes are annotated with @Deprecated and will be removed in the next version
  • The new classes has all the methods of the old version. If you want to change for the new code just “replace” the text EasyCriteria for UaiCriteria in your code
  • Again, I did not want to change the framework name but I do not want legal problems

The framework now has a mascot:

mascot

mascot

The new version has a lot of new stuff. Let us talk first about the structural changes:

  • The site has changed, now is http://uaicriteria.com
  • The repository has changed, now is on GIT (requested by a lot of develpers) https://github.com/uaihebert/uaicriteria
  • The SONAR plug-in was added to the pom.xml to help with code the code coverage and static analysis:

    uaicriteria cobertura

    uaicriteria cobertura

  • The old site will be deactivated, but all the old documentation was migrated.
  • The current API has some criteria limitations, using HAVING in the criteria is something that is not possible. We will create a new Interface/API to use with complex criteria – I am looking for a new name for the new Interface, could you suggest me one? (:

Let us talk about the new features:

Welcome to Batoo

Batoo is a JPA provider like EclipseLink or Hibernate. In this new version we got a good number of methods tested with Batoo.

Notice that I talked about “a good number of methods” but not most of the methods. Unfortunately Batoo has several problems with JPQL and Criterias, and I could not cover most of the methods with it.

uaiCriteria framework support almost all methods with EclipseLink, Hibernate and OpenJPA.

MultiSelect

It is possible to choose which attributes will be returned:

select
    p.name,
    p.age
from 
    Person p

If we transform the JPQL above in Criteria:

finalUaiCriteria<Person> uaicriteria =
    UaiCriteriaFactory.UaiCriteriaFactory.createMultiSelectCriteria(entityManager, Person.class);

uaiCriteria.addMultiSelectAttribute("name")
           .addMultiSelectAttribute("age");

finalList multiselectList = uaiCriteria.getMultiSelectResult();

Some considerations about the code above:

  • Object will be returned if you select only one attribute
  • Object[] will be returned if you select more than one attribute
  • The JPA provider may return Vector instead of Object[] (with my tests EclipseLink was returning a Vector)

SubQuery

Now it is possible to do a subQuery like below:

select p from Person p 
where p.id in
        (select dog.person.id from Dog dog where dog.cute = true)

I will not talk about the several lines of native JPA criteria needed to do the JPQL above, but with UaiCriteria is very easy to do:

final UaiCriteria<Person> uaiCriteria = UaiCriteriaFactory.createQueryCriteria(Person.class);
 
final UaiCriteria<Dog> subQuery = uaiCriteria.subQuery("person.id", Dog.class); // dog.person.id
 
subQuery.andEquals("cute", true);
 
uaiCriteria.andAttributeIn("id", subQuery); //person.id

All you need to do is to create a subQuery informing its return; then call the method attributeIn of the root criteria.

MapIsEmpty [NOT]

The isEmpty method can be used with maps:

uaiCriteria.andCollectionIsEmpty("ENTITY_MAP");

AttributeIn [NOT]

If you want to validate if a value is inside a list like the JPQL:

select p
from Payment p
where
    p.statusEnum in :enumList

You can create the JPQL above like:

final UaiCriteria<Payment> uaiCriteria = 
    UaiCriteriaFactory.createQueryCriteria(Payment.class);
 
uaiCriteria.andAttributeIn("statusEnum", 
                           Arrays.asList(StatusEnum.VALUE_01, StatusEnum.VALUE_02));

The attribute could be a enum, integer, String, etc.

MemberOf [NOT]

The query below:

select d
from Departament d
where :person member of d.employeeList

Could be created like:

final UaiCriteria<Departament> uaiCriteria = 
    UaiCriteriaFactory.createQueryCriteria(Departament.class);
 
uaiCriteria.andIsMemberOf(person, "employeeList");

Count and CountRegularCriteria

Now it is possible to do a count with a MultiSelect criteria. The count method was renamed to countRegularCriteria(). It works like the older version, just the name was refactored to make things more distinct.

CountAttribute

Sometimes you need to count an attribute instead of an entity:

select count(p.id)
from Person p

You can run the JPQL above like:

final UaiCriteria<Person> uaiCriteria = 
    UaiCriteriaFactory.createMultiSelectCriteria(Person.class);
 
uaiCriteria.countAttribute("id");
 
final List result = uaiCriteria.getMultiSelectResult();

GroupBy and Aggregate Functions

Now it is possible to do a GroupBy with aggregate functions: sum, diff, divide, module,  etc.

select sum(p.value), p.status
from Payment p
group by p.status

Could be executed like:

final UaiCriteria<Payment> uaiCriteria = 
    UaiCriteriaFactory.createMultiSelectCriteria(Payment.class);
 
uaiCriteria.sum("id").groupBy("status");
 
final List result = uaiCriteria.getMultiSelectResult();

New Maven Import

If you want to use the new version, just add the xml below to your pom.xml:

<dependency>
    <groupId>uaihebert.com</groupId>
    <artifactId>uaiCriteria</artifactId>
    <version>4.0.0</version>
</dependency>

I hope you liked the news.

Do not forget to visit the new site ———–> http://uaicriteria.com

If you have any doubts, questions or suggestions just post it.

See you soon. \o_

Alternativas ao JPA Hibernate. O que usar quando o JPA não atende meu projeto?

14

Posted on by

Share it now!

Olá, tudo bem?

Hoje vamos falar sobre situações onde o JPA pode não nos atender. Com quais alternativas podemos contar a partir do momento que percebemos que o JPA não está ajudando?

O que vamos ver aqui hoje:

  • Problemas do JPA e do Hibernate
  • Soluções para problemas do JPA
  • Critérios para escolha dos frameworks descritos aqui
  • Spring JDBC Template
  • MyBatis
  • Sormula
  • sql2o
  • Vale a pena conferir: jOOQ e Avaje
  • E o JDBC puro? Ainda vale a pena?
  • Considerações sobre qual framework escolher
  • Conclusão

Criei em meu github 4 CRUDS completos das ferramentas detalhadas aqui no post, cada URL está em cada página que descreve o framework.

Eu não sou o tipo de pessoa radical que acha que o JPA não serve para nada, pelo contrário, creio que em determinados momentos é necessário escolher o framework mais adequado para a cada situação. Para quem não sabe eu já escrevi um livro de JPA e ainda assim não o considero a bala de prata para todos os problemas.

Espero que vocês gostem. [=

JPA Hibernate Alternatives. What can I use if JPA or Hibernate is not good enough for my project?

15

Posted on by

Share it now!

Hello, how are you?

Today we will talk about situations that the use of the JPA/Hibernate is not recommended. Which alternatives do we have outside the JPA world?

What we will talk about:

  • JPA/Hibernate problems

  • Solutions to some of the JPA/Hibernate problems

  • Criteria for choosing the frameworks described here

  • Spring JDBC Template

  • MyBatis

  • Sormula

  • sql2o

  • Take a look at: jOOQ and Avaje

  • Is a raw JDBC approach worth it?

  • How can I choose the right framework?

  • Final thoughts

I have created 4 CRUDs in my github using the frameworks mentioned in this post, you will find the URL at the beginning of each page.

I am not a radical that thinks that JPA is worthless, but I do believe that we need to choose the right framework for the each situation. If you do not know I wrote a JPA book (in Portuguese only) and I do not think that JPA is the silver bullet that will solve all the problems.

I hope you like the post. [=

Ultimo dia da promoção compre 1 e leve outro da Packt

2

Posted on by

Share it now!

Pessoal, bom dia.

Entraram em contato comigo da editora Pack pedindo para anunciar o último dia da promoção:

Packt Publishing celebrates their 2000th title with an exclusive offer – We’ve got IT covered!

Abaixo o texto promocional:

Known for their extensive range of pragmatic IT ebooks, Packt Publishing are celebrating their 2000th book title `Learning Dart’– they want their customers to celebrate too.

To mark this milestone Packt Publishing will launch a ‘Buy One Get One Free’ offer across all eBooks on March 18th – for a limited period only.

Packt is one of the most prolific and fast-growing tech book publishers in the world. Originally focused on open source software, Packt contributes back into the community paying a royalty on relevant books directly to open source projects. These projects have received over $400,000 as part of Packt’s Open Source Royalty Scheme to date.

Their books focus on practicality, recognising that readers are ultimately concerned with getting the job done. Packt’s digitally-focused business model allows them to quickly publish up-to-date books in very specific areas across a range of key categories – web development, game development, big data, application development, and more. Their commitment to providing a comprehensive range of titles has seen Packt publish 1054% more titles in 2013 than in 2006.

Here are some of the best titles across Packt’s main categories – but Buy One, Get One Free will apply across all 2000 titles:

Last day to by one and get other book for free!

0

Posted on by

Share it now!

Hello, how are you?

The people from Packt Publishing asked me to announce:

 

Packt Publishing celebrates their 2000th title with an exclusive offer – We’ve got IT covered!

Known for their extensive range of pragmatic IT ebooks, Packt Publishing are celebrating their 2000th book title `Learning Dart’– they want their customers to celebrate too.

To mark this milestone Packt Publishing will launch a ‘Buy One Get One Free’ offer across all eBooks on March 18th – for a limited period only.

Packt is one of the most prolific and fast-growing tech book publishers in the world. Originally focused on open source software, Packt contributes back into the community paying a royalty on relevant books directly to open source projects. These projects have received over $400,000 as part of Packt’s Open Source Royalty Scheme to date.

Their books focus on practicality, recognising that readers are ultimately concerned with getting the job done. Packt’s digitally-focused business model allows them to quickly publish up-to-date books in very specific areas across a range of key categories – web development, game development, big data, application development, and more. Their commitment to providing a comprehensive range of titles has seen Packt publish 1054% more titles in 2013 than in 2006.

Here are some of the best titles across Packt’s main categories – but Buy One, Get One Free will apply across all 2000 titles:

Protegendo sua aplicação – Mini Livro

24

Posted on by

Share it now!

Olá, tudo bem?

Esse post é para comemorar a marca de 1 milhão de visualizações que o blog atingiu no mês passado. Abaixo você encontrará mini livro sobre segurança, grátis.

Todos os milhares de envolvidos no blog (cof cof cof) estão mega animados e prontos para celebrar esse marco histórico:

happy

Melhor deixar a celebração para outro dia… =P

Hoje vamos falar sobre segurança. Não apenas segurança de ambiente, mas também em como criar um código seguro. Esse post na verdade faz parte do que eu chamo de Mini Livro. Não será publicado como livro, mas também foge a regra de que um post deve ter poucas páginas.

Por diversas vezes ouvimos falar de ataques, mas não paramos para pensar em como poderíamos proteger nossa aplicação.

Um projeto com um código seguro e um ambiente de produção que sejam seguros e de rápida respostas a um ataque é primordial para qualquer empresa. Precisamos ter a certeza de que nosso código está seguindo boas práticas e que, nosso ambiente de produção está protegido e bem preparado para qualquer tipo de ataque que chegar.

Atenção: Eu não vou gerar uma versão em PDF deste post. Já levo muito tempo apenas para planejar, escrever, formatar e traduzir o post. Para mim é inviável gerar uma versão em PDF ou qualquer outro formato para colocar a disposição aqui no blog. Este mini livro estará apenas disponível online.

Graças ao Rogério Angeliski temos ao final do post a versão em PDF do post.
Muito obrigado Rogério!

O que veremos por aqui:

  • Página 02: No que se baseia segurança?
  • Página 03: Público Alvo
  • Página 04: Um bom hacker sempre tem tempo
    • Cuidado com a informação retornada
    • Cuidado com o tamanho da mensagem retornada
    • Firewall/SSL não faz mágica
  • Página 05: Tipos de ataques e sugestões para evitá-los/tratá-los:
    • SQL Injection
    • JPQL Injection e HQL Injection
    • Cross-Site scripting (XSS)
    • Brute Force Attack
    • Man In The Middle
    • XPath Injection
    • LDAP Injection
    • DoS ou DDoS
    • Slow DoS
  • Página 06: Cuidado com os dados
    • Protegendo a entrada de dados
    • Protegendo a saída de dados
  • Página 07: Cuidados com o “Client Side”
    • Fique atento a URL
    • Testes Técnicos
  • Página 08: Validações
    • Validando dados
    • Cuidado com arquivos
  • Página 09: Sempre dê o menor privilégio possível
  • Página 10: Trate os erros do projeto
  • Página 11: Cuidados com bibliotecas de terceiros
  • Página 12: Versão do projeto
  • Página 13: Preste atenção com o log
  • Página 14: Separe seu projeto das camadas
  • Página 15: Comentários nem sempre são saudáveis
  • Página 16: Sempre valide seu código
  • Página 17: Tenha um CheckList
  • Página 18: Cuidado com a equipe de TI
    • Exposição dos dados
    • Cuidado com o código escrito
    • Futuro ex-funcionário
    • Code Review / Pair Programming
    • Fique atento a terminologia
  • Página 19: Proteja a senha do modo correto
  • Página 20: Boas práticas para controle de acesso
    • Esconda o botão/link, mas proteja o código
    • Conheça a necessidade do seu usuário
    • Sempre oculte
  • Página 21: Políticas de Segurança
  • Página 22: Evitando falhas de códigos e/ou frameworks
    • Não exponha tecnologias desnecessariamente
    • Nunca misture os tipos
    • Utilize chaves nos “IFs”
    • Inteiros com Flutuantes
    • Sempre programe defensivamente

Não sou nenhum especialista no assunto, apenas estou compartilhando coisas que aprendi por leitura ou vivenciei no dia a dia do desenvolvimento.

Vamos começar?

Protecting your Project – Mini Book

4

Posted on by

Share it now!

Hello, how are you?

This post is to celebrate the mark of 1 million views that the blog reached in the last month. Below you will find a free mini book about project security.

We are very excited to celebrate this milestone, all the 300+ post writers of the  blog(cof cof cof) cannot wait for the party:

happy

Ok… We will do the celebration in another day.

Today we will talk about security. Not only environment security, but how can we create a secure code. This post is what I call of: “Mini Book”. This post will not be published as a book, but it does not have a few pages like other posts.

It is easy to hear about a hacker attack in the news, but we do not take a time to think about security measures to our systems.

A project that has a code with good security practices and a production environment that is safe and fast to respond a hacker attack should be a requirement for every project. We need to be sure that our code is following good security practices; it is fundamental that our production environment is protected and ready to react when a hacker attacks our project.

PS.: I will not create a PDF version of this post. I have invested several hours planning, writing, formatting and translating this post. I do not have enough time to create a PDF or any other file format version of this post. This Mini Book will be available on-line only.

What you will see here:

  • Page 02: What are the foundations of security?
  • Page 03: Who will access our project?
  • Page 04: A good hacker always will have time
    • Watch out for the returned information
    • Watch out for the size of the returned message
    • Firewall/SSL does no magic
  • Page 05: Attack types and suggestion prevent/handle them
    • SQL Injection
    • JPQL Injection and HQL Injection
    • Cross-site scripting (XSS)
    • Brute Force Attack
    • Man in the middle
    • XPath Injection
    • LDAP Injection
    • DoS or DDoS
    • Slow DoS
  • Page 06: Protect your data
    • Protecting the incoming data
    • Protecting the outgoing data
  • Page 07: The “Client Side”
    • URL tips
    • Technical Tests
  • Page 08: Validation
    • Data validation
    • Be careful with uploaded files
  • Page 09: Always start with the lowest privilege
  • Page 10: Handle all project exceptions
  • Page 11: Watch out for third party libraries
  • Page 12: System versions
  • Page 13: Pay attention to the log
  • Page 14: Add layers to your project
  • Page 15: Comments in code are not always healthy
  • Page 16: Always do a Code Validation
  • Page 17: Create a Checklist
  • Page 18: IT Staff
    • Data leaking
    • Be careful with your code
    • Fired Employee
    • Code Review / Pair Programming
    • Defining a terminology
  • Page 19: Handle the passwords correctly
  • Page 20: Good practices to handle user requests
    • Hide the buttons/links, but protect the code
    • Know your user needs
    • Always hide
  • Page 21: Security Policies
  • Page 22: Be careful with errors in the code/frameworks
    • Do not expose the technologies
    • Do not mix the types
    • Use brackets in the Ifs
    • Integer and Floating
    • Defensive programming

I am not an expert in the security subject; I am sharing what I learned by reading books or in the places that I have worked.

Let us begin.

Review do Livro: Developing RESTful Services

0

Posted on by

Share it now!

Olá pessoal, tudo bem?

Fui convidado pela editora Packt para fazer o review do livro: Developing RESTful Services with JAX-RS 2.0, WebSockets, and JSON.

Esse livro foi laçado em inglês apenas e não sei se haverá uma versão em português.

Ele é um livro pequeno e direto. Não se aprofunda muito no assunto, mas mostra todos os conceitos necessários para começar a construir um projeto com conceitos RESTFul.

O que mais me chamou atenção do livro foi que no capítulo dois onde ele descreve sobre pooling. O assunto foi muito bem abordado e detalhado.

Ao final do livro é possível encontrar dois projetos completos que mostram duas abordagens para a utilização de Webservice em um projeto.

É um livro interessante para quem quer saber rapidamente sobre os conceitos básicos de Webservices.

Até a próxima pessoal! \o_

Book Review: Developing RESTful Services

2

Posted on by

Share it now!

Hello, how are you?

I was invited by Packt publisher to do a review of the book: Developing RESTful Services with JAX-RS 2.0, WebSockets, and JSON.

It is a small and versatile book. It not goes deep in the Webservices subject, but it talks about all needed knowledge to start a Webservice project.

The chapter that I liked most is the chapter two that talks about pooling. It talked a lot about it and got deep in the pooling subject.

At the end of the book it is possible to find two projects with different Webservices approaches.

It is a good book to those that wants to know quickly about the basic Webservices concepts.

See you later! \o_

1 2 3 4 5 12 13