Is there possibility for FreeMarker to create a directory or package on Android Studio templating? - android-studio

I'm trying to create a template that has a nested package.
Here's my templating code.
// root/global.xml.ftl
<?xml version="1.0"?>
<globals>
<global id="simpleLayoutName" value="${layoutName}"/>
<global id="excludeMenu" type="boolean" value="true"/>
<global id="resOut" value="${resDir}"/>
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}"/>
<#include "../common/common_globals.xml.ftl" />
</globals>
// root/recipe.xml.ftl
<?xml version="1.0"?>
<recipe>
<#if generateLayout>
<#include "../common/recipe_simple.xml.ftl" />
<open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml"/>
</#if>
<instantiate from="root/src/app_package/SimpleFragment.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}Fragment.kt"/>
</recipe>
// root/template.xml
<?xml version="1.0"?>
<template
format="5"
revision="1"
name="MVVM Activity"
minApi="9"
minBuildApi="14"
description="Creates a new empty activity that uses MVVM Pattern">
<category value="Activity" />
<formfactor value="Mobile" />
<parameter
id="generateLayout"
name="Generate Layout File"
type="boolean"
default="true"
help="If true, a layout file will be generated" />
<parameter
id="layoutName"
name="Layout Name"
type="string"
constraints="layout|unique|nonempty"
suggest="${activityToLayout(activityClass)}"
default="activity_main"
visibility="generateLayout"
help="The name of the layout to create for the activity" />
<parameter
id="packageName"
name="Package name"
type="string"
constraints="package"
default="com.mycompany.myapp" />
<!-- 128x128 thumbnails relative to template.xml -->
<thumbs>
<!-- default thumbnail is required -->
<thumb>template_MVVM_activity.png</thumb>
</thumbs>
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>
// root/src/app_package/SimpleFragment.kt.ftl
package ${packageName}
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
class ${fragmentClass}Fragment : Fragment() {
// TODO: Implement by lazy ViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// TODO: Init or setup view, viewmodel related, etc anything to setup here
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// TODO: Init or setup view, viewmodel related, etc anything to setup here
}
}
But, I didn't find any function to create a directory here: http://freemarker.apache.org/docs
Looks like I'm missing something here, is there anyone ever doing this to achieve creating a package inside output directory.
I quite catch that recipe.xml.ftl able to instantiate new file, but I still didn't try to create a directory instead, is it possible? What should add for from attribute value?

According to this article. By default, you can do this without any extra effort. Just point the new package on recipe.xml.ftl e.g:
<instantiate from="root/src/main/java/model/Simple.kt.ftl"
to="${escapeXmlAttribute(srcOut)}/model/${modelName}.kt"/>
to element will creating the new model package inside your destination directdory.

Related

Using global actions with multiple graphs in jetpack navigation

I created an application with a bottom navigation bar and added four different nav graphs using google's advanced navigation example
After that I added a fifth graph called settings that had the settings fragment along with a global action
I added an include to that graph on each of the first four graphs
when I do something like findNavController(R.id.container).navigate(SettingsDirections.showSettings()) the app crashes because it cannot find the destination or the action
but when I copy the fragment and the global action inside each of those graphs and call the above (with that graph's directions) it works
am I missing something? doesn't include actually copy everything from the other graph the original?
It seems that the include tag does not actually include all of the nav graph including the global actions
so in case someone wants to do something similar here is how I did it
first I updated the settings navigation to include a dummy action to show settings like so:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/settings"
app:startDestination="#+id/settings_dest">
<include app:graph="#navigation/questions" />
<!--this is just so safeargs will create a SettingsNavigation.showSettings it is never actually used-->
<action
android:id="#+id/show_settings"
app:destination="#id/settings_dest" />
<fragment
android:id="#+id/settings_dest"
android:name="com.example.app.ui.fragments.SettingsFragment"
android:label="#string/settings"
tools:layout="#layout/fragment_settings" >
<argument
app:argType="com.example.app.ui.model.SettingsProfile"
android:name="profile"
app:nullable="false"/>
</fragment>
</navigation>
and then on every nav graph that I wanted to use the show_settings action I would do by including this:
<include app:graph="#navigation/settings" />
<action
android:id="#+id/show_settings"
app:destination="#id/settings"
app:enterAnim="#anim/fade_in"
app:exitAnim="#anim/fade_out"
app:popEnterAnim="#anim/fade_in"
app:popExitAnim="#anim/fade_out" />
so now when I want to use directions to go to settings I do it like this
findNavController().navigate(SettingsDirections.showSettings(profile))
this will use the directions created in my settings.xml to execute the action in my current nav controller
it is important by the way the id of the action in the included file and the id of the action of the file including it to be the same
Let me show you with an example
<navigation ...
app:startDestination:"#id/nav_graph_one">
<include app:graph:"#navigation/nav_graph_one"/>
<include app:graph:"#navigation/nav_graph_two"/>
<fragment
android:id="#+id/aCommonFragment"
.../>
<action
android:id="#+id/action_grobal_aCommonFragment
app:destination="#+id/aCommonFragment"/>
</navigation>
Any where from your app you can now use
findNavController().navigate(NavGraphDirections.actionGlobalACommonFragment)
By copying nodes and actions from global actions graph to main graph in runtime it is possible to use global actions in all subgraphs and stay them in separate file.
main graph:
<navigation android:id="#+id/main_graph">
<include app:graph="#navigation/subgraph1"/>
<include app:graph="#navigation/subgraph2"/>
<navigation/>
global actions graph:
<navigation android:id="#+id/customer_dialogs">
<action android:id="#+id/actionToShareCustomer"
android:destionation="#id/shareCustomerDialog"/>
<dialog android:id="#+id/shareCustomerDialog">
<argument android:id="#+id/customerId" app:argType="long"/>
</dialog>
<navigation/>
programmatically set main_graph to navController:
override fun onCreate(savedInstanceState: Bundle?) {
with(navHostFragment.findNavController()) {
val mainGraph = navInflater.inflate(R.navigation.main_graph)
val actionsGraph = navInflater.inflate(R.navigation.customer_dialogs)
copyGraph(actionsGraph, mainGraph)
setGraph(mainGraph, null)
}
}
fun copyGraph(from: NavGraph, to: NavGraph) {
to.addAll(from)
val actions = NavDestination::class.java.getDeclaredField("actions").let {
it.isAccessible = true
it.get(from)
} as? SparseArrayCompat<NavAction>
actions?.forEach { actionId, action -> to.putAction(actionId, action) }
}
usage of action from fragment of subgraph1:
private fun shareCustomer(customerId: Long) {
findNavController().navigate(CustomerDialogsDirections.actionToShareCustomer(customerId))
}
I created an extension function when setting the default animation
fun View.navigate(id: Int, navOptions: NavOptions? = null){
var updatedNavOptions = navOptions
if(updatedNavOptions == null){
updatedNavOptions = navOptions {
anim {
enter = R.anim.slide_in_right
exit = R.anim.slide_out_left
popEnter = R.anim.slide_in_left
popExit = R.anim.slide_out_right
}
}
}
this.findNavController().navigate(id, null, updatedNavOptions)
}
In my fragment just do so:
my_view.click { view?.navigate(R.id.how_referral_program_works) }

SAP Hybris E-commerce : Send Email in CronJob

I have created a CronJob that works perfectly.
But I want to generate the sending of an email within this Cronjob. I followed a tutorial on the internet.
I start with the creation itemType of ProductsApprovedEmailProcess.
then I created productsApprovedEmailProcess to define the steps be executed by the Process Engine as follow
Then I have added an EmailContext to holds the data to be passed to the email template as follow
public class ProductsApprovedEmailContext extends CustomerEmailContext
{
private String message;
#Override
public void init(final StoreFrontCustomerProcessModel processModel, final EmailPageModel emailPageModel)
{
super.init(processModel, emailPageModel);
if (processModel instanceof ProductsApprovedEmailProcessModel)
{
setMessage(((ProductsApprovedEmailProcessModel) processModel).getMessage());
}
}
public String getMessage()
{
return message;
}
public void setMessage(final String message)
{
this.message = message;
}
}
And I had register ProductsApprovedEmailContext as a bean in Spring as follow
<bean id="productsApprovedEmailContext" class="com.hybris.training.facades.process.email.context.ProductsApprovedEmailContext"
parent="abstractEmailContext"
scope="prototype" >
</bean>
Then I created 2 Velocity templates, one for the email Subject and the other for the Body email-productsapproved-subject.vm and email-productsapproved-body.vm
And the following impex allows you to create RendererTemplates for the Subject and the Body, and attach them to an EmailPageTemplate as follow
$contentCatalog=electronicsContentCatalog
$contentCV=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),CatalogVersion.version[default=Online])[default=$contentCatalog:Online]
UPDATE GenericItem[processor=de.hybris.platform.commerceservices.impex.impl.ConfigPropertyImportProcessor];pk[unique=true]
$emailResource=$config-emailResourceValue
$emailPackageName=$config-emailContextPackageName
$lang=en
INSERT_UPDATE RendererTemplate ;code[unique=true] ;contextClass ;templateScript[lang=en,translator=de.hybris.platform.commerceservices.impex.impl.FileLoaderValueTranslator];rendererType(code)[default='velocity']
;email-productsapproved-body ;$emailPackageName.ProductsApprovedEmailContext ;$emailResource/email-productsapproved-body.vm
;email-productsapproved-subject ;$emailPackageName.ProductsApprovedEmailContext ;$emailResource/email-productsapproved-subject.vm
INSERT_UPDATE EmailPage ;$contentCV[unique=true];uid[unique=true] ;masterTemplate(uid,$contentCV) ;approvalStatus(code)[default='approved']
; ;ProductApprovedEmail ;ProductApprovedEmailTemplate ;
And in the Cronjob I added this code !
final ProductsApprovedEmailProcessModel productsApprovedEmailProcessModel = (ProductsApprovedEmailProcessModel) businessProcessService
.createProcess("productsApprovedEmailProcess" + "-" + System.currentTimeMillis(), "productsApprovedEmailProcess");
productsApprovedEmailProcessModel.setMessage("Products approved in csv file");
productsApprovedEmailProcessModel.setSite(baseSiteService.getBaseSiteForUID("electronics"));
productsApprovedEmailProcessModel.setLanguage(CommerceCommonI18NService.getCurrentLanguage());
modelService.save(productsApprovedEmailProcessModel);
businessProcessService.startProcess(productsApprovedEmailProcessModel);
But a acheive this error when I'm strating CronJob using HMC Interface :
Error executing ActionNode with ID [generateProductsApprovedEmail]: HtmlTemplate associated with MasterTemplate of EmailPageModel cannot be null
UPDATE :
Here is my business process :
<process xmlns="http://www.hybris.de/xsd/processdefinition"
start="generateProductsApprovedEmail"
name="productsApprovedEmailProcess"
processClass="com.hybris.training.core.model.process.ProductsApprovedEmailProcessModel"
onError="error">
<action id="generateProductsApprovedEmail" bean="generateProductsApprovedEmail">
<transition name="OK" to="sendEmail"/>
<transition name="NOK" to="error"/>
</action>
<action id="sendEmail" bean="sendEmail">
<transition name="OK" to="removeSentEmail"/>
<transition name="NOK" to="failed"/>
</action>
<action id="removeSentEmail" bean="removeSentEmail">
<transition name="OK" to="success"/>
<transition name="NOK" to="error"/>
</action>
<end id="error" state="ERROR">Something went wrong.</end>
<end id="failed" state="FAILED">Could not send products approved in csv File email.</end>
<end id="success" state="SUCCEEDED">Sent file in email.</end>
After declaring ProductApprovedEmailTemplate (EmailPageTemplate) i got this warn and the mail is not generated :
WARN [TaskExecutor-master-264-ProcessTask [8796715713462]] [GenerateEmailAction] Could not retrieve email page model for ProductApprovedEmail and Electronics Content Catalog:Online, cannot generate email content
Look like, the blog you have followed, it has mentioned each step correctly, but you might be missed something.
Make sure you have followed the below steps correctly.
e.g.
frontendTemplateName should be matched with EmailPageTemplate one
<bean id="generateProductApprovedEmail" parent="abstractGenerateEmailAction">
<property name="frontendTemplateName" value="ProductApprovedEmail"/>
</bean>
Create Email page Template
INSERT_UPDATE EmailPageTemplate ;$contentCV[unique=true];uid[unique=true] ;active ;frontendTemplateName ;subject(code) ;htmlTemplate(code) ;restrictedPageTypes(code)
; ;ProductApprovedEmailTemplate ;true ;ProductApprovedEmail ;email-productsapproved-subject ;email-productsapproved-body ;EmailPage
Create Email Page
INSERT_UPDATE EmailPage ;$contentCV[unique=true];uid[unique=true] ;masterTemplate(uid,$contentCV);approvalStatus(code)[default='approved']
; ;ProductApprovedEmail ;ProductApprovedEmailTemplate ;

Spring Integration - Scheduling Job from configuration file

I'm using Spring Integration to parse XML file and i will need to create a thread (and each one have a different rate) for each tag.
Right now (with the help of many users here :)) i'm able to split XML by tag and then route it to the appropiate service-activator.
This works great but i'm not able to redirect to a channel that create "a thread" and then execute the operations. Right now i have the following configuration and in my mind (that i dont know if it is correct...)
Split tag -> Route to the appropiate channel -> Start a thread(from tag configuration) -> Execute the operation
This is my actual configuration that split tag and redirect to the channel.
The router should redirect not toward a channel directly, but schedule them.
In first instance will be enought to redirect it in a pool with fixed rate and later i will use XPATH to get the attribute and then replace this "fixed" rate with the correct value.
I've tried many solutions to create this flow but each one fails or do not compile :(
<context:component-scan base-package="it.mypkg" />
<si:channel id="rootChannel" />
<si-xml:xpath-splitter id="mySplitter" input-channel="rootChannel" output-channel="routerChannel" create-documents="true">
<si-xml:xpath-expression expression="//service" />
</si-xml:xpath-splitter>
<si-xml:xpath-router id="router" input-channel="routerChannel" evaluate-as-string="true">
<si-xml:xpath-expression expression="concat(name(./node()), 'Channel')" />
</si-xml:xpath-router>
<si:service-activator input-channel="serviceChannel" output-channel="endChannel">
<bean class="it.mypkg.Service" />
</si:service-activator>
UPDATE:
Using this configuration for the service this should run a task every 10 seconds (the id=service1) and every 5 seconds the other (the id=service2). In the same way i can have another tag that is handle by another class (because this will have another behaviour)
<root>
<service id="service1" interval="10000" />
<service id="service2" interval="5000" />
<activity id="activity1" interval="50000" />
<root>
I will have a classe (Service) that is general to handle Service tag and this complete some operation and then "return me" the value so i can redirect to another channel.
public class Service {
public int execute() {
// Execute the task and return the value to continue the "chain"
}
}
It's not at all clear what you mean; you split a tag; route it but want to "schedule" it at a rate in the XML. It's not clear what you mean by "schedule" here - normally each message is processed once not multiple times on a schedule.
As I said, I don't understand what you need to do, but a smart poller might be suitable.
Another possibility is the delayer where the amount of the delay can be derived from the message.
EDIT
Since your "services" don't seem to take any input data, it looks like you simply need to configure/start an <inbound-channel-adapter/> for each service, and then start it, based on the arguments in the XML.
<int:inbound-channel-adapter id="service1" channel="foo"
auto-startup="false"
ref="service1Bean" method="execute">
<poller fixed-delay="1000" />
</int:inbound-channel-adapter/>
Note auto-startup="false".
Now, in the code that receives the split
#Autowired
SourcePollingChannelAdapter service1;
...
public void startService1(Node node) {
...
service1.setTrigger(new PeridicTrigger(...));
service1.start();
...
}
I dont know if this is the right way to implement the flow, but i've write the follow code:
applicationContext.xml
<context:component-scan base-package="it.mypkg" />
<!-- Expression to extract interval from XML tag -->
<si-xml:xpath-expression id="selectIntervalXpath" expression="//*/#interval" />
<si:channel id="rootChannel" />
<!-- Split each tag to redirect on router -->
<si-xml:xpath-splitter id="mySplitter" input-channel="rootChannel" output-channel="routerChannel" create-documents="true">
<si-xml:xpath-expression expression="//service|//activity" />
</si-xml:xpath-splitter>
<!-- Route each tag to the appropiate channel -->
<si-xml:xpath-router id="router" input-channel="routerChannel" evaluate-as-string="true">
<si-xml:xpath-expression expression="concat(name(./node()), 'Channel')" />
</si-xml:xpath-router>
<!-- Activator for Service Tag -->
<si:service-activator input-channel="serviceChannel" method="schedule">
<bean class="it.mypkg.Service" />
</si:service-activator>
<!-- Activator for Activity Tag -->
<si:service-activator input-channel="activityChannel" method="schedule">
<bean class="it.mypkg.Activity" />
</si:service-activator>
<!-- Task scheduler -->
<task:scheduler id="taskScheduler" pool-size="10"/>
Each tag will extend an Operation class (to avoid code duplication on bean injection)
Operation.java
public abstract class Operation {
protected TaskScheduler taskScheduler;
protected XPathExpression selectIntervalXpath;
abstract public void schedule(Node document);
#Autowired
public void setTaskScheduler(TaskScheduler taskScheduler) {
this.taskScheduler= taskScheduler;
}
public TaskScheduler getTaskScheduler() {
return this.taskScheduler;
}
#Autowired
public void setSelectIntervalXpath(XPathExpression selectIntervalXpath) {
this.selectIntervalXpath = selectIntervalXpath;
}
public XPathExpression getSelectIntervalXPath() {
return this.selectIntervalXpath;
}
}
And an example of Service class (that handle all tags service provided on .xml)
public class Service extends Operation {
private static final Logger log = Logger.getLogger(Service.class);
#Override
public void schedule(Node document) {
log.debug("Scheduling Service");
long interval = Long.parseLong(this.selectIntervalXpath.evaluateAsString(document));
this.taskScheduler.scheduleAtFixedRate(new ServiceRunner(), interval);
}
private class ServiceRunner implements Runnable {
public void run() {
log.debug("Running...");
}
}
}
Now to continue my flow i will need to find a way to redirect the output of each job to Spring Integration (applicationContext.xml).

How to create a declarative HTML helper in MVC 5

my scenario:
I am finally getting around to creating my own blog, and I am trying to learn as much as possible with regards to MVC while doing so. I am trying to display my tags as a custom declarative helper in my "PostView.cshtml" file but my problem is that it isn't in the current context and I don't know how to make it so.
I have had a look at the following 2 questions on SO:
this one is for previous version of MVC (<= 4) and
this one was answered by the guy who asked the question and isn't very explanatory.
I tried the above advice but with no success, hopefully someone can help me out. Here is my code:
Tags.cshtml (in ~/Views/Helpers/):
#helper Tags(System.Web.Mvc.HtmlHelper htmlHelper,
ICollection<MyNamespace.Objects.Tag> tags)
{
foreach (var tag in tags)
{
<div class="tags-div">
#MyNamespace.Extensions.ActionLinkExtensions.TagLink(htmlHelper, tag):
</div>
}
}
ActionLinkExtensions.cs (in ~/Extensions/ActionLinkExtensions/)
namespace MyNamespace.Extensions
{
public static class ActionLinkExtensions
{
public static MvcHtmlString TagLink(this HtmlHelper helper, Tag tag)
{
return helper.ActionLink("", ""); //logic removed for simplicity
}
}
}
PostView.cshtml (in ~/Views/Shared/) //where i want to use my custom helper:
#model MyNamespace.Objects.Post
<!--extra html removed for simplicity-->
<div>
<span>Tags:</span>#Tags(Html, Model.Tags) // '#Tags' doesn't exist in current context
</div>
I also tried adding namespaces to '~/Views/web.config':
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="MyNamespace" />
<add namespace="MyNamespace.Extensions" />
</namespaces>
</pages>
My "full name" for my "Tag.cs" class is MyNamespace.Objects.Tag and "Post".cs" is MyNamespace.Objects.Post.
Any explanations and advice with an answer would be greatly appreciated too, thank you very much in advance.
I decided to try use MVC3 way, I added the App_Code folder manually and followed steps from this great article.
And it worked, I needed to restart Visual Studio for my Intellisense to work (which prolonged finding my solution).
I deleted the folder '~/Views/Shared/'
I Added a file MyHelpers.cshtml into the App_Code folder, inside the file I added my helper method:
#helper Tags(System.Web.Mvc.HtmlHelper htmlHelper,
ICollection<MyNamespace.Objects.Tag> tags)
{
foreach (var tag in tags)
{
<div class="tags-div">
#MyNamespace.Extensions.ActionLinkExtensions.TagLink(htmlHelper, tag)
</div>
}
}
And called it in my PostView.cshtml like so:
#MyHelpers.Tags(Html, Model.Tags)
And Viola works as expected... hopefully this helps someone else who ends up in this situation...
I believe the better and simpler way would be to define a display template for you Tags collection that would be placed in ~Views/Shared/DisplayTemplates:
#model ICollection<MyNamespace.Objects.Tag>
foreach (var tag in Model)
{
<div class="tags-div">
#MyNamespace.Extensions.ActionLinkExtensions.TagLink(htmlHelper, tag)
</div>
}
In your PostView.cshtml you would then just write:
#Html.DisplayFor(model => model.Tags)

How to 'force' Magento to load a different layout

Background: I need to be able to load upsell / crosssell products in a lightbox complete with add-to-cart functionality.
My idea for achieving this was to 'force' Magento to load products in a different layout. I thought of using an observer on the controller_action_layout_generate_xml_before event (code below).
Unfortunately what I have is not working. Any pointers (or completely different / better ideas) are much appreciated.
<?php
class My_ForceLayout_Model_Observer
{
public function changeLayoutEvent($observer)
{
$action = $observer->getEvent()->getAction();
$layout = $observer->getEvent()->getLayout();
if($action->getRequest()->getControllerName() == 'product'
&& $action->getRequest()->getActionName() == 'view')
{
$update = $layout->getUpdate();
$update->load('popup'); // for testing only
$layout->generateXml();
}
}
}
I managed to get this to work exactly as I first intended. Thanks to #Jonathan Day for making me realize the reason it was not working was trivial.
Config.xml:
<config>
....
<frontend>
<events>
<controller_action_layout_generate_blocks_before>
<observers>
<forcelayout>
<type>singleton</type>
<class>forcelayout/observer</class>
<method>changeLayoutEvent</method>
</forcelayout>
</observers>
</controller_action_layout_generate_blocks_before>
</events>
</frontend>
....
</config>
Observer.php:
class Unleaded_ForceLayout_Model_Observer
{
public function changeLayoutEvent($observer)
{
$action = $observer->getEvent()->getAction();
$layout = $observer->getEvent()->getLayout();
if($action->getRequest()->getControllerName() == 'product'
&& $action->getRequest()->getActionName() == 'view')
{
$template = $action->getRequest()->template;
if (isset($template) && $template != '')
{
$update = $layout->getUpdate();
$update->load($template);
$layout->generateXml();
}
}
}
}
Local.xml:
<popup translate="label">
<label>Catalog Product View Lightbox</label>
<remove name="right"/>
<remove name="left"/>
<reference name="root">
<action method="setTemplate">
<template>page/popup.phtml</template>
</action>
</reference>
<reference name="content">
<remove name="product.info.upsell"/>
</reference>
</popup>
Product url in .phtml file:
echo $this->getProductUrl($_item) . '?template=popup';
Why don't you want to use just regular layout udates?
<catalog_product_view translate="label">
<label>Catalog Product View (Any)</label>
<!-- Mage_Catalog -->
<remove name="right"/>
<remove name="left"/>
<reference name="content">
<block type="new_catalog/product_view"
name="new.product.info"
template="new/catalog/product/view_popup.phtml">
...
</block>
</reference>
</catalog_product_view>
If you want to change the design of your product page depends on some conditions, you could use layout handler functionality. It means that you have to check your parameters in controller and add handler for layout updates, then you could use it in layout file as any other handler. For example:
if ($this->check_parameters()) {
$update->addHandle('new_magic_handler');
$this->loadLayoutUpdates();
}
And in layout:
<new_magic_handler translate="label">
<label>New Magic</label>
...
</new_magic_handler>
Check for details Mage_Catalog_ProductController::_initProductLayout()

Resources