Package org.drools.repository

Source Code of org.drools.repository.AssetItem

/*
* Copyright 2010 JBoss Inc
*
* 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 org.drools.repository;

import java.io.*;
import java.util.Calendar;
import java.util.Iterator;

import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

import org.drools.repository.events.StorageEventManager;
import org.drools.repository.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The RuleItem class is used to abstract away the details of the underlying JCR
* repository. It is used to pass information about rules stored in the
* repository.
*
* @author btruitt
*/
public class AssetItem extends CategorisableItem {
    private Logger             log                                  = LoggerFactory.getLogger( AssetItem.class );
    /**
     * The name of the rule node type
     */
    public static final String RULE_NODE_TYPE_NAME                  = "drools:assetNodeType";

    public static final String CONTENT_PROPERTY_NAME                = "drools:content";
    public static final String CONTENT_PROPERTY_BINARY_NAME         = "drools:binaryContent";
    public static final String CONTENT_PROPERTY_ATTACHMENT_FILENAME = "drools:attachmentFileName";

    /**
     * The name of the date effective property on the rule node type
     */
    public static final String DATE_EFFECTIVE_PROPERTY_NAME         = "drools:dateEffective";

    public static final String DISABLED_PROPERTY_NAME               = "drools:disabled";

    /**
     * The name of the date expired property on the rule node type
     */
    public static final String DATE_EXPIRED_PROPERTY_NAME           = "drools:dateExpired";

    public static final String PACKAGE_NAME_PROPERTY                = "drools:packageName";

    /**
     * Constructs a RuleItem object, setting its node attribute to the specified
     * node.
     *
     * @param rulesRepository
     *            the rulesRepository that instantiated this object
     * @param node
     *            the node in the repository that this RuleItem corresponds to
     * @throws RulesRepositoryException
     */
    public AssetItem(RulesRepository rulesRepository,
                     Node node) throws RulesRepositoryException {
        super( rulesRepository,
               node );
        try {
            // make sure this node is a rule node
            if ( !(this.node.getPrimaryNodeType().getName().equals( RULE_NODE_TYPE_NAME ) || isHistoricalVersion()) ) {
                String message = this.node.getName() + " is not a node of type " + RULE_NODE_TYPE_NAME + " nor nt:version. It is a node of type: " + this.node.getPrimaryNodeType().getName();
                log.error( message );
                throw new RulesRepositoryException( message );
            }
        } catch ( Exception e ) {
            log.error( "Caught exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    public AssetItem() {
        super( null,
               null );
    }

    /**
     * returns the string contents of the rule node. If this is a binary asset,
     * this will return null (use getBinaryContent instead).
     */
    public String getContent() throws RulesRepositoryException {
        return getContent( false );
    }

    /**
     * Only for use in the StorageEventManager, for passing the fromRepo
     * parameter
     *
     * returns the string contents of the rule node. If this is a binary asset,
     * this will return null (use getBinaryContent instead).
     */
    public String getContent(Boolean fromRepo) throws RulesRepositoryException {
        try {

            if ( StorageEventManager.hasLoadEvent() && !fromRepo ) {
                return IOUtils.toString( StorageEventManager.getLoadEvent().loadContent( this ) );
            }

            if ( isBinary() ) {
                return new String( this.getBinaryContentAsBytes() );
            }
            Node ruleNode = getVersionContentNode();
            if ( ruleNode.hasProperty( CONTENT_PROPERTY_NAME ) ) {
                Property data = ruleNode.getProperty( CONTENT_PROPERTY_NAME );
                return data.getValue().getString();

            } else {
                return "";
            }
        } catch ( Exception e ) {
            log.error( "Caught Exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * returns the number of bytes of the content.
     */
    public long getContentLength() {
        try {
            Node ruleNode = getVersionContentNode();
            if ( ruleNode.hasProperty( CONTENT_PROPERTY_BINARY_NAME ) ) {
                Property data = ruleNode.getProperty( CONTENT_PROPERTY_BINARY_NAME );
                return data.getLength();
            } else {
                if ( ruleNode.hasProperty( CONTENT_PROPERTY_NAME ) ) {
                    Property data = ruleNode.getProperty( CONTENT_PROPERTY_NAME );
                    return data.getLength();
                } else {
                    return 0;
                }
            }
        } catch ( RepositoryException e ) {
            log.error( e.getMessage(),
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * True if this is a binary asset (or has binary content).
     */
    public boolean isBinary() {
        try {
            Node ruleNode = getVersionContentNode();
            return ruleNode.hasProperty( CONTENT_PROPERTY_BINARY_NAME );
        } catch ( RepositoryException e ) {
            log.error( e.getMessage(),
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * If this asset contains binary data, this is how you return it. Otherwise
     * it will return null.
     */
    public InputStream getBinaryContentAttachment() {
        try {
            if ( StorageEventManager.hasLoadEvent() ) {
                return StorageEventManager.getLoadEvent().loadContent( this );
            }
            Node ruleNode = getVersionContentNode();
            if ( ruleNode.hasProperty( CONTENT_PROPERTY_BINARY_NAME ) ) {
                Property data = ruleNode.getProperty( CONTENT_PROPERTY_BINARY_NAME );
                return data.getBinary().getStream();
            } else {
                if ( ruleNode.hasProperty( CONTENT_PROPERTY_NAME ) ) {
                    Property data = ruleNode.getProperty( CONTENT_PROPERTY_NAME );
                    return data.getBinary().getStream();
                }
                return null;
            }
        } catch ( Exception e ) {
            log.error( "Caught Exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /** Get the name of the "file" attachment, if one is set. Null otherwise */
    public String getBinaryContentAttachmentFileName() {
        return getStringProperty( CONTENT_PROPERTY_ATTACHMENT_FILENAME );
    }

    /**
     * This is a convenience method for returning the binary data as a byte
     * array.
     */
    public byte[] getBinaryContentAsBytes() {
        try {
            Node ruleNode = getVersionContentNode();
            if ( StorageEventManager.hasLoadEvent() ) {
                return IOUtils.toByteArray( StorageEventManager.getLoadEvent().loadContent( this ) );
            }
            if ( isBinary() ) {
                Property data = ruleNode.getProperty( CONTENT_PROPERTY_BINARY_NAME );
                InputStream in = data.getBinary().getStream();

                // Create the byte array to hold the data
                byte[] bytes = new byte[(int) data.getLength()];

                // Read in the bytes
                int offset = 0;
                int numRead = 0;
                while ( offset < bytes.length && (numRead = in.read( bytes,
                                                                     offset,
                                                                     bytes.length - offset )) >= 0 ) {
                    offset += numRead;
                }

                // Ensure all the bytes have been read in
                if ( offset < bytes.length ) {
                    throw new RulesRepositoryException( "Could not completely read asset " + getName() );
                }

                // Close the input stream and return bytes
                in.close();
                return bytes;
            } else {
                return getContent().getBytes();
            }
        } catch ( Exception e ) {
            log.error( e.getMessage(),
                       e );
            if ( e instanceof RuntimeException ) throw (RuntimeException) e;
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * @return the date the rule becomes effective
     * @throws RulesRepositoryException
     */
    public Calendar getDateEffective() throws RulesRepositoryException {
        try {
            Node ruleNode = getVersionContentNode();

            Property dateEffectiveProperty = ruleNode.getProperty( DATE_EFFECTIVE_PROPERTY_NAME );
            return dateEffectiveProperty.getDate();
        } catch ( PathNotFoundException e ) {
            // doesn't have this property
            return null;
        } catch ( Exception e ) {
            log.error( "Caught Exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * @return if this rule is disabled
     * @throws RulesRepositoryException
     */
    public boolean getDisabled() throws RulesRepositoryException {
        try {
            Node ruleNode = getVersionContentNode();

            Property disabled = ruleNode.getProperty( DISABLED_PROPERTY_NAME );
            return disabled.getBoolean();
        } catch ( PathNotFoundException e ) {
            // doesn't have this property
            return false;
        } catch ( Exception e ) {
            log.error( "Caught Exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

  /**
   * Creates a new version of this object's rule node, updating the effective
   * date for the rule node.
   *
   * @param newDateEffective
   *            the new effective date for the rule
   * @throws RulesRepositoryException
   */
  public void updateDateEffective(Calendar newDateEffective)
      throws RulesRepositoryException {
    checkIsUpdateable();
    checkout();
    try {
      if (newDateEffective!=null || this.node.hasProperty(DATE_EFFECTIVE_PROPERTY_NAME)) {
        this.node.setProperty(DATE_EFFECTIVE_PROPERTY_NAME,
          newDateEffective);
      }
    } catch (RepositoryException e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

    /**
     * Creates a new version of this object's rule node, updating the disable
     * value for the rule node.
     *
     * @param disabled
     *            is this rule disabled
     * @throws RulesRepositoryException
     */
    public void updateDisabled(boolean disabled) throws RulesRepositoryException {
        checkIsUpdateable();
        checkout();
        try {
            this.node.setProperty( DISABLED_PROPERTY_NAME,
                                   disabled );
        } catch ( RepositoryException e ) {
            log.error( "Caught Exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * @return the date the rule becomes expired
     * @throws RulesRepositoryException
     */
    public Calendar getDateExpired() throws RulesRepositoryException {
        try {
            Node ruleNode = getVersionContentNode();

            Property dateExpiredProperty = ruleNode.getProperty( DATE_EXPIRED_PROPERTY_NAME );
            return dateExpiredProperty.getDate();
        } catch ( PathNotFoundException e ) {
            // doesn't have this property
            return null;
        } catch ( Exception e ) {
            log.error( "Caught Exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * Creates a new version of this object's rule node, updating the expired
     * date for the rule node.
     *
     * @param newDateExpired
     *            the new expired date for the rule
     * @throws RulesRepositoryException
     */
    public void updateDateExpired(Calendar newDateExpired) throws RulesRepositoryException {
        checkout();

    try {
      if (newDateExpired!=null || this.node.hasProperty(DATE_EXPIRED_PROPERTY_NAME)) {
        this.node.setProperty(DATE_EXPIRED_PROPERTY_NAME, newDateExpired);
      }
    } catch (Exception e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

    /**
     * This will update the asset's content (checking it out if it is not
     * already). This will not save the session or create a new version of the
     * node (this has to be done seperately, as several properties may change as
     * part of one edit). This is only used if the asset is a textual asset. For
     * binary, use the updateBinaryContent method instead.
     */
    public AssetItem updateContent(String newRuleContent) throws RulesRepositoryException {
        checkout();
        try {
            if ( this.isBinary() ) {
                this.updateBinaryContentAttachment( new ByteArrayInputStream( newRuleContent.getBytes() ) );
            }
            this.node.setProperty( CONTENT_PROPERTY_NAME,
                                   newRuleContent );
            return this;
        } catch ( RepositoryException e ) {
            log.error( "Unable to update the asset content",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * If the asset is a binary asset, then use this to update the content (do
     * NOT use text).
     */
    public AssetItem updateBinaryContentAttachment(InputStream data) {
        checkout();
        try {
            Binary is = this.node.getSession().getValueFactory().createBinary( data );
            this.node.setProperty( CONTENT_PROPERTY_BINARY_NAME,
                                   is );
            return this;
        } catch ( RepositoryException e ) {
            log.error( "Unable to update the assets binary content",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * Optionally set the filename to be associated with the binary content.
     */
    public void updateBinaryContentAttachmentFileName(String name) {
        updateStringProperty( name,
                              CONTENT_PROPERTY_ATTACHMENT_FILENAME );
    }

    /**
     * This updates a user defined property (not one of the intrinsic ones).
     */
    public void updateUserProperty(String propertyName,
                                   String value) {
        if ( propertyName.startsWith( "drools:" ) ) {
            throw new IllegalArgumentException( "Can only set the pre defined fields using the appropriate methods." );
        }
        updateStringProperty( value,
                              propertyName );

    }

    /**
     * Nicely formats the information contained by the node that this object
     * encapsulates
     */
    public String toString() {
        try {
            StringBuilder returnString = new StringBuilder();
            returnString.append( "Content of rule item named '" ).append( this.getName() ).append( "':\n" );
            returnString.append( "Content: " ).append( this.getContent() ).append( "\n" );
            returnString.append( "------\n" );

            returnString.append( "Archived: " ).append( this.isArchived() ).append( "\n" );
            returnString.append( "------\n" );

            returnString.append( "Date Effective: " ).append( this.getDateEffective() ).append( "\n" );
            returnString.append( "Date Expired: " ).append( this.getDateExpired() ).append( "\n" );
            returnString.append( "------\n" );

            returnString.append( "Rule state: " );
            StateItem stateItem = this.getState();
            if ( stateItem != null ) {
                returnString.append( this.getState().getName() ).append( "\n" );
            } else {
                returnString.append( "NO STATE SET FOR THIS NODE\n" );
            }
            returnString.append( "------\n" );

            returnString.append( "Rule tags:\n" );
            for ( Iterator it = this.getCategories().iterator(); it.hasNext(); ) {
                CategoryItem currentTag = (CategoryItem) it.next();
                returnString.append( currentTag.getName() ).append( "\n" );
            }
            returnString.append( "--------------\n" );
            return returnString.toString();
        } catch ( Exception e ) {
            throw new RulesRepositoryException( e );
        }
    }

    public VersionableItem getPrecedingVersion() throws RulesRepositoryException {
        try {
            Node precedingVersionNode = this.getPrecedingVersionNode();
            if ( precedingVersionNode != null ) {
                return new AssetItem( this.rulesRepository,
                                      precedingVersionNode );
            } else {
                return null;
            }
        } catch ( Exception e ) {
            log.error( "Caught exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    public VersionableItem getSucceedingVersion() throws RulesRepositoryException {
        try {
            Node succeedingVersionNode = this.getSucceedingVersionNode();
            if ( succeedingVersionNode != null ) {
                return new AssetItem( this.rulesRepository,
                                      succeedingVersionNode );
            } else {
                return null;
            }
        } catch ( Exception e ) {
            log.error( "Caught exception",
                       e );
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * Get the name of the enclosing package. As assets are stored in
     * versionable subfolders, this means walking up 2 levels in the hierarchy
     * to get to the enclosing "package" node.
     */
    public String getPackageName() {
        return super.getStringProperty( PACKAGE_NAME_PROPERTY );
    }

    /**
     * @return A property value (for a user defined property).
     */
    public String getUserProperty(String property) {
        return getStringProperty( property );
    }

    /**
     * This will remove the item. The repository will need to be saved for this
     * to take effect. Typically the package that contains this should be
     * versioned before removing this, to make it easy to roll back.
     */
    public void remove() {

        if ( StorageEventManager.hasSaveEvent() ) {
            StorageEventManager.getSaveEvent().onAssetDelete( this );
        }

        checkIsUpdateable();
        if ( this.getDateExpired() != null ) {
            if ( Calendar.getInstance().before( this.getDateExpired() ) ) {
                throw new RulesRepositoryException( "Can't delete an item before its expiry date." );
            }
        }
        try {
            this.node.remove();
        } catch ( RepositoryException e ) {
            throw new RulesRepositoryException( e );
        }
    }

    /**
     *
     * @return An iterator over the nodes history.
     */
    public AssetHistoryIterator getHistory() {
        return new AssetHistoryIterator( this.rulesRepository,
                                         this.node );
    }

    /**
     * This will get the package an asset item belongs to.
     */
    public PackageItem getPackage() {

        try {
            if ( this.isHistoricalVersion() ) {
                return this.rulesRepository.loadPackage( this.getPackageName() );
            }
            return new PackageItem( this.rulesRepository,
                                    this.node.getParent().getParent() );
        } catch ( RepositoryException e ) {
            throw new RulesRepositoryException( e );
        }
    }

    /**
     * This converts a "filename" to an asset name.
     *
     * File name is foo.drl -> ["foo", "drl"]
     *
     * @param fileName
     * @return
     */
    public static String[] getAssetNameFromFileName(String fileName) {

        String[] r = new String[]{"", ""};
        if ( !fileName.contains( "." ) ) {
            r[0] = fileName;
        } else if ( fileName.endsWith( ".bpel.jar" ) ) {
            r[0] = fileName.substring( 0,
                                       fileName.lastIndexOf( ".bpel.jar" ) );
            r[1] = "bpel.jar";
        } else if ( fileName.endsWith( ".model.drl" ) ) {
            r[0] = fileName.substring( 0,
                                       fileName.lastIndexOf( ".model.drl" ) );
            r[1] = "model.drl";
        } else {
            r[0] = fileName.substring( 0,
                                       fileName.lastIndexOf( "." ) );
            r[1] = fileName.substring( fileName.lastIndexOf( "." ) + 1 );

        }
        return r;

    }

}
TOP

Related Classes of org.drools.repository.AssetItem

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.