/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.usergrid.tools;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.usergrid.management.ApplicationInfo;
import org.apache.usergrid.persistence.*;
import org.apache.usergrid.persistence.index.query.Identifier;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Map;
/**
* Tools class which takes a json file as an input. Each property in the input is then set into each entity that is
* returned from the query. Used for performing data migrations. It requires an app name or ID, the collection name,
* the input update file and the query to find all matches to update. For instance, to set every admin to approved =
* true and confirmed = true. You would have this json file.
* <p/>
* <pre>
* {
* "activated":true,
* "confirmed":true
* }
* </pre>
* <p/>
* And execute the following options
* <p/>
* EntityUpdate -host 127.0.0.1:9160 -app 00000000-0000-0000-0000-000000000001 -col users -query "select * where
* activated = false or confirmed = false" -update update.json
*
* @author tnine
*/
public class EntityUpdate extends ToolBase {
/**
*
*/
private static final String QUERY_ARG = "query";
/**
*
*/
private static final String APPLICATION_ARG = "app";
/**
*
*/
private static final String COLLECTION_ARG = "col";
/** Used to provide the update file */
private static final String UPDATE_ARG = "update";
//parse the content as a json entity
private static ObjectMapper MAPPER = new ObjectMapper();
/**
*
*/
private static final int PAGE_SIZE = 100;
private static final Logger logger = LoggerFactory.getLogger( EntityUpdate.class );
@Override
public void runTool( CommandLine line ) throws Exception {
startSpring();
setVerbose( line );
String collectionName = line.getOptionValue( COLLECTION_ARG );
String queryString = line.getOptionValue( QUERY_ARG );
String updateFile = line.getOptionValue( UPDATE_ARG );
Query query = Query.fromQL( queryString );
logger.info( "Parsing the file at {}", updateFile );
File file = new File( updateFile );
if ( !file.exists() ) {
logger.error( "The file {} does not exist. Please make sure you have read access so this file. Exiting.",
updateFile );
System.exit( 1 );
}
DynamicEntity update = MAPPER.readValue( file, DynamicEntity.class );
if ( update.getProperties().size() == 0 ) {
logger.error( "The update in file {} has no properties. Exiting", updateFile );
System.exit( 2 );
}
String appName = line.getOptionValue( APPLICATION_ARG );
ApplicationInfo app = managementService.getApplicationInfo( Identifier.from( appName ) );
if ( app == null ) {
logger.error( "Could not find application with id or name {}", appName );
System.exit( 3 );
}
EntityManager entityManager = emf.getEntityManager( app.getId() );
Results results = entityManager.searchCollection( entityManager.getApplicationRef(), collectionName, query );
PagingResultsIterator itr =
new PagingResultsIterator( results, Query.Level.ALL_PROPERTIES, Query.Level.ALL_PROPERTIES );
long count = 0;
for ( Object next : itr ) {
Entity entity = ( Entity ) next;
//set all props
for ( Map.Entry<String, Object> entry : update.getProperties().entrySet() ) {
entity.setProperty( entry.getKey(), entry.getValue() );
}
entityManager.update( entity );
logger.info( "Updated entity in application {} with id {} of type {}",
new Object[] { app.getId(), entity.getUuid(), entity.getType() } );
count++;
}
logger.info( "Process complete. Updated {} entities", count );
}
@Override
public Options createOptions() {
Options options = super.createOptions();
@SuppressWarnings("static-access") Option queryOption =
OptionBuilder.withArgName( QUERY_ARG ).hasArg().isRequired( true )
.withDescription( "Query to execute when searching for organizations" )
.create( QUERY_ARG );
options.addOption( queryOption );
Option hostOption =
OptionBuilder.withArgName( "host" ).hasArg().isRequired( true ).withDescription( "Cassandra host" )
.create( "host" );
options.addOption( hostOption );
Option appOption = OptionBuilder.withArgName( APPLICATION_ARG ).hasArg().isRequired( true )
.withDescription( "application id or app name" ).create( APPLICATION_ARG );
options.addOption( appOption );
Option collectionOption = OptionBuilder.withArgName( COLLECTION_ARG ).hasArg().isRequired( true )
.withDescription( "colleciton name" ).create( COLLECTION_ARG );
options.addOption( collectionOption );
Option updateOption =
OptionBuilder.withArgName( UPDATE_ARG ).hasArg().isRequired( true ).withDescription( "Update file" )
.create( UPDATE_ARG );
options.addOption( updateOption );
return options;
}
}