/*
* Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package bootstrap;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import models.User;
import models.Widget;
import models.WidgetIcon;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.reflections.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.Play;
import play.api.libs.MimeTypes;
import beans.config.Conf;
import com.google.common.base.Predicate;
/**
* User: guym
* Date: 3/31/13
* Time: 11:50 AM
*/
public class JsonInitialData implements InitialData {
private static Logger logger = LoggerFactory.getLogger( JsonInitialData.class );
@Inject
Conf conf;
@Override
public void load( String dataStr )
{
try{
logger.info( "loading initial data" );
ObjectMapper mapper = new ObjectMapper( );
JsonData data = mapper.readValue( dataStr, JsonData.class );
loadUsers( data.users );
}catch(Exception e){
logger.error( "error while reading initial data",e );
}
}
private void loadUsers( Map<String, JsonUser> users )
{
logger.info( "loading users" );
for ( String username : users.keySet() ) {
logger.info( "loading user : " + username );
User user = findOrCreateUser( username );
JsonUser jsonUser = users.get( username );
Map<String, JsonWidget> widgets =jsonUser.widgets;
for ( String widgetName : widgets.keySet() ) {
logger.info( updateOrCreateWidget( user, widgetName, widgets.get( widgetName ) ).toString() );
}
}
}
public static class InitialDataChange{
public boolean newItem = false;
public boolean override = false;
public String diff = null;
public String name;
@Override
public String toString()
{
return "InitialDataChange{" +
"newItem=" + newItem +
", diff='" + diff + '\'' +
", name='" + name + '\'' +
", override='" + override + '\'' +
'}';
}
}
public InitialDataChange updateOrCreateWidget( User user, String widgetName, JsonWidget widgetJson ){
InitialDataChange result = new InitialDataChange();
result.name = widgetName;
Widget w = null;
Widget newWidget = null;
for ( Widget widget : user.getWidgets() ) {
if ( widget.getProductName().equals( widgetName )){
w = widget;
break;
}
}
newWidget = new Widget( widgetName, widgetJson.version, widgetJson.title, widgetJson.youtube, widgetJson.provider, widgetJson.recipe, widgetJson.console.title, widgetJson.console.link, widgetJson.path );
newWidget.setConsoleUrlService( widgetJson.console.service );
newWidget.setRecipeName( widgetJson.name );
newWidget.setDescription( widgetJson.description );
// handle requires login
if ( widgetJson.login != null ) {
newWidget.setRequireLogin( widgetJson.login.require );
newWidget.setLoginVerificationUrl( widgetJson.login.url );
newWidget.setWebServiceKey( widgetJson.login.token );
}
if ( w == null ){
result.newItem = true;
w = user.addNewWidget( newWidget );
} else if ( conf.settings.initialData.override ) {
result.override = true;
String apiKey = w.getApiKey();
w.delete( );
newWidget.setApiKey( apiKey );
w = user.addNewWidget( newWidget );
} else {
result.diff = diffObjects( newWidget, w, new HashSet<String>( ){ {add( "id" ); add( "apiKey" );} } ).toString();
}
// handle image
if ( widgetJson.image != null && !StringUtils.isEmpty( widgetJson.image.selected ) ) {
File file = new File( Play.application().getFile( "conf/initialData/images" ), widgetJson.image.selected );
if ( !file.exists() ) {
logger.warn( "image file does not exist! [{}]", file.getAbsolutePath() );
} else {
WidgetIcon icon = WidgetIcon.findByWidgetApiKey( w.getApiKey() );
if ( icon == null ) {
logger.info( "creating icon from file [{}]", file.getName() );
icon = new WidgetIcon();
updateAndSave( file, icon, w );
}else if ( conf.settings.initialData.override ){
logger.info( "overriding icon" );
updateAndSave( file, icon, w );
}
}
}
return result;
}
private void updateAndSave( File file, WidgetIcon icon, Widget w )
{
String contentType = MimeTypes.forFileName( file.getName() ).get();
icon.setContentType( contentType );
try {
icon.setData( IOUtils.toByteArray(new FileInputStream( file ) ) );
} catch ( Exception e ) {
logger.error( "unable to read file to byte array", e );
}
icon.setName( file.getName() );
icon.save( );
w.setIcon( icon );
w.save( );
}
public User findOrCreateUser ( String username ){
User u = User.find.where( ).eq( "email", username ).findUnique();
if ( u == null ){
u = User.newUser(null, null, username, conf.settings.initialData.defaultPassword);
u.save( );
}
return u;
}
public void setConf( Conf conf )
{
this.conf = conf;
}
public static class JsonConsole{
public String title;
public String link;
public String service;
}
public static class JsonImage{
public String selected;
}
public static class JsonLogin{
public boolean require = false;
public String url = null;
public String token = null;
}
public static class JsonWidget{
public String version;
public String title;
public String youtube;
public String description;
public String name;
public String provider;
public String recipe;
public JsonConsole console = new JsonConsole();
public String path;
public JsonImage image = new JsonImage();
public JsonLogin login = new JsonLogin();
}
public static class JsonUser{
public Map<String, JsonWidget> widgets = new HashMap<String, JsonWidget>( );
}
public static class JsonData
{
public Map<String, JsonUser> users = new HashMap<String, JsonUser>( );
}
private List<DiffRecord> diffObjects( Object newObject, Object oldObject, final Set<String> ignoreFields ){
List<DiffRecord> result = new LinkedList<DiffRecord>( );
Set<Field> allFields = ReflectionUtils.getAllFields( newObject.getClass(), new Predicate<Field>() {
@Override
public boolean apply( Field field )
{
return !ignoreFields.contains( field.getName() );
}
} );
for ( Field field : allFields ) {
try{
Object oldValue = FieldUtils.readField( field, oldObject, true );
Object newValue = FieldUtils.readField( field, oldObject, true );
if ( !ObjectUtils.equals(oldValue, newValue) ){
result.add( new DiffRecord( field.getName(), oldValue, newValue ) );
}
}catch(Exception e){
logger.error( "unable to get field values [{}]", e );
}
}
return result;
}
public static class DiffRecord {
public String fieldName;
public Object oldValue;
public Object newValue;
public DiffRecord( String fieldName, Object oldValue, Object newValue )
{
this.fieldName = fieldName;
this.oldValue = oldValue;
this.newValue = newValue;
}
}
}