Spring boot ตอนที่ 3 – กรณีศึกษา MyFacebook web (4)

spring-boot-logo
บทสุดท้ายของกรณีศึกษาแล้วครับ เนื่องจากจะยาวเกินไป และเนื้อหาก็เป็นการใช้ spring mvc, security, jpa ซึ่งเป็นเรื่องที่นอกเหนือจาก spring boot ในบทนี้จะทำในเรื่อง Add friend และ comment post ของเพื่อนที่เราได้ Add ไปแล้ว โดยผมไม่ได้ทำเหมือน facebook ที่ต้องกด approve เพื่อเป็นการประหยัดเวลาครับ คือ add แล้วก็มีเพื่อนได้เลย

updated
รวมลิงก์ของทุกตอนครับ

  1. แก้ไข User.java ให้รองรับเพื่อน
    package com.magicalcyber.myfacebook.model;
    
    import java.sql.Timestamp;
    import java.util.Set;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.OneToOne;
    import javax.persistence.OrderBy;
    import javax.persistence.Table;
    import javax.validation.constraints.Size;
    
    @Entity
    @Table(name = "user")
    public class User {
    
    	@Id
    	@GeneratedValue
    	private Long id;
    
    	@Column
    	@Size(min = 5, max = 64)
    	private String email;
    
    	@Column
    	@Size(min = 5, max = 32)
    	private String name;
    
    	@Column
    	@Size(min = 5, max = 64)
    	private String password;
    
    	@Column
    	private Timestamp createdDate;
    
    	@OneToOne
    	private Role role;
    
    	@OneToMany(cascade = CascadeType.ALL)
    	@OrderBy("createdDate")
    	private Set<User> friends;
    
    	public Role getRole() {
    		return role;
    	}
    
    	public void setRole(Role role) {
    		this.role = role;
    	}
    
    	public Long getId() {
    		return id;
    	}
    
    	public void setId(Long id) {
    		this.id = id;
    	}
    
    	public String getEmail() {
    		return email;
    	}
    
    	public void setEmail(String email) {
    		this.email = email;
    	}
    
    	public String getPassword() {
    		return password;
    	}
    
    	public void setPassword(String password) {
    		this.password = password;
    	}
    
    	public Timestamp getCreatedDate() {
    		return createdDate;
    	}
    
    	public void setCreatedDate(Timestamp createdDate) {
    		this.createdDate = createdDate;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Set<User> getFriends() {
    		return friends;
    	}
    
    	public void setFriends(Set<User> friends) {
    		this.friends = friends;
    	}
    
    }
    
    
  2. ข้อนี้เป็นข้อผิดพลาดของผมเองง ให้แก้ไขประเภทตัวแปร comment ใน Post.java จาก Set ให้เป็น List
    package com.magicalcyber.myfacebook.model;
    
    import java.sql.Timestamp;
    import java.util.List;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.ManyToOne;
    import javax.persistence.OneToMany;
    import javax.persistence.OrderBy;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "post")
    public class Post {
    
    	@Id
    	@GeneratedValue
    	private Long id;
    
    	@Column
    	private String content;
    
    	@Column
    	private Timestamp createdDate;
    
    	@ManyToOne
    	private User createdUser;
    
    	@OneToMany(cascade = CascadeType.ALL)
    	@OrderBy("createdDate")
    	private List<Comment> comments;
    
    	public Long getId() {
    		return id;
    	}
    
    	public void setId(Long id) {
    		this.id = id;
    	}
    
    	public String getContent() {
    		return content;
    	}
    
    	public void setContent(String content) {
    		this.content = content;
    	}
    
    	public Timestamp getCreatedDate() {
    		return createdDate;
    	}
    
    	public void setCreatedDate(Timestamp createdDate) {
    		this.createdDate = createdDate;
    	}
    
    	public User getCreatedUser() {
    		return createdUser;
    	}
    
    	public void setCreatedUser(User createdUser) {
    		this.createdUser = createdUser;
    	}
    
    	public List<Comment> getComments() {
    		return comments;
    	}
    
    	public void setComments(List<Comment> comments) {
    		this.comments = comments;
    	}
    
    }
    
    
  3. สร้าง FriendDto.java เพื่อรองรับการค้นหาเพื่อน

    package com.magicalcyber.myfacebook.dto;
    
    public class FriendDto {
    
    	private Long userId;
    	private String name;
    	private boolean friend;
    
    	public FriendDto() {
    	}
    
    	public FriendDto(Long userId, String name, boolean friend) {
    		this.userId = userId;
    		this.name = name;
    		this.friend = friend;
    	}
    
    	public Long getUserId() {
    		return userId;
    	}
    
    	public void setUserId(Long userId) {
    		this.userId = userId;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public boolean isFriend() {
    		return friend;
    	}
    
    	public void setFriend(boolean friend) {
    		this.friend = friend;
    	}
    
    }
    
    
  4. แก้ไข PostRepository ให้รองรับ post ของเพื่อนด้วย
    package com.magicalcyber.myfacebook.repository;
    
    import java.util.List;
    import java.util.Set;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    import com.magicalcyber.myfacebook.model.Post;
    import com.magicalcyber.myfacebook.model.User;
    
    public interface PostRepository extends JpaRepository<Post, Long> {
    	List<Post> findByCreatedUserInOrderByCreatedDateDesc(Set<User> users);
    }
    
    
  5. ปรับ UserRepository ให้รอบรับการค้นหาเพื่่อนจากชื่อ
    package com.magicalcyber.myfacebook.repository;
    
    import java.util.List;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    import com.magicalcyber.myfacebook.model.User;
    
    public interface UserRepository extends JpaRepository<User, Long> {
    	User findByEmail(String email);
    
    	List<User> findByNameContainingOrEmail(String name, String email);
    
    }
    
    
  6. แก้ไข PostServiceImpl ให้ list post ของเพื่อนด้วย

    package com.magicalcyber.myfacebook.service;
    
    import java.sql.Timestamp;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.magicalcyber.myfacebook.model.Comment;
    import com.magicalcyber.myfacebook.model.Post;
    import com.magicalcyber.myfacebook.model.User;
    import com.magicalcyber.myfacebook.repository.PostRepository;
    import com.magicalcyber.myfacebook.repository.UserRepository;
    import com.magicalcyber.myfacebook.web.form.CommentForm;
    import com.magicalcyber.myfacebook.web.form.PostForm;
    
    @Service("postService")
    public class PostServiceImpl implements PostService {
    
    	@Autowired
    	private PostRepository postRepository;
    
    	@Autowired
    	private UserRepository userRepository;
    
    	@Override
    	public void save(PostForm postForm) {
    		User currentUser = userRepository.getOne(postForm.getUserId());
    		Post post = new Post();
    		post.setCreatedUser(currentUser);
    		post.setCreatedDate(new Timestamp(System.currentTimeMillis()));
    		post.setContent(postForm.getContent());
    		postRepository.save(post);
    	}
    
    	@Override
    	public List<Post> listPost(Long userId) {
    
    		// get current user
    		User currentUser = userRepository.findOne(userId);
    
    		HashSet<User> users = new HashSet<>();
    		if (currentUser.getFriends() != null && !currentUser.getFriends().isEmpty()) {
    			users = new HashSet<>(currentUser.getFriends());
    		}
    		users.add(currentUser);
    
    		return postRepository.findByCreatedUserInOrderByCreatedDateDesc(users);
    	}
    
    	@Override
    	public void saveComment(CommentForm commentForm) {
    		Post post = postRepository.findOne(commentForm.getPostId());
    		if (post == null) {
    			throw new IllegalArgumentException("Not found this post");
    		} else {
    			if (post.getComments() == null) {
    				post.setComments(new ArrayList<>());
    			}
    
    			User commentUser = userRepository.findOne(commentForm.getUserId());
    
    			Comment comment = new Comment();
    			comment.setCreatedUser(commentUser);
    			comment.setContent(commentForm.getContent());
    			comment.setCreatedDate(new Timestamp(System.currentTimeMillis()));
    
    			post.getComments().add(comment);
    			postRepository.save(post);
    		}
    	}
    
    }
    
    
  7. แก้ไข UserService ให้รองรับการ add/remove เพื่อน

    package com.magicalcyber.myfacebook.service;
    
    import java.util.Set;
    
    import com.magicalcyber.myfacebook.constant.UserRole;
    import com.magicalcyber.myfacebook.dto.FriendDto;
    import com.magicalcyber.myfacebook.model.User;
    import com.magicalcyber.myfacebook.web.form.FriendForm;
    import com.magicalcyber.myfacebook.web.form.RegisterForm;
    
    public interface UserService {
    	void create(RegisterForm form, UserRole userRole);
    
    	User findByEmail(String email);
    
    	Set<FriendDto> searchFriend(FriendForm friendForm);
    
    	void addFriend(Long userId);
    
    	void removeFriend(Long userId);
    
    	void addFriend(Long userId, Long friendId);
    
    }
    
    

    UserServiceImpl

    package com.magicalcyber.myfacebook.service;
    
    import java.sql.Timestamp;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Service;
    
    import com.magicalcyber.myfacebook.constant.UserRole;
    import com.magicalcyber.myfacebook.dto.FriendDto;
    import com.magicalcyber.myfacebook.model.CustomUserDetail;
    import com.magicalcyber.myfacebook.model.User;
    import com.magicalcyber.myfacebook.repository.RoleRepository;
    import com.magicalcyber.myfacebook.repository.UserRepository;
    import com.magicalcyber.myfacebook.web.form.FriendForm;
    import com.magicalcyber.myfacebook.web.form.RegisterForm;
    
    @Service
    public class UserServiceImpl implements UserService {
    
    	@Autowired
    	private UserRepository userRepository;
    
    	@Autowired
    	private RoleRepository roleRepository;
    
    	@Autowired
    	private PasswordEncoder passwordEncoder;
    
    	@Override
    	public void create(RegisterForm form, UserRole userRole) {
    		User user = new User();
    		user.setName(form.getName());
    		user.setEmail(form.getEmail());
    		user.setPassword(passwordEncoder.encode(form.getPassword()));
    		user.setRole(roleRepository.findOne(userRole.name()));
    		user.setCreatedDate(new Timestamp(System.currentTimeMillis()));
    		userRepository.save(user);
    	}
    
    	@Override
    	public User findByEmail(String email) {
    		return userRepository.findByEmail(email);
    	}
    
    	@Override
    	public Set<FriendDto> searchFriend(FriendForm friendForm) {
    		// set cache for check already friend
    		HashMap<Long, User> friendCache = new HashMap<>();
    		User currentUser = userRepository.findOne(friendForm.getUserId());
    		Set<User> currentFriends = currentUser.getFriends();
    		if (currentFriends != null && !currentFriends.isEmpty()) {
    			for (User friend : currentFriends) {
    				friendCache.put(friend.getId(), friend);
    			}
    		}
    
    		// set user and check already friend
    		Set<FriendDto> userList = new HashSet<>();
    
    		List<User> users = userRepository.findByNameContainingOrEmail(friendForm.getKeyword(), friendForm.getKeyword());
    		if (users != null && !users.isEmpty()) {
    			for (User user : users) {
    				FriendDto friend = new FriendDto();
    				friend.setUserId(user.getId());
    				friend.setName(user.getName());
    				friend.setFriend(friendCache.containsKey(user.getId()));
    				userList.add(friend);
    			}
    		}
    		return userList;
    	}
    
    	@Override
    	public void addFriend(Long userId) {
    		// get current user
    		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    		CustomUserDetail userDetail = (CustomUserDetail) auth.getPrincipal();
    		User currentUser = userRepository.findOne(userDetail.getId());
    
    		// add current friend
    		User requestedFriend = userRepository.findOne(userId);
    		if (currentUser.getFriends() == null) {
    			currentUser.setFriends(new HashSet<>());
    		}
    		currentUser.getFriends().add(requestedFriend);
    		userRepository.save(currentUser);
    
    		// add requested friend
    		if (requestedFriend.getFriends() == null) {
    			requestedFriend.setFriends(new HashSet<>());
    		}
    		requestedFriend.getFriends().add(currentUser);
    		userRepository.save(requestedFriend);
    	}
    
    	@Override
    	public void addFriend(Long userId, Long friendId) {
    		// get current user
    		User currentUser = userRepository.findOne(userId);
    
    		// add current friend
    		User requestedFriend = userRepository.findOne(friendId);
    		if (currentUser.getFriends() == null) {
    			currentUser.setFriends(new HashSet<>());
    		}
    		currentUser.getFriends().add(requestedFriend);
    		userRepository.save(currentUser);
    
    		// add requested friend
    		if (requestedFriend.getFriends() == null) {
    			requestedFriend.setFriends(new HashSet<>());
    		}
    		requestedFriend.getFriends().add(currentUser);
    		userRepository.save(requestedFriend);
    	}
    
    	@Override
    	public void removeFriend(Long userId) {
    		// get current user
    		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    		CustomUserDetail userDetail = (CustomUserDetail) auth.getPrincipal();
    		User currentUser = userRepository.findOne(userDetail.getId());
    
    		// remove current friend
    		User requestedFriend = userRepository.findOne(userId);
    		if (currentUser.getFriends() != null) {
    			currentUser.getFriends().remove(requestedFriend);
    		}
    		userRepository.save(currentUser);
    
    		// remove requested friend
    		if (requestedFriend.getFriends() != null) {
    			requestedFriend.getFriends().remove(currentUser);
    		}
    		userRepository.save(requestedFriend);
    	}
    
    }
    
    
  8. เพิ่ม FriendController

    package com.magicalcyber.myfacebook.web.controller;
    
    import javax.validation.Valid;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import com.magicalcyber.myfacebook.model.CustomUserDetail;
    import com.magicalcyber.myfacebook.service.UserService;
    import com.magicalcyber.myfacebook.web.form.FriendForm;
    
    @Controller
    public class FriendController {
    
    	private static final Logger log = LoggerFactory.getLogger(FriendController.class);
    
    	@Autowired
    	private UserService userService;
    
    	@GetMapping("/friend")
    	String friends(Model model) {
    
    		// get current user
    		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    
    		CustomUserDetail currentUser = (CustomUserDetail) auth.getPrincipal();
    
    		FriendForm friendForm = new FriendForm();
    		friendForm.setUserId(currentUser.getId());
    		model.addAttribute("friendForm", friendForm);
    		return "friend";
    	}
    
    	@GetMapping("/friend/search")
    	String searchFriends(@Valid @ModelAttribute("friendForm") FriendForm friendForm, BindingResult result,
    			Model model) {
    		if (!result.hasErrors()) {
    			model.addAttribute("users", userService.searchFriend(friendForm));
    		}
    		return "friend";
    	}
    
    	@PostMapping("/friend/add")
    	String addFriend(@RequestParam("userId") Long userId, Model model) {
    		log.info("request friend id: " + userId);
    
    		userService.addFriend(userId);
    		return "redirect:/";
    	}
    
    	@PostMapping("/friend/remove")
    	String removeFriend(@RequestParam("userId") Long userId, Model model) {
    		log.info("remove friend id: " + userId);
    
    		userService.removeFriend(userId);
    		return "redirect:/";
    	}
    }
    
    
  9. เพิ่ม FriendForm
    package com.magicalcyber.myfacebook.web.form;
    
    import org.hibernate.validator.constraints.NotEmpty;
    
    public class FriendForm {
    
    	private Long userId;
    
    	@NotEmpty
    	private String keyword;
    
    	public String getKeyword() {
    		return keyword;
    	}
    
    	public void setKeyword(String keyword) {
    		this.keyword = keyword;
    	}
    
    	public Long getUserId() {
    		return userId;
    	}
    
    	public void setUserId(Long userId) {
    		this.userId = userId;
    	}
    
    }
    
    
  10. เพิ่ม friend.jsp สำหรับหน้าค้นหาเพื่อน

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@taglib prefix="sec"
    	uri="http://www.springframework.org/security/tags"%>
    <%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>My Facebook</title>
    <link rel="stylesheet" type="text/css"
    	href='<c:url value="/css/bootstrap.min.css" />' />
    <link rel="stylesheet" type="text/css"
    	href='<c:url value="/css/main.css" />' />
    </head>
    <body>
    	<%@include file="nav.jsp"%>
    
    
    	<div class="container">
    
    		<div class="row">
    			<div class="col-md-4 col-md-offset-4 block">
    				<form:form servletRelativeAction="/friend/search" method="get"
    					modelAttribute="friendForm" cssClass="form-inline">
    					<form:hidden path="userId" />
    					<div class="form-group">
    						<form:input cssClass="form-control" path="keyword"
    							placeholder="Name or Email" />
    						<input type="submit" class="btn btn-primary" value="Search" />
    					</div>
    
    				</form:form>
    			</div>
    		</div>
    		<div class="row">
    			<div class="col-md-4 col-md-offset-4 block">
    				<c:choose>
    					<c:when test="${ not empty users }">
    						<div class="row">
    							<div class="col-sm-12">Found ${ users.size() }</div>
    						</div>
    						<hr />
    						<div class="row">
    							<c:forEach items="${ users }" var="user">
    								<div class="col-sm-8">
    									<div class="form-group">
    										<a href="#">${user.name }</a>
    									</div>
    								</div>
    								<div class="col-sm-4">
    									<c:choose>
    										<c:when test="${ user.friend }">
    											<form action='<c:url value="/friend/remove" />' method="post" >
    												<input type="hidden" name="userId" value="${ user.userId }" />
    												<input type='hidden' name='${_csrf.parameterName}'
    													value='${_csrf.token}' />
    												<input type="submit" class="btn btn-danger" value="Unfriend" />
    											</form>
    										</c:when>
    										<c:otherwise>
    											<form action='<c:url value="/friend/add" />' method="post">
    												<input type="hidden" name="userId" value="${ user.userId }" />
    												<input type='hidden' name='${_csrf.parameterName}'
    													value='${_csrf.token}' />
    												<input type="submit" class="btn btn-success"
    													value="Add friend" />
    											</form>
    										</c:otherwise>
    									</c:choose>
    								</div>
    							</c:forEach>
    						</div>
    					</c:when>
    					<c:otherwise>Not found a user</c:otherwise>
    				</c:choose>
    			</div>
    		</div>
    
    
    	</div>
    	<%@include file="footer.jsp"%>
    </body>
    </html>
    
  11. แก้ไข nav.jsp เพิ่มเมนูค้นหาเพื่อน

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@taglib prefix="sec"
    	uri="http://www.springframework.org/security/tags"%>
    <%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta name="viewport"
    	content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>My Facebook</title>
    </head>
    <body>
    	<nav class="navbar navbar-default navbar-static-top">
    		<div class="container-fluid">
    
    			<!-- Brand and toggle get grouped for better mobile display -->
    			<div class="navbar-header">
    				<button type="button" class="navbar-toggle collapsed"
    					data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
    					aria-expanded="false">
    					<span class="sr-only">Toggle navigation</span>
    					<span class="icon-bar"></span>
    					<span class="icon-bar"></span>
    					<span class="icon-bar"></span>
    				</button>
    				<a class="navbar-brand" href="#">My Facebook</a>
    			</div>
    
    
    			<!-- Collect the nav links, forms, and other content for toggling -->
    			<div class="collapse navbar-collapse"
    				id="bs-example-navbar-collapse-1">
    				<ul class="nav navbar-nav">
    					<li class="active">
    						<a href='<c:url value="/" />'>Home <span class="sr-only">(current)</span></a>
    					</li>
    					<sec:authorize access="isAnonymous()">
    						<li>
    							<a href='<c:url value="/login" />'>Login</a>
    						</li>
    					</sec:authorize>
    					<sec:authorize access="isAuthenticated()">
    						<li>
    							<a href='<c:url value="/friend" />'> <span
    									class="glyphicon glyphicon glyphicon-user" aria-hidden="true">
    									<c:if test="${ not empty friendsWaitForApprove }">${ friendsWaitForApprove.size() }</c:if>
    								</span>
    							</a>
    						</li>
    						<li>
    							<a href="#"> <sec:authorize access="isAuthenticated()">
    									<sec:authentication var="user" property="principal" />
    									<c:out value="${ user.fullname }"></c:out>
    
    								</sec:authorize>
    							</a>
    						</li>
    
    						<li>
    
    							<form:form cssClass="navbar-form" servletRelativeAction="/logout"
    								method="post">
    								<input type="submit" class="btn btn-danger" value="Logout" />
    							</form:form>
    						</li>
    					</sec:authorize>
    				</ul>
    			</div>
    
    		</div>
    	</nav>
    </body>
    </html>
    

    เนื่องจากผมเรียกใช้ font ของ bootstrap ดังนั้นต้องเพิ่ม font ของ bootstrap เข้ามาด้วย (หาได้จาก zip ของ bootstrap)

    1-font

จากนั้นก็ run แล้วสมัครมาสอง account เมื่อ login เข้ามาแล้วทำการค้นหาเพื่อนอีกคน หากยังไม่เคยกด add ก็จะมีปุ่มให้ add ถ้าเคย add แล้วก็จะเป็นปุ่ม Unfriend ตามรูป
2-search-friend

เมื่อเป็น friend กันแล้วก็จะสามารถเห็น post ของอีกฝ่าย และสามารถเข้าไป comment ได้
2-post-comment

Test

ดาวโหลด code มาดูได้เลยครับ

Sourcecode

https://github.com/magickiat/myfacebook.git

Advertisements

5 thoughts on “Spring boot ตอนที่ 3 – กรณีศึกษา MyFacebook web (4)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s